From 821d4409b519c6c9eb36ea42ee1f3116d1494b83 Mon Sep 17 00:00:00 2001 From: Pedro Amorim Date: Thu, 30 Mar 2023 12:07:05 +0200 Subject: [PATCH] Bug 22440: Tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updated API tests Co-authored-by: Tomás Cohen Arazi Signed-off-by: Martin Renvoize --- t/db_dependent/api/v1/ill_backends.t | 214 +++++++++++++++++++++++ t/db_dependent/api/v1/ill_requests.t | 237 +++++++++++++++++++++++++ t/db_dependent/api/v1/illrequests.t | 248 --------------------------- 3 files changed, 451 insertions(+), 248 deletions(-) create mode 100755 t/db_dependent/api/v1/ill_backends.t create mode 100755 t/db_dependent/api/v1/ill_requests.t delete mode 100755 t/db_dependent/api/v1/illrequests.t diff --git a/t/db_dependent/api/v1/ill_backends.t b/t/db_dependent/api/v1/ill_backends.t new file mode 100755 index 0000000000..704fca4432 --- /dev/null +++ b/t/db_dependent/api/v1/ill_backends.t @@ -0,0 +1,214 @@ +#!/usr/bin/env perl + +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# Koha is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Koha; if not, see . + +use Modern::Perl; + +use Test::More tests => 1; + +use Test::MockModule; +use Test::MockObject; +use Test::Mojo; + +use t::lib::TestBuilder; +use t::lib::Mocks; + +use Koha::AuthorisedValueCategories; +use Koha::Illrequests; + +my $schema = Koha::Database->new->schema; +my $builder = t::lib::TestBuilder->new; + +t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 ); + +my $t = Test::Mojo->new('Koha::REST::V1'); + +subtest 'list() tests' => sub { + + plan tests => 16; + + # Mock Illrequest::Config (as module) + my $illconfig_module = Test::MockModule->new('Koha::Illrequest::Config'); + + # Start with no backends installed + $illconfig_module->mock( 'available_backends', sub { () } ); + + # Mock ILLBackend (as object) + my $backend = Test::MockObject->new; + $backend->set_isa('Koha::Illbackends::Mock'); + $backend->set_always( 'name', 'Mock' ); + $backend->set_always( 'capabilities', sub { return 'bar'; } ); + $backend->mock( + 'metadata', + sub { + my ( $self, $rq ) = @_; + return { + ID => $rq->illrequest_id, + Title => $rq->patron->borrowernumber + }; + } + ); + + #Add a backend-specific status + $backend->mock( + 'status_graph', + sub { + return { + READY => { + prev_actions => [ 'NEW', 'ERROR' ], + id => 'READY', + name => 'Request ready', + ui_method_name => 'Mark request as ready', + method => 'ready', + next_actions => [], + ui_method_icon => 'fa-check', + } + }; + } + ); + + # Mock Koha::Illrequest::load_backend (to load Mocked Backend) + my $illreqmodule = Test::MockModule->new('Koha::Illrequest'); + $illreqmodule->mock( 'load_backend', + sub { my $self = shift; $self->{_my_backend} = $backend; return $self } + ); + + $schema->storage->txn_begin; + + Koha::Illrequests->search->delete; + + # create an authorized user + my $librarian = $builder->build_object( + { + class => 'Koha::Patrons', + value => { flags => 2**22 } # 22 => ill + } + ); + my $password = 'thePassword123'; + $librarian->set_password( { password => $password, skip_validation => 1 } ); + my $userid = $librarian->userid; + + # create an unauthorized user + my $patron = $builder->build_object( + { + class => 'Koha::Patrons', + value => { flags => 0 } + } + ); + + $patron->set_password( { password => $password, skip_validation => 1 } ); + my $unauth_userid = $patron->userid; + + # Make sure the ILL_STATUS_ALIAS authorised value category is defined + unless ( + Koha::AuthorisedValueCategories->search( + { category_name => 'ILL_STATUS_ALIAS' } + )->count > 0 + ) + { + $builder->build_object( + { + class => 'Koha::AuthorisedValueCategories', + value => { category_name => 'ILL_STATUS_ALIAS' } + } + ); + } + + my $tag = "Print copy"; + my $av_code = "print_copy"; + my $av = $builder->build_object( + { + class => 'Koha::AuthorisedValues', + value => { + category => 'ILL_STATUS_ALIAS', + authorised_value => $av_code, + lib => $tag, + } + } + ); + + # No backends, expect empty + $t->get_ok("//$userid:$password@/api/v1/ill/backends")->status_is(200) + ->json_is( [] ); + + # Mock one existing backend + $illconfig_module->mock( 'available_backends', sub { ["Mock"] } ); + + #One backend exists, expect that + $t->get_ok("//$userid:$password@/api/v1/ill/backends")->status_is(200) + ->json_has( '/0/ill_backend_id', 'Mock' ); + + # Prepare status + my $backend_status = { + code => "READY", + str => "Request ready" + }; + my $core_status = { + code => "COMP", + str => "Completed" + }; + + my $alias_status = { + code => $av_code, + str => $tag, + }; + + # Create some ILL requests + my $backend_status_req = $builder->build_object( + { + class => 'Koha::Illrequests', + value => + { status => $backend_status->{code}, backend => $backend->name } + } + ); + my $core_status_req = $builder->build_object( + { + class => 'Koha::Illrequests', + value => + { status => $core_status->{code}, backend => $backend->name } + } + ); + my $alias_status_req = $builder->build_object( + { + class => 'Koha::Illrequests', + value => { + status => $core_status->{code}, + backend => $backend->name, + status_alias => $av->authorised_value + } + } + ); + + #Check for backend existing statuses + $t->get_ok("//$userid:$password@/api/v1/ill/backends/Mock/statuses") + ->status_is(200) + ->json_is( [ $backend_status, $core_status, $alias_status ] ); + + #Check for backend existing statuses of a backend that doesn't exist + $t->get_ok("//$userid:$password@/api/v1/ill/backends/GhostBackend/statuses") + ->status_is(200) + ->json_is( [] ); + + # Unauthorized attempt to list + $t->get_ok("//$unauth_userid:$password@/api/v1/ill/backends") + ->status_is(403); + + # DELETE method not supported + $t->delete_ok("//$unauth_userid:$password@/api/v1/ill/backends") + ->status_is(404); + + $schema->storage->txn_rollback; +}; diff --git a/t/db_dependent/api/v1/ill_requests.t b/t/db_dependent/api/v1/ill_requests.t new file mode 100755 index 0000000000..dc3974e5d3 --- /dev/null +++ b/t/db_dependent/api/v1/ill_requests.t @@ -0,0 +1,237 @@ +#!/usr/bin/env perl + +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# Koha is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Koha; if not, see . + +use Modern::Perl; + +use Test::More tests => 1; + +use Test::MockModule; +use Test::MockObject; +use Test::Mojo; + +use JSON qw(encode_json); + +use t::lib::TestBuilder; +use t::lib::Mocks; + +use Koha::AuthorisedValueCategories; +use Koha::Illrequests; +use Koha::DateUtils qw( format_sqldatetime ); + +my $schema = Koha::Database->new->schema; +my $builder = t::lib::TestBuilder->new; + +t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 ); + +my $t = Test::Mojo->new('Koha::REST::V1'); + +subtest 'list() tests' => sub { + + plan tests => 34; + + # Mock ILLBackend (as object) + my $backend = Test::MockObject->new; + $backend->set_isa('Koha::Illbackends::Mock'); + $backend->set_always('name', 'Mock'); + $backend->set_always('capabilities', sub { return 'bar'; } ); + $backend->mock( + 'metadata', + sub { + my ( $self, $rq ) = @_; + return { + ID => $rq->illrequest_id, + Title => $rq->patron->borrowernumber + } + } + ); + $backend->mock( + 'status_graph', sub {}, + ); + + # Mock Koha::Illrequest::load_backend (to load Mocked Backend) + my $illreqmodule = Test::MockModule->new('Koha::Illrequest'); + $illreqmodule->mock( 'load_backend', + sub { my $self = shift; $self->{_my_backend} = $backend; return $self } + ); + + $schema->storage->txn_begin; + + Koha::Illrequests->search->delete; + + # create an authorized user + my $librarian = $builder->build_object( + { + class => 'Koha::Patrons', + value => { flags => 2 ** 22 } # 22 => ill + } + ); + my $password = 'thePassword123'; + $librarian->set_password( { password => $password, skip_validation => 1 } ); + my $userid = $librarian->userid; + + # create an unauthorized user + my $patron = $builder->build_object( + { + class => 'Koha::Patrons', + value => { flags => 0 } + } + ); + + $patron->set_password( { password => $password, skip_validation => 1 } ); + my $unauth_userid = $patron->userid; + + # Make sure the ILL_STATUS_ALIAS authorised value category is defined + unless ( Koha::AuthorisedValueCategories->search( { category_name => 'ILL_STATUS_ALIAS' } )->count > 0 ) { + $builder->build_object( + { class => 'Koha::AuthorisedValueCategories', value => { category_name => 'ILL_STATUS_ALIAS' } } ); + } + + my $tag = "Print copy"; + my $av_code = "print_copy"; + my $av = $builder->build_object( + { class => 'Koha::AuthorisedValues', + value => { + category => 'ILL_STATUS_ALIAS', + authorised_value => $av_code, + lib => $tag, + } + } + ); + + # No requests, expect empty + $t->get_ok("//$userid:$password@/api/v1/ill/requests") + ->status_is(200) + ->json_is( [] ); + + + # Prepare some expected response structure + my $request_status = { + code =>"REQ", + str =>"Requested" + }; + + my $response_status = { + backend => $backend->name, + code =>$request_status->{code}, + str =>$request_status->{str}, + type =>"ill_status" + }; + + my $response_status_av = { + category => "ILL_STATUS_ALIAS", + code => $av_code, + str => $tag, + type => "av" + }; + + # Create some ILL requests + my $req_1 = $builder->build_object({ class => 'Koha::Illrequests', value => { borrowernumber => $patron->borrowernumber, status => $request_status->{code}, backend =>$backend->name } }); + my $req_2 = $builder->build_object({ class => 'Koha::Illrequests', value => { status => $request_status->{code}, backend =>$backend->name , status_alias => $av->authorised_value } } ); + my $ret = $builder->build_object({ class => 'Koha::Illrequests', value => { status => 'RET' } } ); + + # Three requests exist, expect all three to be returned + $t->get_ok("//$userid:$password@/api/v1/ill/requests") + ->status_is(200) + ->json_is( [ $req_1->to_api, $req_2->to_api, $ret->to_api ]); + + my $status_query = encode_json({ status => 'REQ' }); + my $status_alias_query = encode_json({ status_av => $av_code }); + + # x-koha-embed: +strings + # Two requests exist with status 'REQ', expect them to be returned + # One of which also has a status_alias, expect that to be in that request's body + $t->get_ok("//$userid:$password@/api/v1/ill/requests?q=$status_query" => {"x-koha-embed" => "+strings"} ) + ->status_is(200) + ->json_is( [ + { _strings => { status => $response_status }, %{$req_1->to_api} }, + { _strings => { status => $response_status, status_av => $response_status_av }, %{$req_2->to_api} } + ] + ); + + # One request with status_alias 'print_copy' exists, expect that to be returned + $t->get_ok("//$userid:$password@/api/v1/ill/requests?q=$status_alias_query" => {"x-koha-embed" => "+strings"} ) + ->status_is(200) + ->json_is( [ + { _strings => { status => $response_status, status_av => $response_status_av }, %{$req_2->to_api} } + ] + ); + + # x-koha-embed: patron + my $patron_query = encode_json({ borrowernumber => $patron->borrowernumber }); + + # One request related to $patron, make sure it comes back + $t->get_ok("//$userid:$password@/api/v1/ill/requests" => {"x-koha-embed" => "patron"} ) + ->status_is(200) + ->json_has('/0/patron', $patron->to_api); + + # x-koha-embed: comments + # Create comment + my $comment_text = "This is the comment"; + my $comment = $builder->build_object({ class => 'Koha::Illcomments', value => { illrequest_id => $req_1->illrequest_id, comment => $comment_text , borrowernumber => $patron->borrowernumber } } ); + + # Make sure comments come back + $t->get_ok("//$userid:$password@/api/v1/ill/requests" => {"x-koha-embed" => "comments"} ) + ->status_is(200) + ->json_has('/0/comments', $comment_text); + + # x-koha-embed: id_prefix + # Mock Illrequest::Config to return a static prefix + my $id_prefix = 'ILL'; + my $config = Test::MockObject->new; + $config->set_isa('Koha::Illrequest::Config::Mock'); + $config->set_always('getPrefixes', $id_prefix); + + # Make sure id_prefix comes back + $t->get_ok("//$userid:$password@/api/v1/ill/requests" => {"x-koha-embed" => "id_prefix"} ) + ->status_is(200) + ->json_has('/0/id_prefix', $id_prefix); + + # ILLHiddenRequestStatuses syspref + # Hide 'REQ', expect to return just 1 'RET' + t::lib::Mocks::mock_preference( 'ILLHiddenRequestStatuses', 'REQ' ); + $t->get_ok( "//$userid:$password@/api/v1/ill/requests" ) + ->status_is(200) + ->json_is( [ $ret->to_api ] ); + + # Hide 'RET', expect to return 2 'REQ' + t::lib::Mocks::mock_preference( 'ILLHiddenRequestStatuses', 'RET' ); + $t->get_ok( "//$userid:$password@/api/v1/ill/requests" ) + ->status_is(200) + ->json_is( [ $req_1->to_api, $req_2->to_api ]); + + # Status code + # Warn on unsupported query parameter + $t->get_ok( "//$userid:$password@/api/v1/ill/requests?request_blah=blah" ) + ->status_is(400) + ->json_is( + [{ path => '/query/request_blah', message => 'Malformed query string'}] + ); + + # Unauthorized attempt to list + $t->get_ok( + "//$unauth_userid:$password@/api/v1/ill/requests") + ->status_is(403); + + # DELETE method not supported + $t->delete_ok( + "//$unauth_userid:$password@/api/v1/ill/requests/1") + ->status_is(404); + + #TODO; test complex query on extended_attributes + + $schema->storage->txn_rollback; +}; diff --git a/t/db_dependent/api/v1/illrequests.t b/t/db_dependent/api/v1/illrequests.t deleted file mode 100755 index 0b4cd312bf..0000000000 --- a/t/db_dependent/api/v1/illrequests.t +++ /dev/null @@ -1,248 +0,0 @@ -#!/usr/bin/env perl - -# This file is part of Koha. -# -# Koha is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# Koha is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Koha; if not, see . - -use Modern::Perl; - -use Test::More tests => 2; - -use Test::MockModule; -use Test::MockObject; -use Test::Mojo; - -use JSON qw(encode_json); - -use t::lib::TestBuilder; -use t::lib::Mocks; - -use Koha::Illrequests; -use Koha::DateUtils qw( format_sqldatetime ); - -my $schema = Koha::Database->new->schema; -my $builder = t::lib::TestBuilder->new; - -t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 ); - -my $t = Test::Mojo->new('Koha::REST::V1'); - -subtest 'list_legacy() tests' => sub { - - plan tests => 30; - - # Mock ILLBackend (as object) - my $backend = Test::MockObject->new; - $backend->set_isa('Koha::Illbackends::Mock'); - $backend->set_always('name', 'Mock'); - $backend->set_always('capabilities', sub { return 'bar'; } ); - $backend->mock( - 'metadata', - sub { - my ( $self, $rq ) = @_; - return { - ID => $rq->illrequest_id, - Title => $rq->patron->borrowernumber - } - } - ); - $backend->mock( - 'status_graph', sub {}, - ); - - # Mock Koha::Illrequest::load_backend (to load Mocked Backend) - my $illreqmodule = Test::MockModule->new('Koha::Illrequest'); - $illreqmodule->mock( 'load_backend', - sub { my $self = shift; $self->{_my_backend} = $backend; return $self } - ); - - $schema->storage->txn_begin; - - Koha::Illrequests->search->delete; - - # create an authorized user - my $patron = $builder->build_object({ - class => 'Koha::Patrons', - value => { flags => 2 ** 22 } # 22 => ill - }); - my $password = 'thePassword123'; - $patron->set_password({ password => $password, skip_validation => 1 }); - my $userid = $patron->userid; - - ## Authorized user tests - # No requests, so empty array should be returned - $t->get_ok( "//$userid:$password@/api/v1/illrequests" ) - ->status_is(200) - ->json_is( [] ); - - my $library = $builder->build_object( { class => 'Koha::Libraries' } ); - my $patron_1 = $builder->build_object( { class => 'Koha::Patrons' } ); - my $patron_2 = $builder->build_object( { class => 'Koha::Patrons' } ); - - # Create an ILL request - my $illrequest = $builder->build_object( - { - class => 'Koha::Illrequests', - value => { - backend => 'Mock', - biblio_id => undef, - branchcode => $library->branchcode, - borrowernumber => $patron_1->borrowernumber, - status => 'STATUS1', - } - } - ); - - # The api response is always augmented with the id_prefix - my $response = $illrequest->unblessed; - $response->{id_prefix} = $illrequest->id_prefix; - - my $req_formatted = add_formatted($response); - - # One illrequest created, should get returned - $t->get_ok( "//$userid:$password@/api/v1/illrequests" ) - ->status_is(200) - ->json_is( [ $req_formatted ] ); - - # One illrequest created, returned with augmented data - $t->get_ok( "//$userid:$password@/api/v1/illrequests?embed=patron,library,capabilities,metadata,requested_partners" ) - ->status_is(200) - ->json_has( '/0/patron', 'patron embedded' ) - ->json_is( '/0/patron/patron_id', $patron_1->borrowernumber, 'The right patron is embeded') - ->json_has( '/0/requested_partners', 'requested_partners embedded' ) - ->json_has( '/0/capabilities', 'capabilities embedded' ) - ->json_has( '/0/library', 'library embedded' ) - ->json_has( '/0/metadata', 'metadata embedded' ) - ->json_hasnt( '/1', 'Only one request was created' ); - - # Create another ILL request - my $illrequest2 = $builder->build_object( - { - class => 'Koha::Illrequests', - value => { - backend => 'Mock', - biblio_id => undef, - branchcode => $library->branchcode, - borrowernumber => $patron_2->borrowernumber, - status => 'STATUS2', - } - } - ); - - # The api response is always augmented with the id_prefix - my $response2 = $illrequest2->unblessed; - $response2->{id_prefix} = $illrequest2->id_prefix; - - my $req2_formatted = add_formatted($response2); - - # Two illrequest created, should get returned - $t->get_ok( "//$userid:$password@/api/v1/illrequests" ) - ->status_is(200) - ->json_is( [ $req_formatted, $req2_formatted ] ); - - # Warn on unsupported query parameter - $t->get_ok( "//$userid:$password@/api/v1/illrequests?request_blah=blah" ) - ->status_is(400) - ->json_is( - [{ path => '/query/request_blah', message => 'Malformed query string'}] - ); - - # Test the borrowernumber parameter - $t->get_ok( "//$userid:$password@/api/v1/illrequests?borrowernumber=" . $patron_2->borrowernumber ) - ->status_is(200) - ->json_is( [ $response2 ] ); - - # Test the ILLHiddenRequestStatuses syspref - t::lib::Mocks::mock_preference( 'ILLHiddenRequestStatuses', 'STATUS1' ); - $t->get_ok( "//$userid:$password@/api/v1/illrequests" ) - ->status_is(200) - ->json_is( [ $req2_formatted ] ); - - t::lib::Mocks::mock_preference( 'ILLHiddenRequestStatuses', 'STATUS2' ); - $t->get_ok( "//$userid:$password@/api/v1/illrequests" ) - ->status_is(200) - ->json_is( [ $req_formatted ] ); - - $schema->storage->txn_rollback; -}; - -subtest 'list() tests' => sub { - - plan tests => 9; - - $schema->storage->txn_begin; - - Koha::Illrequests->search->delete; - - my $librarian = $builder->build_object( - { - class => 'Koha::Patrons', - value => { flags => 2 ** 22 } # 22 => ill - } - ); - my $password = 'thePassword123'; - $librarian->set_password( { password => $password, skip_validation => 1 } ); - my $userid = $librarian->userid; - - my $patron = $builder->build_object( - { - class => 'Koha::Patrons', - value => { flags => 0 } - } - ); - - $patron->set_password( { password => $password, skip_validation => 1 } ); - my $unauth_userid = $patron->userid; - - $t->get_ok("//$userid:$password@/api/v1/ill_requests") - ->status_is(200) - ->json_is( [] ); - - my $req_1 = $builder->build_object({ class => 'Koha::Illrequests', value => { biblio_id => undef, status => 'REQ' } }); - my $req_2 = $builder->build_object({ class => 'Koha::Illrequests', value => { biblio_id => undef, status => 'REQ' } } ); - my $ret = $builder->build_object({ class => 'Koha::Illrequests', value => { biblio_id => undef, status => 'RET' } } ); - - $t->get_ok("//$userid:$password@/api/v1/ill_requests") - ->status_is(200) - ->json_is( [ $req_1->to_api, $req_2->to_api, $ret->to_api ]); - - my $query = encode_json({ status => 'REQ' }); - - # Filtering works - $t->get_ok("//$userid:$password@/api/v1/ill_requests?q=$query" ) - ->status_is(200) - ->json_is( [ $req_1->to_api, $req_2->to_api ]); - - $schema->storage->txn_rollback; -}; - -sub add_formatted { - my $req = shift; - my @format_dates = ( 'placed', 'updated', 'completed' ); - # We need to embellish the request with properties that the API - # controller calculates on the fly - # Create new "formatted" columns for each date column - # that needs formatting - foreach my $field(@format_dates) { - if (defined $req->{$field}) { - $req->{$field . "_formatted"} = format_sqldatetime( - $req->{$field}, - undef, - undef, - 1 - ); - } - } - return $req; -} -- 2.40.1