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>.
23 use Test::More tests => 10;
29 use t::lib::TestBuilder;
32 use C4::Circulation qw( AddIssue AddReturn );
37 use Koha::Old::Checkouts;
39 my $schema = Koha::Database->new->schema;
40 my $builder = t::lib::TestBuilder->new;
42 t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 );
44 my $t = Test::Mojo->new('Koha::REST::V1');
46 subtest 'get() tests' => sub {
50 $schema->storage->txn_begin;
52 my $patron = $builder->build_object(
54 class => 'Koha::Patrons',
55 value => { flags => 0 }
58 my $password = 'thePassword123';
59 $patron->set_password( { password => $password, skip_validation => 1 } );
60 $patron->discard_changes;
61 my $userid = $patron->userid;
63 my $biblio = $builder->build_sample_biblio({
64 title => 'The unbearable lightness of being',
65 author => 'Milan Kundera'
67 $t->get_ok("//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber)
70 $patron->flags(4)->store;
72 $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber
73 => { Accept => 'application/weird+format' } )
76 $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber
77 => { Accept => 'application/json' } )
79 ->json_is( '/title', 'The unbearable lightness of being' )
80 ->json_is( '/author', 'Milan Kundera' );
82 $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber
83 => { Accept => 'application/marcxml+xml' } )
86 $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber
87 => { Accept => 'application/marc-in-json' } )
90 $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber
91 => { Accept => 'application/marc' } )
94 $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber
95 => { Accept => 'text/plain' } )
97 ->content_is($biblio->metadata->record->as_formatted);
100 $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber
101 => { Accept => 'application/marc' } )
103 ->json_is( '/error', 'Object not found.' );
105 subtest 'marc-in-json encoding tests' => sub {
109 my $title_with_diacritics = "L'insoutenable légèreté de l'être";
111 my $biblio = $builder->build_sample_biblio(
113 title => $title_with_diacritics,
114 author => "Milan Kundera"
118 my $result = $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber
119 => { Accept => 'application/marc-in-json' } )
120 ->status_is(200)->tx->res->body;
122 my $encoded_title = Encode::encode( "UTF-8", $title_with_diacritics );
124 like( $result, qr/\Q$encoded_title/, "The title is not double encoded" );
127 $schema->storage->txn_rollback;
130 subtest 'get_items() tests' => sub {
134 $schema->storage->txn_begin;
136 my $patron = $builder->build_object(
138 class => 'Koha::Patrons',
139 value => { flags => 0 }
142 my $password = 'thePassword123';
143 $patron->set_password( { password => $password, skip_validation => 1 } );
144 $patron->discard_changes;
145 my $userid = $patron->userid;
147 my $biblio = $builder->build_sample_biblio();
148 $t->get_ok("//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/items")
151 $patron->flags(4)->store;
153 $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/items")
155 ->json_is( '' => [], 'No items on the biblio' );
157 my $item_1 = $builder->build_sample_item({ biblionumber => $biblio->biblionumber });
158 my $item_2 = $builder->build_sample_item({ biblionumber => $biblio->biblionumber });
160 $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/items")
162 ->json_is( '' => [ $item_1->to_api, $item_2->to_api ], 'The items are returned' );
164 $schema->storage->txn_rollback;
167 subtest 'delete() tests' => sub {
171 $schema->storage->txn_begin;
173 my $patron = $builder->build_object(
175 class => 'Koha::Patrons',
176 value => { flags => 0 } # no permissions
179 my $password = 'thePassword123';
180 $patron->set_password( { password => $password, skip_validation => 1 } );
181 my $userid = $patron->userid;
183 my $item = $builder->build_sample_item();
184 my $biblio_id = $item->biblionumber;
186 $t->delete_ok("//$userid:$password@/api/v1/biblios/$biblio_id")
187 ->status_is(403, 'Not enough permissions makes it return the right code');
192 source => 'UserPermission',
194 borrowernumber => $patron->borrowernumber,
196 code => 'edit_catalogue'
202 # Bibs with items cannot be deleted
203 $t->delete_ok("//$userid:$password@/api/v1/biblios/$biblio_id")
208 # Bibs with no items can be deleted
209 $t->delete_ok("//$userid:$password@/api/v1/biblios/$biblio_id")
210 ->status_is(204, 'SWAGGER3.2.4')
211 ->content_is('', 'SWAGGER3.3.4');
213 $t->delete_ok("//$userid:$password@/api/v1/biblios/$biblio_id")
216 $schema->storage->txn_rollback;
219 subtest 'get_public() tests' => sub {
223 $schema->storage->txn_begin;
225 my $category = $builder->build_object({ class => 'Koha::Patron::Categories' });
226 my $patron = $builder->build_object(
228 class => 'Koha::Patrons',
230 flags => undef, # opac user
231 categorycode => $category->categorycode
235 my $password = 'thePassword123';
236 $patron->set_password( { password => $password, skip_validation => 1 } );
237 $patron->discard_changes;
238 my $userid = $patron->userid;
240 my $biblio = $builder->build_sample_biblio({
241 title => 'The unbearable lightness of being',
242 author => 'Milan Kundera'
245 # Make sure author in shown in the OPAC
246 my $subfields = Koha::MarcSubfieldStructures->search({ tagfield => '100' });
247 while ( my $subfield = $subfields->next ) {
248 $subfield->set({ hidden => -1 })->store;
250 Koha::Caches->get_instance()->flush_all;
252 $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber
253 => { Accept => 'application/weird+format' } )
256 $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber
257 => { Accept => 'text/plain' } )
259 ->content_like( qr{100\s+_aMilan Kundera} )
260 ->content_like( qr{245\s+_aThe unbearable lightness of being} );
262 $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber
263 => { Accept => 'application/marcxml+xml' } )
266 $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber
267 => { Accept => 'application/marc-in-json' } )
270 $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber
271 => { Accept => 'application/marc' } )
274 $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber
275 => { Accept => 'text/plain' } )
277 ->content_is($biblio->metadata->record->as_formatted);
279 subtest 'anonymous access' => sub {
282 $t->get_ok( "/api/v1/public/biblios/" . $biblio->biblionumber
283 => { Accept => 'application/marcxml+xml' } )
286 $t->get_ok( "/api/v1/public/biblios/" . $biblio->biblionumber
287 => { Accept => 'application/marc-in-json' } )
290 $t->get_ok( "/api/v1/public/biblios/" . $biblio->biblionumber
291 => { Accept => 'application/marc' } )
294 $t->get_ok( "/api/v1/public/biblios/" . $biblio->biblionumber
295 => { Accept => 'text/plain' } )
297 ->content_is($biblio->metadata->record->as_formatted);
300 subtest 'marc-in-json encoding tests' => sub {
304 my $title_with_diacritics = "L'insoutenable légèreté de l'être";
306 my $biblio = $builder->build_sample_biblio(
308 title => $title_with_diacritics,
309 author => "Milan Kundera"
313 my $result = $t->get_ok( "/api/v1/public/biblios/" . $biblio->biblionumber
314 => { Accept => 'application/marc-in-json' } )
315 ->status_is(200)->tx->res->body;
317 my $encoded_title = Encode::encode( "UTF-8", $title_with_diacritics );
319 like( $result, qr/\Q$encoded_title/, "The title is not double encoded" );
322 # Hide author in OPAC
323 $subfields = Koha::MarcSubfieldStructures->search({ tagfield => '100' });
324 while ( my $subfield = $subfields->next ) {
325 $subfield->set({ hidden => 1 })->store;
328 Koha::Caches->get_instance()->flush_all;
330 $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber
331 => { Accept => 'text/plain' } )
333 ->content_unlike( qr{100\s+_aMilan Kundera} )
334 ->content_like( qr{245\s+_aThe unbearable lightness of being} );
336 subtest 'hidden_in_opac tests' => sub {
340 my $biblio_hidden_in_opac = 1;
342 my $biblio_class = Test::MockModule->new('Koha::Biblio');
343 # force biblio hidden in OPAC
344 $biblio_class->mock( 'hidden_in_opac', sub { return $biblio_hidden_in_opac; } );
346 $t->get_ok( "/api/v1/public/biblios/" . $biblio->biblionumber
347 => { Accept => 'text/plain' } )
348 ->status_is(404, 'hidden_in_opac + anonymous => hidden');
350 my $category_override_hidden_items = 0;
351 my $category_class = Test::MockModule->new('Koha::Patron::Category');
352 $category_class->mock( 'override_hidden_items', sub { return $category_override_hidden_items; } );
353 $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber
354 => { Accept => 'text/plain' } )
355 ->status_is(404, "hidden_in_opac + patron whose category doesn't override => hidden");
357 # Make the category override
358 $category_override_hidden_items = 1;
359 $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber
360 => { Accept => 'text/plain' } )
361 ->status_is(200, "hidden_in_opac + patron whose category that overrides => displayed");
363 t::lib::Mocks::mock_preference('OpacHiddenItems');
367 $t->get_ok( "//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber
368 => { Accept => 'application/marc' } )
370 ->json_is( '/error', 'Object not found.' );
372 $schema->storage->txn_rollback;
375 subtest 'pickup_locations() tests' => sub {
379 $schema->storage->txn_begin;
381 t::lib::Mocks::mock_preference( 'AllowHoldPolicyOverride', 0 );
383 # Small trick to ease testing
384 Koha::Libraries->search->update({ pickup_location => 0 });
386 my $library_1 = $builder->build_object({ class => 'Koha::Libraries', value => { marcorgcode => 'A', pickup_location => 1 } });
387 my $library_2 = $builder->build_object({ class => 'Koha::Libraries', value => { marcorgcode => 'B', pickup_location => 1 } });
388 my $library_3 = $builder->build_object({ class => 'Koha::Libraries', value => { marcorgcode => 'C', pickup_location => 1 } });
390 my $library_1_api = $library_1->to_api();
391 my $library_2_api = $library_2->to_api();
392 my $library_3_api = $library_3->to_api();
394 $library_1_api->{needs_override} = Mojo::JSON->false;
395 $library_2_api->{needs_override} = Mojo::JSON->false;
396 $library_3_api->{needs_override} = Mojo::JSON->true;
398 my $patron = $builder->build_object(
400 class => 'Koha::Patrons',
401 value => { userid => 'tomasito', flags => 0 }
404 my $password = 'thePassword123';
405 $patron->set_password( { password => $password, skip_validation => 1 } );
406 my $userid = $patron->userid;
409 source => 'UserPermission',
411 borrowernumber => $patron->borrowernumber,
413 code => 'place_holds',
418 my $biblio_class = Test::MockModule->new('Koha::Biblio');
422 my ( $self, $params ) = @_;
423 my $mock_patron = $params->{patron};
424 is( $mock_patron->borrowernumber,
425 $patron->borrowernumber, 'Patron passed correctly' );
426 return Koha::Libraries->search(
430 $library_1->branchcode,
431 $library_2->branchcode
435 { # we make sure no surprises in the order of the result
436 order_by => { '-asc' => 'marcorgcode' }
442 my $biblio = $builder->build_sample_biblio;
444 $t->get_ok( "//$userid:$password@/api/v1/biblios/"
446 . "/pickup_locations?patron_id=" . $patron->id )
447 ->json_is( [ $library_1_api, $library_2_api ] );
450 $t->get_ok( "//$userid:$password@/api/v1/biblios/"
452 . '/pickup_locations?'
453 . 'patron_id=' . $patron->id . '&q={"marc_org_code": { "-like": "A%" }}' )
454 ->json_is( [ $library_1_api ] );
456 t::lib::Mocks::mock_preference( 'AllowHoldPolicyOverride', 1 );
458 my $library_4 = $builder->build_object({ class => 'Koha::Libraries', value => { pickup_location => 0, marcorgcode => 'X' } });
459 my $library_5 = $builder->build_object({ class => 'Koha::Libraries', value => { pickup_location => 1, marcorgcode => 'Y' } });
461 my $library_5_api = $library_5->to_api();
462 $library_5_api->{needs_override} = Mojo::JSON->true;
464 $t->get_ok( "//$userid:$password@/api/v1/biblios/"
466 . "/pickup_locations?"
467 . "patron_id=" . $patron->id . "&_order_by=marc_org_code" )
468 ->json_is( [ $library_1_api, $library_2_api, $library_3_api, $library_5_api ] );
470 subtest 'Pagination and AllowHoldPolicyOverride tests' => sub {
474 t::lib::Mocks::mock_preference( 'AllowHoldPolicyOverride', 1 );
476 $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->id . "/pickup_locations?" . "patron_id=" . $patron->id . "&_order_by=marc_org_code" . "&_per_page=1" )
477 ->json_is( [$library_1_api] )
478 ->header_is( 'X-Total-Count', '4', '4 is the count for libraries with pickup_location=1' )
479 ->header_is( 'X-Base-Total-Count', '4', '4 is the count for libraries with pickup_location=1' )
480 ->header_unlike( 'Link', qr|rel="prev"| )
481 ->header_like( 'Link', qr#(_per_page=1.*\&_page=2.*|_page=2.*\&_per_page=1.*)>\; rel="next"# )
482 ->header_like( 'Link', qr#(_per_page=1.*\&_page=1.*|_page=1.*\&_per_page=1).*>\; rel="first"# )
483 ->header_like( 'Link', qr#(_per_page=1.*\&_page=4.*|_page=4.*\&_per_page=1).*>\; rel="last"# );
485 $t->get_ok( "//$userid:$password@/api/v1/biblios/"
487 . "/pickup_locations?"
490 . "&_order_by=marc_org_code"
491 . "&_per_page=1&_page=3" ) # force the needs_override=1 check
492 ->json_is( [$library_3_api] )
493 ->header_is( 'X-Total-Count', '4', '4 is the count for libraries with pickup_location=1' )
494 ->header_is( 'X-Base-Total-Count', '4', '4 is the count for libraries with pickup_location=1' )
495 ->header_like( 'Link', qr#(_per_page=1.*\&_page=2.*|_page=2.*\&_per_page=1.*)>\; rel="prev"# )
496 ->header_like( 'Link', qr#(_per_page=1.*\&_page=4.*|_page=4.*\&_per_page=1.*)>\; rel="next"# )
497 ->header_like( 'Link', qr#(_per_page=1.*\&_page=1.*|_page=1.*\&_per_page=1).*>\; rel="first"# )
498 ->header_like( 'Link', qr#(_per_page=1.*\&_page=4.*|_page=4.*\&_per_page=1).*>\; rel="last"# );
500 t::lib::Mocks::mock_preference( 'AllowHoldPolicyOverride', 0 );
502 $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->id . "/pickup_locations?" . "patron_id=" . $patron->id . "&_order_by=marc_org_code" . "&_per_page=1" )
503 ->json_is( [$library_1_api] )
504 ->header_is( 'X-Total-Count', '2' )
505 ->header_is( 'X-Base-Total-Count', '2' )
506 ->header_unlike( 'Link', qr|rel="prev"| )
507 ->header_like( 'Link', qr#(_per_page=1.*\&_page=2.*|_page=2.*\&_per_page=1.*)>\; rel="next"# )
508 ->header_like( 'Link', qr#(_per_page=1.*\&_page=1.*|_page=1.*\&_per_page=1).*>\; rel="first"# )
509 ->header_like( 'Link', qr#(_per_page=1.*\&_page=2.*|_page=2.*\&_per_page=1).*>\; rel="last"# );
512 my $deleted_patron = $builder->build_object({ class => 'Koha::Patrons' });
513 my $deleted_patron_id = $deleted_patron->id;
514 $deleted_patron->delete;
516 $t->get_ok( "//$userid:$password@/api/v1/biblios/"
518 . "/pickup_locations?"
519 . "patron_id=" . $deleted_patron_id )
521 ->json_is( '/error' => 'Patron not found' );
525 $t->get_ok( "//$userid:$password@/api/v1/biblios/"
527 . "/pickup_locations?"
528 . "patron_id=" . $patron->id )
530 ->json_is( '/error' => 'Biblio not found' );
532 $schema->storage->txn_rollback;
535 subtest 'get_items_public() tests' => sub {
539 $schema->storage->txn_begin;
541 my $override_hidden_items = 0;
543 my $mocked_category = Test::MockModule->new('Koha::Patron::Category');
544 $mocked_category->mock(
545 'override_hidden_items',
547 return $override_hidden_items;
553 my $mocked_context = Test::MockModule->new('C4::Context');
554 $mocked_context->mock(
561 my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
562 my $password = 'thePassword123';
563 $patron->set_password( { password => $password, skip_validation => 1 } );
564 $patron->discard_changes;
565 my $userid = $patron->userid;
567 my $biblio = $builder->build_sample_biblio();
570 "//$userid:$password@/api/v1/public/biblios/" . $biblio->id . "/items" )
571 ->status_is(200)->json_is( '' => [], 'No items on the biblio' );
573 my $item_1 = $builder->build_sample_item( { biblionumber => $biblio->id } );
574 my $item_2 = $builder->build_sample_item(
575 { biblionumber => $biblio->id, withdrawn => 1 } );
577 $t->get_ok( "//$userid:$password@/api/v1/public/biblios/"
578 . $biblio->biblionumber
579 . "/items" )->status_is(200)->json_is(
581 $item_1->to_api( { public => 1 } ),
582 $item_2->to_api( { public => 1 } )
584 'The items are returned'
587 $rules = { withdrawn => ['1'] };
589 $t->get_ok( "//$userid:$password@/api/v1/public/biblios/"
590 . $biblio->biblionumber
591 . "/items" )->status_is(200)->json_is(
592 '' => [ $item_1->to_api( { public => 1 } ) ],
593 'The items are returned, hidden one is not returned'
596 $t->get_ok( "/api/v1/public/biblios/"
597 . $biblio->biblionumber
598 . "/items" )->status_is(200)->json_is(
599 '' => [ $item_1->to_api( { public => 1 } ) ],
600 'Anonymous user, items are returned, hidden one is not returned'
604 $override_hidden_items = 1;
606 $t->get_ok( "//$userid:$password@/api/v1/public/biblios/"
607 . $biblio->biblionumber
608 . "/items" )->status_is(200)->json_is(
610 $item_1->to_api( { public => 1 } ),
611 $item_2->to_api( { public => 1 } )
613 'The items are returned, the patron category has an override'
616 $schema->storage->txn_rollback;
619 subtest 'get_checkouts() tests' => sub {
623 $schema->storage->txn_begin;
625 my $patron = $builder->build_object(
627 class => 'Koha::Patrons',
628 value => { flags => 0 }
631 my $password = 'thePassword123';
632 $patron->set_password( { password => $password, skip_validation => 1 } );
633 $patron->discard_changes;
634 my $userid = $patron->userid;
636 my $biblio = $builder->build_sample_biblio();
637 $t->get_ok("//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/checkouts")
640 $patron->flags(1)->store; # circulate permissions
642 $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/checkouts")
644 ->json_is( '' => [], 'No checkouts on the biblio' );
646 my $item_1 = $builder->build_sample_item({ biblionumber => $biblio->biblionumber });
647 my $item_2 = $builder->build_sample_item({ biblionumber => $biblio->biblionumber });
649 AddIssue( $patron->unblessed, $item_1->barcode );
650 AddIssue( $patron->unblessed, $item_2->barcode );
652 my $ret = $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/checkouts")
656 my $checkout_1 = Koha::Checkouts->find({ itemnumber => $item_1->id });
657 my $checkout_2 = Koha::Checkouts->find({ itemnumber => $item_2->id });
659 is_deeply( $ret, [ $checkout_1->to_api, $checkout_2->to_api ] );
661 AddReturn( $item_1->barcode );
663 $ret = $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/checkouts")
667 is_deeply( $ret, [ $checkout_2->to_api ] );
669 $ret = $t->get_ok( "//$userid:$password@/api/v1/biblios/" . $biblio->biblionumber . "/checkouts?checked_in=1")
673 my $old_checkout_1 = Koha::Old::Checkouts->find( $checkout_1->id );
675 is_deeply( $ret, [ $old_checkout_1->to_api ] );
677 $schema->storage->txn_rollback;
680 subtest 'set_rating() tests' => sub {
684 $schema->storage->txn_begin;
686 my $patron = $builder->build_object(
688 class => 'Koha::Patrons',
689 value => { flags => 0 }
692 my $password = 'thePassword123';
693 $patron->set_password( { password => $password, skip_validation => 1 } );
694 $patron->discard_changes;
695 my $userid = $patron->userid;
697 my $biblio = $builder->build_sample_biblio();
698 $t->post_ok("/api/v1/public/biblios/" . $biblio->biblionumber . "/ratings" => json => { rating => 3 })
701 $t->post_ok("//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber . "/ratings" => json => { rating => 3 })
703 ->json_is( '/rating', '3' )
704 ->json_is( '/average', '3' )
705 ->json_is( '/count', '1' );
707 $t->post_ok("//$userid:$password@/api/v1/public/biblios/" . $biblio->biblionumber . "/ratings" => json => { rating => undef })
709 ->json_is( '/rating', undef )
710 ->json_is( '/average', '0' )
711 ->json_is( '/count', '0' );
713 $schema->storage->txn_rollback;
718 subtest 'post() tests' => sub {
722 $schema->storage->txn_begin;
724 my $patron = $builder->build_object(
726 class => 'Koha::Patrons',
727 value => { flags => 0 } # no permissions
730 my $password = 'thePassword123';
731 $patron->set_password( { password => $password, skip_validation => 1 } );
732 my $userid = $patron->userid;
734 my $frameworkcode = 'BKS';
735 my $marcxml = q|<?xml version="1.0" encoding="UTF-8"?>
737 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
738 xsi:schemaLocation="http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd"
739 xmlns="http://www.loc.gov/MARC21/slim">
741 <leader>01102pam a2200289 a 7500</leader>
742 <controlfield tag="001">2504398</controlfield>
743 <controlfield tag="005">20200421093816.0</controlfield>
744 <controlfield tag="008">920610s1993 caub s001 0 eng </controlfield>
745 <datafield tag="010" ind1=" " ind2=" ">
746 <subfield code="a"> 92021731 </subfield>
748 <datafield tag="020" ind1=" " ind2=" ">
749 <subfield code="a">05200784381 (Test marcxml)</subfield>
751 <datafield tag="020" ind1=" " ind2=" ">
752 <subfield code="a">05200784461 (Test marcxml)</subfield>
754 <datafield tag="040" ind1=" " ind2=" ">
755 <subfield code="a">DLC</subfield>
756 <subfield code="c">DLC</subfield>
757 <subfield code="d">DLC</subfield>
759 <datafield tag="041" ind1="0" ind2=" ">
760 <subfield code="a">enggrc</subfield>
762 <datafield tag="050" ind1="0" ind2="0">
763 <subfield code="a">PA522</subfield>
764 <subfield code="b">.M38 1993</subfield>
766 <datafield tag="082" ind1="0" ind2="0">
767 <subfield code="a">480</subfield>
768 <subfield code="2">20</subfield>
770 <datafield tag="100" ind1="1" ind2=" ">
771 <subfield code="a">Mastronarde, Donald J.</subfield>
772 <subfield code="9">389</subfield>
774 <datafield tag="245" ind1="1" ind2="0">
775 <subfield code="a">Introduction to Attic Greek (Using marcxml) /</subfield>
776 <subfield code="c">Donald J. Mastronarde.</subfield>
778 <datafield tag="260" ind1=" " ind2=" ">
779 <subfield code="a">Berkeley :</subfield>
780 <subfield code="b">University of California Press,</subfield>
781 <subfield code="c">c1993.</subfield>
783 <datafield tag="300" ind1=" " ind2=" ">
784 <subfield code="a">ix, 425 p. :</subfield>
785 <subfield code="b">maps ;</subfield>
786 <subfield code="c">26 cm.</subfield>
788 <datafield tag="500" ind1=" " ind2=" ">
789 <subfield code="a">Includes index.</subfield>
791 <datafield tag="650" ind1=" " ind2="0">
792 <subfield code="a">Attic Greek dialect</subfield>
793 <subfield code="9">7</subfield>
795 <datafield tag="856" ind1="4" ind2="2">
796 <subfield code="3">Contributor biographical information</subfield>
797 <subfield code="u">http://www.loc.gov/catdir/bios/ucal051/92021731.html</subfield>
799 <datafield tag="856" ind1="4" ind2="2">
800 <subfield code="3">Publisher description</subfield>
801 <subfield code="u">http://www.loc.gov/catdir/description/ucal041/92021731.html</subfield>
803 <datafield tag="906" ind1=" " ind2=" ">
804 <subfield code="a">7</subfield>
805 <subfield code="b">cbc</subfield>
806 <subfield code="c">orignew</subfield>
807 <subfield code="d">1</subfield>
808 <subfield code="e">ocip</subfield>
809 <subfield code="f">19</subfield>
810 <subfield code="g">y-gencatlg</subfield>
812 <datafield tag="942" ind1=" " ind2=" ">
813 <subfield code="2">ddc</subfield>
814 <subfield code="c">BK</subfield>
816 <datafield tag="955" ind1=" " ind2=" ">
817 <subfield code="a">pc05 to ea00 06-11-92; ea04 to SCD 06-11-92; fd11 06-11-92 (PA522.M...); fr21 06-12-92; fs62 06-15-92; CIP ver. pv07 11-12-93</subfield>
819 <datafield tag="999" ind1=" " ind2=" ">
820 <subfield code="c">3</subfield>
821 <subfield code="d">3</subfield>
831 "005": "20200421093816.0"
834 "008": "920610s1993 caub s001 0 eng "
851 "a": "05200784382 (Test mij)"
862 "a": "05200784462 (Test mij)"
930 "a": "Mastronarde, Donald J."
944 "a": "Introduction to Attic Greek (Using mij) /"
947 "c": "Donald J. Mastronarde."
960 "b": "University of California Press,"
991 "a": "Includes index."
1002 "a": "Attic Greek dialect"
1016 "3": "Contributor biographical information"
1019 "u": "http://www.loc.gov/catdir/bios/ucal051/92021731.html"
1031 "3": "Publisher description"
1034 "u": "http://www.loc.gov/catdir/description/ucal041/92021731.html"
1087 "a": "pc05 to ea00 06-11-92; ea04 to SCD 06-11-92; fd11 06-11-92 (PA522.M...); fr21 06-12-92; fs62 06-15-92; CIP ver. pv07 11-12-93"
1109 "leader": "01102pam a2200289 a 8500"
1111 my $marc = q|01102pam a2200289 a 9500001000800000005001700008008004100025010001700066020002800083020003500111040001800146041001100164050002100175082001200196100003200208245005800240260005600298300003300354500002000387650002700407856009500434856008700529906004500616942001200661955013000673999000900803
\1e2504398
\1e20200421093816.0
\1e920610s1993 caub s001 0 eng
\1e \1fa 92021731
\1e \1fa05200784383 (Test usmarc)
\1e \1fa05200784463 (Test usmarc)
\1e \1faDLC
\1fcDLC
\1fdDLC
\1e0
\1faenggrc
\1e00
\1faPA522
\1fb.M38 1993
\1e00
\1fa480
\1f220
\1e1
\1faMastronarde, Donald J.
\1f9389
\1e10
\1faIntroduction to Attic Greek (Using usmarc) /
\1fcDonald J. Mastronarde.
\1e \1faBerkeley :
\1fbUniversity of California Press,
\1fcc1993.
\1e \1faix, 425 p. :
\1fbmaps ;
\1fc26 cm.
\1e \1faIncludes index.
\1e 0
\1faAttic Greek dialect
\1f97
\1e42
\1f3Contributor biographical information
\1fuhttp://www.loc.gov/catdir/bios/ucal051/92021731.html
\1e42
\1f3Publisher description
\1fuhttp://www.loc.gov/catdir/description/ucal041/92021731.html
\1e \1fa7
\1fbcbc
\1fcorignew
\1fd1
\1feocip
\1ff19
\1fgy-gencatlg
\1e \1f2ddc
\1fcBK
\1e \1fapc05 to ea00 06-11-92; ea04 to SCD 06-11-92; fd11 06-11-92 (PA522.M...); fr21 06-12-92; fs62 06-15-92; CIP ver. pv07 11-12-93
\1e \1fc3
\1fd3
\1e\1d|;
1113 $t->post_ok("//$userid:$password@/api/v1/biblios")
1114 ->status_is(403, 'Not enough permissions makes it return the right code');
1119 source => 'UserPermission',
1121 borrowernumber => $patron->borrowernumber,
1123 code => 'edit_catalogue'
1128 $t->post_ok("//$userid:$password@/api/v1/biblios" => {'Content-Type' => 'application/marcxml+xml', 'x-framework-id' => $frameworkcode, "x-march-schema" => 'INVALID'})
1129 ->status_is(400, 'Invalid header x-marc-schema');
1131 $t->post_ok("//$userid:$password@/api/v1/biblios" => {'Content-Type' => 'application/marcxml+xml', 'x-framework-id' => $frameworkcode} => $marcxml)
1135 $t->post_ok("//$userid:$password@/api/v1/biblios" => {'Content-Type' => 'application/marc-in-json', 'x-framework-id' => $frameworkcode, 'x-confirm-not-duplicate' => 1} => $mij)
1139 $t->post_ok("//$userid:$password@/api/v1/biblios" => {'Content-Type' => 'application/marc', 'x-framework-id' => $frameworkcode} => $marc)
1143 $schema->storage->txn_rollback;
1146 subtest 'put() tests' => sub {
1150 $schema->storage->txn_begin;
1152 my $patron = $builder->build_object(
1154 class => 'Koha::Patrons',
1155 value => { flags => 0 } # no permissions
1158 my $password = 'thePassword123';
1159 $patron->set_password( { password => $password, skip_validation => 1 } );
1160 my $userid = $patron->userid;
1162 my $frameworkcode = 'BKS';
1163 my $biblio = $builder->build_sample_biblio({frameworkcode => $frameworkcode});
1165 my $biblionumber = $biblio->biblionumber;
1167 my $marcxml = q|<?xml version="1.0" encoding="UTF-8"?>
1169 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
1170 xsi:schemaLocation="http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd"
1171 xmlns="http://www.loc.gov/MARC21/slim">
1173 <leader>01102pam a2200289 a 6500</leader>
1174 <controlfield tag="001">2504398</controlfield>
1175 <controlfield tag="005">20200421093816.0</controlfield>
1176 <controlfield tag="008">920610s1993 caub s001 0 eng </controlfield>
1177 <datafield tag="010" ind1=" " ind2=" ">
1178 <subfield code="a"> 92021731 </subfield>
1180 <datafield tag="020" ind1=" " ind2=" ">
1181 <subfield code="a">05200784384 (Test json)</subfield>
1183 <datafield tag="020" ind1=" " ind2=" ">
1184 <subfield code="a">05200784464 (Test json)</subfield>
1186 <datafield tag="040" ind1=" " ind2=" ">
1187 <subfield code="a">DLC</subfield>
1188 <subfield code="c">DLC</subfield>
1189 <subfield code="d">DLC</subfield>
1191 <datafield tag="041" ind1="0" ind2=" ">
1192 <subfield code="a">enggrc</subfield>
1194 <datafield tag="050" ind1="0" ind2="0">
1195 <subfield code="a">PA522</subfield>
1196 <subfield code="b">.M38 1993</subfield>
1198 <datafield tag="082" ind1="0" ind2="0">
1199 <subfield code="a">480</subfield>
1200 <subfield code="2">20</subfield>
1202 <datafield tag="100" ind1="1" ind2=" ">
1203 <subfield code="a">Mastronarde, Donald J.</subfield>
1204 <subfield code="9">389</subfield>
1206 <datafield tag="245" ind1="1" ind2="0">
1207 <subfield code="a">Introduction to Attic Greek (Using marcxml) /</subfield>
1208 <subfield code="c">Donald J. Mastronarde.</subfield>
1210 <datafield tag="260" ind1=" " ind2=" ">
1211 <subfield code="a">Berkeley :</subfield>
1212 <subfield code="b">University of California Press,</subfield>
1213 <subfield code="c">c1993.</subfield>
1215 <datafield tag="300" ind1=" " ind2=" ">
1216 <subfield code="a">ix, 425 p. :</subfield>
1217 <subfield code="b">maps ;</subfield>
1218 <subfield code="c">26 cm.</subfield>
1220 <datafield tag="500" ind1=" " ind2=" ">
1221 <subfield code="a">Includes index.</subfield>
1223 <datafield tag="650" ind1=" " ind2="0">
1224 <subfield code="a">Attic Greek dialect</subfield>
1225 <subfield code="9">7</subfield>
1227 <datafield tag="856" ind1="4" ind2="2">
1228 <subfield code="3">Contributor biographical information</subfield>
1229 <subfield code="u">http://www.loc.gov/catdir/bios/ucal051/92021731.html</subfield>
1231 <datafield tag="856" ind1="4" ind2="2">
1232 <subfield code="3">Publisher description</subfield>
1233 <subfield code="u">http://www.loc.gov/catdir/description/ucal041/92021731.html</subfield>
1235 <datafield tag="906" ind1=" " ind2=" ">
1236 <subfield code="a">7</subfield>
1237 <subfield code="b">cbc</subfield>
1238 <subfield code="c">orignew</subfield>
1239 <subfield code="d">1</subfield>
1240 <subfield code="e">ocip</subfield>
1241 <subfield code="f">19</subfield>
1242 <subfield code="g">y-gencatlg</subfield>
1244 <datafield tag="942" ind1=" " ind2=" ">
1245 <subfield code="2">ddc</subfield>
1246 <subfield code="c">BK</subfield>
1248 <datafield tag="955" ind1=" " ind2=" ">
1249 <subfield code="a">pc05 to ea00 06-11-92; ea04 to SCD 06-11-92; fd11 06-11-92 (PA522.M...); fr21 06-12-92; fs62 06-15-92; CIP ver. pv07 11-12-93</subfield>
1251 <datafield tag="999" ind1=" " ind2=" ">
1252 <subfield code="c">3</subfield>
1253 <subfield code="d">3</subfield>
1263 "005": "20200421093816.0"
1266 "008": "920610s1993 caub s001 0 eng "
1283 "a": "05200784382 (Test mij)"
1294 "a": "05200784462 (Test mij)"
1362 "a": "Mastronarde, Donald J."
1376 "a": "Introduction to Attic Greek (Using mij) /"
1379 "c": "Donald J. Mastronarde."
1392 "b": "University of California Press,"
1423 "a": "Includes index."
1434 "a": "Attic Greek dialect"
1448 "3": "Contributor biographical information"
1451 "u": "http://www.loc.gov/catdir/bios/ucal051/92021731.html"
1463 "3": "Publisher description"
1466 "u": "http://www.loc.gov/catdir/description/ucal041/92021731.html"
1519 "a": "pc05 to ea00 06-11-92; ea04 to SCD 06-11-92; fd11 06-11-92 (PA522.M...); fr21 06-12-92; fs62 06-15-92; CIP ver. pv07 11-12-93"
1541 "leader": "01102pam a2200289 a 8500"
1543 my $marc = q|01116pam a2200289 a 4500001000800000005001700008008004100025010001700066020002800083020002800111040001800139041001100157050002100168082001200189100003200201245007500233260005600308300003300364500002000397650002700417856009500444856008700539906004500626942001200671955013000683999001300813
\1e2504398
\1e20221223213433.0
\1e920610s1993 caub s001 0 eng
\1e \1fa 92021731
\1e \1fa05200784384 (Test json)
\1e \1fa05200784464 (Test json)
\1e \1faDLC
\1fcDLC
\1fdDLC
\1e0
\1faenggrc
\1e00
\1faPA522
\1fb.M38 1993
\1e00
\1fa480
\1f220
\1e1
\1faMastronarde, Donald J.
\1f9389
\1e10
\1faIntroduction to Attic Greek (Using usmarc) /
\1fcDonald J. Mastronarde.
\1e \1faBerkeley :
\1fbUniversity of California Press,
\1fcc1993.
\1e \1faix, 425 p. :
\1fbmaps ;
\1fc26 cm.
\1e \1faIncludes index.
\1e 0
\1faAttic Greek dialect
\1f97
\1e42
\1f3Contributor biographical information
\1fuhttp://www.loc.gov/catdir/bios/ucal051/92021731.html
\1e42
\1f3Publisher description
\1fuhttp://www.loc.gov/catdir/description/ucal041/92021731.html
\1e \1fa7
\1fbcbc
\1fcorignew
\1fd1
\1feocip
\1ff19
\1fgy-gencatlg
\1e \1f2ddc
\1fcBK
\1e \1fapc05 to ea00 06-11-92; ea04 to SCD 06-11-92; fd11 06-11-92 (PA522.M...); fr21 06-12-92; fs62 06-15-92; CIP ver. pv07 11-12-93
\1e \1fc715
\1fd715
\1e\1d|;
1545 $t->put_ok("//$userid:$password@/api/v1/biblios/$biblionumber")
1546 ->status_is(403, 'Not enough permissions makes it return the right code');
1551 source => 'UserPermission',
1553 borrowernumber => $patron->borrowernumber,
1555 code => 'edit_catalogue'
1560 $t->put_ok("//$userid:$password@/api/v1/biblios/$biblionumber" => {'Content-Type' => 'application/marcxml+xml', 'x-framework-id' => $frameworkcode} => $marcxml)
1564 $biblio = Koha::Biblios->find($biblionumber);
1566 is($biblio->title, 'Introduction to Attic Greek (Using marcxml) /');
1568 $t->put_ok("//$userid:$password@/api/v1/biblios/$biblionumber" => {'Content-Type' => 'application/marc-in-json', 'x-framework-id' => $frameworkcode} => $mij)
1572 $biblio = Koha::Biblios->find($biblionumber);
1574 is($biblio->title, 'Introduction to Attic Greek (Using mij) /');
1576 $t->put_ok("//$userid:$password@/api/v1/biblios/$biblionumber" => {'Content-Type' => 'application/marc', 'x-framework-id' => $frameworkcode} => $marc)
1580 $biblio = Koha::Biblios->find($biblionumber);
1582 is($biblio->title, 'Introduction to Attic Greek (Using usmarc) /');
1584 $schema->storage->txn_rollback;