3 # This file is part of Koha.
5 # Koha is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
10 # Koha is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with Koha; if not, see <http://www.gnu.org/licenses>.
20 use Test::More tests => 5;
26 use t::lib::TestBuilder;
32 my $schema = Koha::Database->new->schema;
33 my $builder = t::lib::TestBuilder->new;
35 t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 );
37 my $t = Test::Mojo->new('Koha::REST::V1');
39 subtest 'get() tests' => sub {
43 $schema->storage->txn_begin;
45 my $patron = $builder->build_object(
47 class => 'Koha::Patrons',
48 value => { flags => 0 }
51 my $password = 'thePassword123';
52 $patron->set_password( { password => $password, skip_validation => 1 } );
53 $patron->discard_changes;
54 my $userid = $patron->userid;
56 my $biblio = $builder->build_sample_biblio({
57 title => 'The unbearable lightness of being',
58 author => 'Milan Kundera'
60 $t->get_ok("//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber)
63 $patron->flags(4)->store;
65 $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber
66 => { Accept => 'application/weird+format' } )
68 ->json_is( [ "application/json",
69 "application/marcxml+xml",
70 "application/marc-in-json",
74 $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber
75 => { Accept => 'application/json' } )
77 ->json_is( '/title', 'The unbearable lightness of being' )
78 ->json_is( '/author', 'Milan Kundera' );
80 $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber
81 => { Accept => 'application/marcxml+xml' } )
84 $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber
85 => { Accept => 'application/marc-in-json' } )
88 $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber
89 => { Accept => 'application/marc' } )
92 $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber
93 => { Accept => 'text/plain' } )
95 ->content_is($biblio->metadata->record->as_formatted);
98 $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber
99 => { Accept => 'application/marc' } )
101 ->json_is( '/error', 'Object not found.' );
103 $schema->storage->txn_rollback;
106 subtest 'get_items() tests' => sub {
110 $schema->storage->txn_begin;
112 my $patron = $builder->build_object(
114 class => 'Koha::Patrons',
115 value => { flags => 0 }
118 my $password = 'thePassword123';
119 $patron->set_password( { password => $password, skip_validation => 1 } );
120 $patron->discard_changes;
121 my $userid = $patron->userid;
123 my $biblio = $builder->build_sample_biblio();
124 $t->get_ok("//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/items")
127 $patron->flags(4)->store;
129 $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/items")
131 ->json_is( '' => [], 'No items on the biblio' );
133 my $item_1 = $builder->build_sample_item({ biblionumber => $biblio->biblionumber });
134 my $item_2 = $builder->build_sample_item({ biblionumber => $biblio->biblionumber });
136 $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/items")
138 ->json_is( '' => [ $item_1->to_api, $item_2->to_api ], 'The items are returned' );
140 $schema->storage->txn_rollback;
143 subtest 'delete() tests' => sub {
147 $schema->storage->txn_begin;
149 my $patron = $builder->build_object(
151 class => 'Koha::Patrons',
152 value => { flags => 0 } # no permissions
155 my $password = 'thePassword123';
156 $patron->set_password( { password => $password, skip_validation => 1 } );
157 my $userid = $patron->userid;
159 my $item = $builder->build_sample_item();
160 my $biblio_id = $item->biblionumber;
162 $t->delete_ok("//$userid:$password@/api/v1/biblios/$biblio_id")
163 ->status_is(403, 'Not enough permissions makes it return the right code');
168 source => 'UserPermission',
170 borrowernumber => $patron->borrowernumber,
172 code => 'edit_catalogue'
178 # Bibs with items cannot be deleted
179 $t->delete_ok("//$userid:$password@/api/v1/biblios/$biblio_id")
184 # Bibs with no items can be deleted
185 $t->delete_ok("//$userid:$password@/api/v1/biblios/$biblio_id")
186 ->status_is(204, 'SWAGGER3.2.4')
187 ->content_is('', 'SWAGGER3.3.4');
189 $t->delete_ok("//$userid:$password@/api/v1/biblios/$biblio_id")
192 $schema->storage->txn_rollback;
195 subtest 'get_public() tests' => sub {
199 $schema->storage->txn_begin;
201 my $category = $builder->build_object({ class => 'Koha::Patron::Categories' });
202 my $patron = $builder->build_object(
204 class => 'Koha::Patrons',
206 flags => undef, # opac user
207 categorycode => $category->categorycode
211 my $password = 'thePassword123';
212 $patron->set_password( { password => $password, skip_validation => 1 } );
213 $patron->discard_changes;
214 my $userid = $patron->userid;
216 my $biblio = $builder->build_sample_biblio({
217 title => 'The unbearable lightness of being',
218 author => 'Milan Kundera'
221 # Make sure author in shown in the OPAC
222 my $subfields = Koha::MarcSubfieldStructures->search({ tagfield => '100' });
223 while ( my $subfield = $subfields->next ) {
224 $subfield->set({ hidden => -1 })->store;
226 Koha::Caches->get_instance()->flush_all;
228 $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber
229 => { Accept => 'application/weird+format' } )
231 ->json_is( [ "application/marcxml+xml",
232 "application/marc-in-json",
236 $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber
237 => { Accept => 'text/plain' } )
239 ->content_like( qr{100\s+_aMilan Kundera} )
240 ->content_like( qr{245\s+_aThe unbearable lightness of being} );
242 $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber
243 => { Accept => 'application/marcxml+xml' } )
246 $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber
247 => { Accept => 'application/marc-in-json' } )
250 $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber
251 => { Accept => 'application/marc' } )
254 $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber
255 => { Accept => 'text/plain' } )
257 ->content_is($biblio->metadata->record->as_formatted);
259 subtest 'anonymous access' => sub {
262 $t->get_ok( "/api/v1/public/biblios/" . $biblio->biblionumber
263 => { Accept => 'application/marcxml+xml' } )
266 $t->get_ok( "/api/v1/public/biblios/" . $biblio->biblionumber
267 => { Accept => 'application/marc-in-json' } )
270 $t->get_ok( "/api/v1/public/biblios/" . $biblio->biblionumber
271 => { Accept => 'application/marc' } )
274 $t->get_ok( "/api/v1/public/biblios/" . $biblio->biblionumber
275 => { Accept => 'text/plain' } )
277 ->content_is($biblio->metadata->record->as_formatted);
280 # Hide author in OPAC
281 $subfields = Koha::MarcSubfieldStructures->search({ tagfield => '100' });
282 while ( my $subfield = $subfields->next ) {
283 $subfield->set({ hidden => 1 })->store;
286 Koha::Caches->get_instance()->flush_all;
288 $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber
289 => { Accept => 'text/plain' } )
291 ->content_unlike( qr{100\s+_aMilan Kundera} )
292 ->content_like( qr{245\s+_aThe unbearable lightness of being} );
294 subtest 'hidden_in_opac tests' => sub {
298 my $biblio_hidden_in_opac = 1;
300 my $biblio_class = Test::MockModule->new('Koha::Biblio');
301 # force biblio hidden in OPAC
302 $biblio_class->mock( 'hidden_in_opac', sub { return $biblio_hidden_in_opac; } );
304 $t->get_ok( "/api/v1/public/biblios/" . $biblio->biblionumber
305 => { Accept => 'text/plain' } )
306 ->status_is(404, 'hidden_in_opac + anonymous => hidden');
308 my $category_override_hidden_items = 0;
309 my $category_class = Test::MockModule->new('Koha::Patron::Category');
310 $category_class->mock( 'override_hidden_items', sub { return $category_override_hidden_items; } );
311 $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber
312 => { Accept => 'text/plain' } )
313 ->status_is(404, "hidden_in_opac + patron whose category doesn't override => hidden");
315 # Make the category override
316 $category_override_hidden_items = 1;
317 $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber
318 => { Accept => 'text/plain' } )
319 ->status_is(200, "hidden_in_opac + patron whose category that overrides => displayed");
321 t::lib::Mocks::mock_preference('OpacHiddenItems');
325 $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber
326 => { Accept => 'application/marc' } )
328 ->json_is( '/error', 'Object not found.' );
330 $schema->storage->txn_rollback;
333 subtest 'pickup_locations() tests' => sub {
337 $schema->storage->txn_begin;
339 t::lib::Mocks::mock_preference( 'AllowHoldPolicyOverride', 0 );
341 # Small trick to ease testing
342 Koha::Libraries->search->update({ pickup_location => 0 });
344 my $library_1 = $builder->build_object({ class => 'Koha::Libraries', value => { marcorgcode => 'A', pickup_location => 1 } });
345 my $library_2 = $builder->build_object({ class => 'Koha::Libraries', value => { marcorgcode => 'B', pickup_location => 1 } });
346 my $library_3 = $builder->build_object({ class => 'Koha::Libraries', value => { marcorgcode => 'C', pickup_location => 1 } });
348 my $library_1_api = $library_1->to_api();
349 my $library_2_api = $library_2->to_api();
350 my $library_3_api = $library_3->to_api();
352 $library_1_api->{needs_override} = Mojo::JSON->false;
353 $library_2_api->{needs_override} = Mojo::JSON->false;
354 $library_3_api->{needs_override} = Mojo::JSON->true;
356 my $patron = $builder->build_object(
358 class => 'Koha::Patrons',
359 value => { userid => 'tomasito', flags => 0 }
362 my $password = 'thePassword123';
363 $patron->set_password( { password => $password, skip_validation => 1 } );
364 my $userid = $patron->userid;
367 source => 'UserPermission',
369 borrowernumber => $patron->borrowernumber,
371 code => 'place_holds',
376 my $biblio_class = Test::MockModule->new('Koha::Biblio');
380 my ( $self, $params ) = @_;
381 my $mock_patron = $params->{patron};
382 is( $mock_patron->borrowernumber,
383 $patron->borrowernumber, 'Patron passed correctly' );
384 return Koha::Libraries->search(
388 $library_1->branchcode,
389 $library_2->branchcode
393 { # we make sure no surprises in the order of the result
394 order_by => { '-asc' => 'marcorgcode' }
400 my $biblio = $builder->build_sample_biblio;
402 $t->get_ok( "//$userid:$password@/api/v1/biblios/"
404 . "/pickup_locations?patron_id=" . $patron->id )
405 ->json_is( [ $library_1_api, $library_2_api ] );
408 $t->get_ok( "//$userid:$password@/api/v1/biblios/"
410 . '/pickup_locations?'
411 . 'patron_id=' . $patron->id . '&q={"marc_org_code": { "-like": "A%" }}' )
412 ->json_is( [ $library_1_api ] );
414 t::lib::Mocks::mock_preference( 'AllowHoldPolicyOverride', 1 );
416 my $library_4 = $builder->build_object({ class => 'Koha::Libraries', value => { pickup_location => 0, marcorgcode => 'X' } });
417 my $library_5 = $builder->build_object({ class => 'Koha::Libraries', value => { pickup_location => 1, marcorgcode => 'Y' } });
419 my $library_5_api = $library_5->to_api();
420 $library_5_api->{needs_override} = Mojo::JSON->true;
422 $t->get_ok( "//$userid:$password@/api/v1/biblios/"
424 . "/pickup_locations?"
425 . "patron_id=" . $patron->id . "&_order_by=marc_org_code" )
426 ->json_is( [ $library_1_api, $library_2_api, $library_3_api, $library_5_api ] );
428 my $deleted_patron = $builder->build_object({ class => 'Koha::Patrons' });
429 my $deleted_patron_id = $deleted_patron->id;
430 $deleted_patron->delete;
432 $t->get_ok( "//$userid:$password@/api/v1/biblios/"
434 . "/pickup_locations?"
435 . "patron_id=" . $deleted_patron_id )
437 ->json_is( '/error' => 'Patron not found' );
441 $t->get_ok( "//$userid:$password@/api/v1/biblios/"
443 . "/pickup_locations?"
444 . "patron_id=" . $patron->id )
446 ->json_is( '/error' => 'Biblio not found' );
448 $schema->storage->txn_rollback;