From fcdcb49fd58a161fe55648727638d44772b66bad Mon Sep 17 00:00:00 2001 From: Agustin Moyano Date: Thu, 16 Feb 2023 22:17:43 -0300 Subject: [PATCH] Bug 32734: Add REST endpoint to list biblios This patch adds an endpoint to list biblios To test: 1. apply patch 2. enable basic auth 3. call to GET /api/v1/biblios with the following Accept headers: * application/json * application/marcxml+xml * application/marc-in-json * application/marc * text/plain 4. notice how data changes with each Accept header 5. prove t/db_dependent/Koha/Biblios.t t/db_dependent/api/v1/biblios.t 6. sign off --- Koha/Biblios.pm | 43 + Koha/REST/Plugin/Objects.pm | 8 +- Koha/REST/V1/Biblios.pm | 64 ++ api/v1/swagger/paths/biblios.yaml | 57 ++ t/db_dependent/Koha/Biblios.t | 41 +- t/db_dependent/api/v1/biblios.t | 1471 +++++++++++++++-------------- 6 files changed, 972 insertions(+), 712 deletions(-) diff --git a/Koha/Biblios.pm b/Koha/Biblios.pm index 416aa2bbe5..2675e9a492 100644 --- a/Koha/Biblios.pm +++ b/Koha/Biblios.pm @@ -24,6 +24,10 @@ use Koha::Database; use Koha::Biblio; use Koha::Libraries; +use MARC::File::MiJ; +use MARC::File::USMARC; +use MARC::File::XML; +use MARC::Record; use base qw(Koha::Objects); @@ -35,6 +39,45 @@ Koha::Biblios - Koha Biblio object set class =head2 Class methods +=head3 print_collection + my $collection_text = $result_set->print_collection($format) + +Return a text representation of a collection (group of records) in the specified format. +Allowed formats are marcxml, mij, marc and txt. Defaults to marcxml. + +=cut + +sub print_collection { + my ( $self, $format ) = @_; + + my ($start, $glue, $end, @parts); + + my %serializers = ( + 'mij' => \&MARC::File::MiJ::encode, + 'marc' => \&MARC::File::USMARC::encode, + 'txt' => \&MARC::Record::as_formatted, + 'marcxml' => \&MARC::File::XML::record + ); + if ($format eq 'mij') { + $start = '['; + $glue = ','; + $end = ']'; + } elsif ($format eq 'marc') { + $glue = "\n"; + } elsif ($format eq 'txt') { + $glue = "\n----------\n"; + } else { + $glue = ''; + $format = 'marcxml'; + $start = MARC::File::XML::header(); + $end = MARC::File::XML::footer(); + } + while (my $biblio = $self->next) { + push @parts, $serializers{$format}->($biblio->metadata->record); + } + return (defined $start ? $start : '').join($glue, @parts).(defined $end ? $end : ''); +} + =head3 pickup_locations my $biblios = Koha::Biblios->search(...); diff --git a/Koha/REST/Plugin/Objects.pm b/Koha/REST/Plugin/Objects.pm index eba63a4ded..0688936715 100644 --- a/Koha/REST/Plugin/Objects.pm +++ b/Koha/REST/Plugin/Objects.pm @@ -48,7 +48,7 @@ the requested object. It passes through any embeds if specified. $app->helper( 'objects.find' => sub { - my ( $c, $result_set, $id ) = @_; + my ( $c, $result_set, $id, $return_result_set ) = @_; my $attributes = {}; @@ -68,6 +68,8 @@ the requested object. It passes through any embeds if specified. return unless $object; + return $object if $return_result_set; + return $object->to_api({ embed => $embed, strings => $strings }); } ); @@ -89,7 +91,7 @@ shouldn't be called twice in it. $app->helper( 'objects.search' => sub { - my ( $c, $result_set ) = @_; + my ( $c, $result_set, $return_result_set ) = @_; my $args = $c->validation->output; my $attributes = {}; @@ -205,6 +207,8 @@ shouldn't be called twice in it. } ); + return $objects if $return_result_set; + return $objects->to_api({ embed => $embed, public => $is_public, strings => $strings }); } ); diff --git a/Koha/REST/V1/Biblios.pm b/Koha/REST/V1/Biblios.pm index 8546afbfd7..ea307b100c 100644 --- a/Koha/REST/V1/Biblios.pm +++ b/Koha/REST/V1/Biblios.pm @@ -597,4 +597,68 @@ sub update { $c->unhandled_exception($_); }; } + +=head3 list + +Controller function that handles retrieving a single biblio object + +=cut + +sub list { + my $c = shift->openapi->valid_input or return; + + my $attributes; + $attributes = { prefetch => [ 'metadata' ] } # don't prefetch metadata if not needed + unless $c->req->headers->accept =~ m/application\/json/; + + my $biblios = $c->objects->search( Koha::Biblios->new, 1 ); + + return try { + + if ( $c->req->headers->accept =~ m/application\/json(;.*)?$/ ) { + return $c->render( + status => 200, + json => $biblios->to_api + ); + } elsif ( $c->req->headers->accept =~ m/application\/marcxml\+xml(;.*)?$/ ) { + $c->res->headers->add('Content-Type', 'application/marcxml+xml'); + return $c->render( + status => 200, + text => $biblios->print_collection('marcxml') + ); + } elsif ( $c->req->headers->accept =~ m/application\/marc-in-json(;.*)?$/ ) { + $c->res->headers->add('Content-Type', 'application/marc-in-json'); + return $c->render( + status => 200, + data => $biblios->print_collection('mij') + ); + } elsif ( $c->req->headers->accept =~ m/application\/marc(;.*)?$/ ) { + $c->res->headers->add('Content-Type', 'application/marc'); + return $c->render( + status => 200, + text => $biblios->print_collection('marc') + ); + } elsif ( $c->req->headers->accept =~ m/text\/plain(;.*)?$/ ) { + return $c->render( + status => 200, + text => $biblios->print_collection('txt') + ); + } else { + return $c->render( + status => 406, + openapi => [ + "application/json", + "application/marcxml+xml", + "application/marc-in-json", + "application/marc", + "text/plain" + ] + ); + } + } + catch { + $c->unhandled_exception($_); + }; +} + 1; diff --git a/api/v1/swagger/paths/biblios.yaml b/api/v1/swagger/paths/biblios.yaml index 2480021730..f8cfe00b02 100644 --- a/api/v1/swagger/paths/biblios.yaml +++ b/api/v1/swagger/paths/biblios.yaml @@ -56,6 +56,63 @@ x-koha-authorization: permissions: editcatalogue: edit_catalogue + get: + x-mojo-to: Biblios#list + operationId: listBiblio + tags: + - biblios + summary: List biblios + parameters: + - $ref: "../swagger.yaml#/parameters/page" + - $ref: "../swagger.yaml#/parameters/per_page" + - $ref: "../swagger.yaml#/parameters/match" + - $ref: "../swagger.yaml#/parameters/order_by" + - $ref: "../swagger.yaml#/parameters/q_param" + - $ref: "../swagger.yaml#/parameters/q_body" + - $ref: "../swagger.yaml#/parameters/q_header" + - $ref: "../swagger.yaml#/parameters/request_id_header" + produces: + - application/json + - application/marcxml+xml + - application/marc-in-json + - application/marc + - text/plain + responses: + "200": + description: A list of biblios + "401": + description: Authentication required + schema: + $ref: "../swagger.yaml#/definitions/error" + "403": + description: Access forbidden + schema: + $ref: "../swagger.yaml#/definitions/error" + "404": + description: Biblio not found + schema: + $ref: "../swagger.yaml#/definitions/error" + "406": + description: Not acceptable + schema: + type: array + description: Accepted content-types + items: + type: string + "500": + description: | + Internal server error. Possible `error_code` attribute values: + + * `internal_server_error` + schema: + $ref: "../swagger.yaml#/definitions/error" + "503": + description: Under maintenance + schema: + $ref: "../swagger.yaml#/definitions/error" + x-koha-authorization: + permissions: + catalogue: "1" "/biblios/{biblio_id}": get: x-mojo-to: Biblios#get diff --git a/t/db_dependent/Koha/Biblios.t b/t/db_dependent/Koha/Biblios.t index b93efebb21..31b9ff9582 100755 --- a/t/db_dependent/Koha/Biblios.t +++ b/t/db_dependent/Koha/Biblios.t @@ -19,7 +19,7 @@ use Modern::Perl; -use Test::More tests => 6; +use Test::More tests => 7; use Test::Exception; use Test::MockModule; @@ -29,6 +29,7 @@ use MARC::Field; use C4::Items; use C4::Biblio qw( AddBiblio ModBiblio ); use C4::Reserves qw( AddReserve ); +use JSON qw( decode_json ); use Koha::DateUtils qw( dt_from_string output_pref ); use Koha::Biblios; @@ -309,3 +310,41 @@ subtest 'pickup_locations() tests' => sub { $schema->storage->txn_rollback; }; + +subtest 'print_collection() tests' => sub { + plan tests => 4; + + $schema->storage->txn_begin; + + # Two biblios + my $biblio_1 = $builder->build_sample_biblio; + my $biblio_2 = $builder->build_sample_biblio; + + my $result_set = Koha::Biblios->search([{biblionumber => $biblio_1->biblionumber}, {biblionumber => $biblio_2->biblionumber}]); + my $collection = $result_set->print_collection('marcxml'); + + like($collection, qr/<(\s*\w*:)?collection[^>]*>/, 'Has collection tag'); + + $result_set->reset; + $collection = $result_set->print_collection('mij'); + + my $count = scalar(@{decode_json($collection)}); + + is($count, 2, 'Has 2 elements'); + + $result_set->reset; + $collection = $result_set->print_collection('marc'); + + $count = $collection =~ tr/[\x1D]//; + + is($count, 2, 'Has 2 USMARC end of record'); + + $result_set->reset; + $collection = $result_set->print_collection('txt'); + + $count = scalar(split(/-{10}/, $collection) ); + + is($count, 2, 'Has 2 records'); + + $schema->storage->txn_rollback; +}; diff --git a/t/db_dependent/api/v1/biblios.t b/t/db_dependent/api/v1/biblios.t index 5d17ee5ee3..e5af44bb61 100755 --- a/t/db_dependent/api/v1/biblios.t +++ b/t/db_dependent/api/v1/biblios.t @@ -20,7 +20,7 @@ use Modern::Perl; use utf8; use Encode; -use Test::More tests => 10; +use Test::More tests => 11; use Test::MockModule; use Test::Mojo; use Test::Warn; @@ -733,381 +733,381 @@ subtest 'post() tests' => sub { my $frameworkcode = 'BKS'; my $marcxml = q| - - - 01102pam a2200289 a 7500 - 2504398 - 20200421093816.0 - 920610s1993 caub s001 0 eng - - 92021731 - - - 05200784381 (Test marcxml) - - - 05200784461 (Test marcxml) - - - DLC - DLC - DLC - - - enggrc - - - PA522 - .M38 1993 - - - 480 - 20 - - - Mastronarde, Donald J. - 389 - - - Introduction to Attic Greek (Using marcxml) / - Donald J. Mastronarde. - - - Berkeley : - University of California Press, - c1993. - - - ix, 425 p. : - maps ; - 26 cm. - - - Includes index. - - - Attic Greek dialect - 7 - - - Contributor biographical information - http://www.loc.gov/catdir/bios/ucal051/92021731.html - - - Publisher description - http://www.loc.gov/catdir/description/ucal041/92021731.html - - - 7 - cbc - orignew - 1 - ocip - 19 - y-gencatlg - - - ddc - BK - - - 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 - - - 3 - 3 - -|; + + + 01102pam a2200289 a 7500 + 2504398 + 20200421093816.0 + 920610s1993 caub s001 0 eng + + 92021731 + + + 05200784381 (Test marcxml) + + + 05200784461 (Test marcxml) + + + DLC + DLC + DLC + + + enggrc + + + PA522 + .M38 1993 + + + 480 + 20 + + + Mastronarde, Donald J. + 389 + + + Introduction to Attic Greek (Using marcxml) / + Donald J. Mastronarde. + + + Berkeley : + University of California Press, + c1993. + + + ix, 425 p. : + maps ; + 26 cm. + + + Includes index. + + + Attic Greek dialect + 7 + + + Contributor biographical information + http://www.loc.gov/catdir/bios/ucal051/92021731.html + + + Publisher description + http://www.loc.gov/catdir/description/ucal041/92021731.html + + + 7 + cbc + orignew + 1 + ocip + 19 + y-gencatlg + + + ddc + BK + + + 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 + + + 3 + 3 + + |; my $mij = q|{ - "fields": [ - { - "001": "2504398" - }, - { - "005": "20200421093816.0" - }, - { - "008": "920610s1993 caub s001 0 eng " - }, - { - "010": { - "ind1": " ", - "subfields": [ - { - "a": " 92021731 " + "fields": [ + { + "001": "2504398" + }, + { + "005": "20200421093816.0" + }, + { + "008": "920610s1993 caub s001 0 eng " + }, + { + "010": { + "ind1": " ", + "subfields": [ + { + "a": " 92021731 " + } + ], + "ind2": " " } - ], - "ind2": " " - } - }, - { - "020": { - "subfields": [ - { - "a": "05200784382 (Test mij)" + }, + { + "020": { + "subfields": [ + { + "a": "05200784382 (Test mij)" + } + ], + "ind2": " ", + "ind1": " " } - ], - "ind2": " ", - "ind1": " " - } - }, - { - "020": { - "subfields": [ - { - "a": "05200784462 (Test mij)" + }, + { + "020": { + "subfields": [ + { + "a": "05200784462 (Test mij)" + } + ], + "ind1": " ", + "ind2": " " } - ], - "ind1": " ", - "ind2": " " - } - }, - { - "040": { - "subfields": [ - { - "a": "DLC" - }, - { - "c": "DLC" - }, - { - "d": "DLC" + }, + { + "040": { + "subfields": [ + { + "a": "DLC" + }, + { + "c": "DLC" + }, + { + "d": "DLC" + } + ], + "ind2": " ", + "ind1": " " } - ], - "ind2": " ", - "ind1": " " - } - }, - { - "041": { - "ind2": " ", - "subfields": [ - { - "a": "enggrc" + }, + { + "041": { + "ind2": " ", + "subfields": [ + { + "a": "enggrc" + } + ], + "ind1": "0" } - ], - "ind1": "0" - } - }, - { - "050": { - "subfields": [ - { - "a": "PA522" - }, - { - "b": ".M38 1993" + }, + { + "050": { + "subfields": [ + { + "a": "PA522" + }, + { + "b": ".M38 1993" + } + ], + "ind1": "0", + "ind2": "0" } - ], - "ind1": "0", - "ind2": "0" - } - }, - { - "082": { - "subfields": [ - { - "a": "480" - }, - { - "2": "20" + }, + { + "082": { + "subfields": [ + { + "a": "480" + }, + { + "2": "20" + } + ], + "ind2": "0", + "ind1": "0" } - ], - "ind2": "0", - "ind1": "0" - } - }, - { - "100": { - "ind2": " ", - "subfields": [ - { - "a": "Mastronarde, Donald J." - }, - { - "9": "389" + }, + { + "100": { + "ind2": " ", + "subfields": [ + { + "a": "Mastronarde, Donald J." + }, + { + "9": "389" + } + ], + "ind1": "1" } - ], - "ind1": "1" - } - }, - { - "245": { - "ind1": "1", - "subfields": [ - { - "a": "Introduction to Attic Greek (Using mij) /" - }, - { - "c": "Donald J. Mastronarde." + }, + { + "245": { + "ind1": "1", + "subfields": [ + { + "a": "Introduction to Attic Greek (Using mij) /" + }, + { + "c": "Donald J. Mastronarde." + } + ], + "ind2": "0" } - ], - "ind2": "0" - } - }, - { - "260": { - "subfields": [ - { - "a": "Berkeley :" - }, - { - "b": "University of California Press," - }, - { - "c": "c1993." + }, + { + "260": { + "subfields": [ + { + "a": "Berkeley :" + }, + { + "b": "University of California Press," + }, + { + "c": "c1993." + } + ], + "ind2": " ", + "ind1": " " } - ], - "ind2": " ", - "ind1": " " - } - }, - { - "300": { - "ind1": " ", - "subfields": [ - { - "a": "ix, 425 p. :" - }, - { - "b": "maps ;" - }, - { - "c": "26 cm." + }, + { + "300": { + "ind1": " ", + "subfields": [ + { + "a": "ix, 425 p. :" + }, + { + "b": "maps ;" + }, + { + "c": "26 cm." + } + ], + "ind2": " " } - ], - "ind2": " " - } - }, - { - "500": { - "subfields": [ - { - "a": "Includes index." + }, + { + "500": { + "subfields": [ + { + "a": "Includes index." + } + ], + "ind1": " ", + "ind2": " " } - ], - "ind1": " ", - "ind2": " " - } - }, - { - "650": { - "subfields": [ - { - "a": "Attic Greek dialect" - }, - { - "9": "7" + }, + { + "650": { + "subfields": [ + { + "a": "Attic Greek dialect" + }, + { + "9": "7" + } + ], + "ind2": "0", + "ind1": " " } - ], - "ind2": "0", - "ind1": " " - } - }, - { - "856": { - "subfields": [ - { - "3": "Contributor biographical information" - }, - { - "u": "http://www.loc.gov/catdir/bios/ucal051/92021731.html" + }, + { + "856": { + "subfields": [ + { + "3": "Contributor biographical information" + }, + { + "u": "http://www.loc.gov/catdir/bios/ucal051/92021731.html" + } + ], + "ind2": "2", + "ind1": "4" } - ], - "ind2": "2", - "ind1": "4" - } - }, - { - "856": { - "ind1": "4", - "subfields": [ - { - "3": "Publisher description" - }, - { - "u": "http://www.loc.gov/catdir/description/ucal041/92021731.html" + }, + { + "856": { + "ind1": "4", + "subfields": [ + { + "3": "Publisher description" + }, + { + "u": "http://www.loc.gov/catdir/description/ucal041/92021731.html" + } + ], + "ind2": "2" } - ], - "ind2": "2" - } - }, - { - "906": { - "subfields": [ - { - "a": "7" - }, - { - "b": "cbc" - }, - { - "c": "orignew" - }, - { - "d": "1" - }, - { - "e": "ocip" - }, - { - "f": "19" - }, - { - "g": "y-gencatlg" + }, + { + "906": { + "subfields": [ + { + "a": "7" + }, + { + "b": "cbc" + }, + { + "c": "orignew" + }, + { + "d": "1" + }, + { + "e": "ocip" + }, + { + "f": "19" + }, + { + "g": "y-gencatlg" + } + ], + "ind1": " ", + "ind2": " " } - ], - "ind1": " ", - "ind2": " " - } - }, - { - "942": { - "subfields": [ - { - "2": "ddc" - }, - { - "c": "BK" + }, + { + "942": { + "subfields": [ + { + "2": "ddc" + }, + { + "c": "BK" + } + ], + "ind2": " ", + "ind1": " " } - ], - "ind2": " ", - "ind1": " " - } - }, - { - "955": { - "subfields": [ - { - "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" + }, + { + "955": { + "subfields": [ + { + "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" + } + ], + "ind2": " ", + "ind1": " " } - ], - "ind2": " ", - "ind1": " " - } - }, - { - "999": { - "subfields": [ - { - "c": "3" - }, - { - "d": "3" + }, + { + "999": { + "subfields": [ + { + "c": "3" + }, + { + "d": "3" + } + ], + "ind1": " ", + "ind2": " " } - ], - "ind1": " ", - "ind2": " " - } - } - ], - "leader": "01102pam a2200289 a 8500" -}|; + } + ], + "leader": "01102pam a2200289 a 8500" + }|; my $marc = q|01102pam a2200289 a 9500001000800000005001700008008004100025010001700066020002800083020003500111040001800146041001100164050002100175082001200196100003200208245005800240260005600298300003300354500002000387650002700407856009500434856008700529906004500616942001200661955013000673999000900803250439820200421093816.0920610s1993 caub s001 0 eng  a 92021731  a05200784383 (Test usmarc) a05200784463 (Test usmarc) aDLCcDLCdDLC0 aenggrc00aPA522b.M38 199300a4802201 aMastronarde, Donald J.938910aIntroduction to Attic Greek (Using usmarc) /cDonald J. Mastronarde. aBerkeley :bUniversity of California Press,cc1993. aix, 425 p. :bmaps ;c26 cm. aIncludes index. 0aAttic Greek dialect97423Contributor biographical informationuhttp://www.loc.gov/catdir/bios/ucal051/92021731.html423Publisher descriptionuhttp://www.loc.gov/catdir/description/ucal041/92021731.html a7bcbccorignewd1eocipf19gy-gencatlg 2ddccBK apc05 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 c3d3|; $t->post_ok("//$userid:$password@/api/v1/biblios") @@ -1165,381 +1165,381 @@ subtest 'put() tests' => sub { my $biblionumber = $biblio->biblionumber; my $marcxml = q| - - - 01102pam a2200289 a 6500 - 2504398 - 20200421093816.0 - 920610s1993 caub s001 0 eng - - 92021731 - - - 05200784384 (Test json) - - - 05200784464 (Test json) - - - DLC - DLC - DLC - - - enggrc - - - PA522 - .M38 1993 - - - 480 - 20 - - - Mastronarde, Donald J. - 389 - - - Introduction to Attic Greek (Using marcxml) / - Donald J. Mastronarde. - - - Berkeley : - University of California Press, - c1993. - - - ix, 425 p. : - maps ; - 26 cm. - - - Includes index. - - - Attic Greek dialect - 7 - - - Contributor biographical information - http://www.loc.gov/catdir/bios/ucal051/92021731.html - - - Publisher description - http://www.loc.gov/catdir/description/ucal041/92021731.html - - - 7 - cbc - orignew - 1 - ocip - 19 - y-gencatlg - - - ddc - BK - - - 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 - - - 3 - 3 - -|; + + + 01102pam a2200289 a 6500 + 2504398 + 20200421093816.0 + 920610s1993 caub s001 0 eng + + 92021731 + + + 05200784384 (Test json) + + + 05200784464 (Test json) + + + DLC + DLC + DLC + + + enggrc + + + PA522 + .M38 1993 + + + 480 + 20 + + + Mastronarde, Donald J. + 389 + + + Introduction to Attic Greek (Using marcxml) / + Donald J. Mastronarde. + + + Berkeley : + University of California Press, + c1993. + + + ix, 425 p. : + maps ; + 26 cm. + + + Includes index. + + + Attic Greek dialect + 7 + + + Contributor biographical information + http://www.loc.gov/catdir/bios/ucal051/92021731.html + + + Publisher description + http://www.loc.gov/catdir/description/ucal041/92021731.html + + + 7 + cbc + orignew + 1 + ocip + 19 + y-gencatlg + + + ddc + BK + + + 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 + + + 3 + 3 + + |; my $mij = q|{ - "fields": [ - { - "001": "2504398" - }, - { - "005": "20200421093816.0" - }, - { - "008": "920610s1993 caub s001 0 eng " - }, - { - "010": { - "ind1": " ", - "subfields": [ - { - "a": " 92021731 " + "fields": [ + { + "001": "2504398" + }, + { + "005": "20200421093816.0" + }, + { + "008": "920610s1993 caub s001 0 eng " + }, + { + "010": { + "ind1": " ", + "subfields": [ + { + "a": " 92021731 " + } + ], + "ind2": " " } - ], - "ind2": " " - } - }, - { - "020": { - "subfields": [ - { - "a": "05200784382 (Test mij)" + }, + { + "020": { + "subfields": [ + { + "a": "05200784382 (Test mij)" + } + ], + "ind2": " ", + "ind1": " " } - ], - "ind2": " ", - "ind1": " " - } - }, - { - "020": { - "subfields": [ - { - "a": "05200784462 (Test mij)" + }, + { + "020": { + "subfields": [ + { + "a": "05200784462 (Test mij)" + } + ], + "ind1": " ", + "ind2": " " } - ], - "ind1": " ", - "ind2": " " - } - }, - { - "040": { - "subfields": [ - { - "a": "DLC" - }, - { - "c": "DLC" - }, - { - "d": "DLC" + }, + { + "040": { + "subfields": [ + { + "a": "DLC" + }, + { + "c": "DLC" + }, + { + "d": "DLC" + } + ], + "ind2": " ", + "ind1": " " } - ], - "ind2": " ", - "ind1": " " - } - }, - { - "041": { - "ind2": " ", - "subfields": [ - { - "a": "enggrc" + }, + { + "041": { + "ind2": " ", + "subfields": [ + { + "a": "enggrc" + } + ], + "ind1": "0" } - ], - "ind1": "0" - } - }, - { - "050": { - "subfields": [ - { - "a": "PA522" - }, - { - "b": ".M38 1993" + }, + { + "050": { + "subfields": [ + { + "a": "PA522" + }, + { + "b": ".M38 1993" + } + ], + "ind1": "0", + "ind2": "0" } - ], - "ind1": "0", - "ind2": "0" - } - }, - { - "082": { - "subfields": [ - { - "a": "480" - }, - { - "2": "20" + }, + { + "082": { + "subfields": [ + { + "a": "480" + }, + { + "2": "20" + } + ], + "ind2": "0", + "ind1": "0" } - ], - "ind2": "0", - "ind1": "0" - } - }, - { - "100": { - "ind2": " ", - "subfields": [ - { - "a": "Mastronarde, Donald J." - }, - { - "9": "389" + }, + { + "100": { + "ind2": " ", + "subfields": [ + { + "a": "Mastronarde, Donald J." + }, + { + "9": "389" + } + ], + "ind1": "1" } - ], - "ind1": "1" - } - }, - { - "245": { - "ind1": "1", - "subfields": [ - { - "a": "Introduction to Attic Greek (Using mij) /" - }, - { - "c": "Donald J. Mastronarde." + }, + { + "245": { + "ind1": "1", + "subfields": [ + { + "a": "Introduction to Attic Greek (Using mij) /" + }, + { + "c": "Donald J. Mastronarde." + } + ], + "ind2": "0" } - ], - "ind2": "0" - } - }, - { - "260": { - "subfields": [ - { - "a": "Berkeley :" - }, - { - "b": "University of California Press," - }, - { - "c": "c1993." + }, + { + "260": { + "subfields": [ + { + "a": "Berkeley :" + }, + { + "b": "University of California Press," + }, + { + "c": "c1993." + } + ], + "ind2": " ", + "ind1": " " } - ], - "ind2": " ", - "ind1": " " - } - }, - { - "300": { - "ind1": " ", - "subfields": [ - { - "a": "ix, 425 p. :" - }, - { - "b": "maps ;" - }, - { - "c": "26 cm." + }, + { + "300": { + "ind1": " ", + "subfields": [ + { + "a": "ix, 425 p. :" + }, + { + "b": "maps ;" + }, + { + "c": "26 cm." + } + ], + "ind2": " " } - ], - "ind2": " " - } - }, - { - "500": { - "subfields": [ - { - "a": "Includes index." + }, + { + "500": { + "subfields": [ + { + "a": "Includes index." + } + ], + "ind1": " ", + "ind2": " " } - ], - "ind1": " ", - "ind2": " " - } - }, - { - "650": { - "subfields": [ - { - "a": "Attic Greek dialect" - }, - { - "9": "7" + }, + { + "650": { + "subfields": [ + { + "a": "Attic Greek dialect" + }, + { + "9": "7" + } + ], + "ind2": "0", + "ind1": " " } - ], - "ind2": "0", - "ind1": " " - } - }, - { - "856": { - "subfields": [ - { - "3": "Contributor biographical information" - }, - { - "u": "http://www.loc.gov/catdir/bios/ucal051/92021731.html" + }, + { + "856": { + "subfields": [ + { + "3": "Contributor biographical information" + }, + { + "u": "http://www.loc.gov/catdir/bios/ucal051/92021731.html" + } + ], + "ind2": "2", + "ind1": "4" } - ], - "ind2": "2", - "ind1": "4" - } - }, - { - "856": { - "ind1": "4", - "subfields": [ - { - "3": "Publisher description" - }, - { - "u": "http://www.loc.gov/catdir/description/ucal041/92021731.html" + }, + { + "856": { + "ind1": "4", + "subfields": [ + { + "3": "Publisher description" + }, + { + "u": "http://www.loc.gov/catdir/description/ucal041/92021731.html" + } + ], + "ind2": "2" } - ], - "ind2": "2" - } - }, - { - "906": { - "subfields": [ - { - "a": "7" - }, - { - "b": "cbc" - }, - { - "c": "orignew" - }, - { - "d": "1" - }, - { - "e": "ocip" - }, - { - "f": "19" - }, - { - "g": "y-gencatlg" + }, + { + "906": { + "subfields": [ + { + "a": "7" + }, + { + "b": "cbc" + }, + { + "c": "orignew" + }, + { + "d": "1" + }, + { + "e": "ocip" + }, + { + "f": "19" + }, + { + "g": "y-gencatlg" + } + ], + "ind1": " ", + "ind2": " " } - ], - "ind1": " ", - "ind2": " " - } - }, - { - "942": { - "subfields": [ - { - "2": "ddc" - }, - { - "c": "BK" + }, + { + "942": { + "subfields": [ + { + "2": "ddc" + }, + { + "c": "BK" + } + ], + "ind2": " ", + "ind1": " " } - ], - "ind2": " ", - "ind1": " " - } - }, - { - "955": { - "subfields": [ - { - "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" + }, + { + "955": { + "subfields": [ + { + "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" + } + ], + "ind2": " ", + "ind1": " " } - ], - "ind2": " ", - "ind1": " " - } - }, - { - "999": { - "subfields": [ - { - "c": "3" - }, - { - "d": "3" + }, + { + "999": { + "subfields": [ + { + "c": "3" + }, + { + "d": "3" + } + ], + "ind1": " ", + "ind2": " " } - ], - "ind1": " ", - "ind2": " " - } - } - ], - "leader": "01102pam a2200289 a 8500" -}|; + } + ], + "leader": "01102pam a2200289 a 8500" + }|; my $marc = q|01116pam a2200289 a 4500001000800000005001700008008004100025010001700066020002800083020002800111040001800139041001100157050002100168082001200189100003200201245007500233260005600308300003300364500002000397650002700417856009500444856008700539906004500626942001200671955013000683999001300813250439820221223213433.0920610s1993 caub s001 0 eng  a 92021731  a05200784384 (Test json) a05200784464 (Test json) aDLCcDLCdDLC0 aenggrc00aPA522b.M38 199300a4802201 aMastronarde, Donald J.938910aIntroduction to Attic Greek (Using usmarc) /cDonald J. Mastronarde. aBerkeley :bUniversity of California Press,cc1993. aix, 425 p. :bmaps ;c26 cm. aIncludes index. 0aAttic Greek dialect97423Contributor biographical informationuhttp://www.loc.gov/catdir/bios/ucal051/92021731.html423Publisher descriptionuhttp://www.loc.gov/catdir/description/ucal041/92021731.html a7bcbccorignewd1eocipf19gy-gencatlg 2ddccBK apc05 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 c715d715|; $t->put_ok("//$userid:$password@/api/v1/biblios/$biblionumber") @@ -1582,4 +1582,57 @@ subtest 'put() tests' => sub { is($biblio->title, 'Introduction to Attic Greek (Using usmarc) /'); $schema->storage->txn_rollback; +}; + +subtest 'list() tests' => sub { + plan tests => 14; + + $schema->storage->txn_begin; + + my $patron = $builder->build_object( + { + class => 'Koha::Patrons', + value => { flags => 0 } + } + ); + my $password = 'thePassword123'; + $patron->set_password( { password => $password, skip_validation => 1 } ); + $patron->discard_changes; + my $userid = $patron->userid; + + my $biblionumber1 = $builder->build_sample_biblio->biblionumber; + my $biblionumber2 = $builder->build_sample_biblio->biblionumber; + + my $search = "[{\"biblionumber\": \"$biblionumber1\"}, {\"biblionumber\": \"$biblionumber2\"}]"; + $t->get_ok( "//$userid:$password@/api/v1/biblios/" + => { 'x-koha-query' => $search } ) + ->status_is(403); + + $patron->flags(4)->store; + + $t->get_ok( "//$userid:$password@/api/v1/biblios/" + => { Accept => 'application/weird+format', 'x-koha-query' => $search } ) + ->status_is(400); + + $t->get_ok( "//$userid:$password@/api/v1/biblios/" + => { Accept => 'application/json', 'x-koha-query' => $search } ) + ->status_is(200); + + $t->get_ok( "//$userid:$password@/api/v1/biblios/" + => { Accept => 'application/marcxml+xml', 'x-koha-query' => $search } ) + ->status_is(200); + + $t->get_ok( "//$userid:$password@/api/v1/biblios/" + => { Accept => 'application/marc-in-json', 'x-koha-query' => $search } ) + ->status_is(200); + + $t->get_ok( "//$userid:$password@/api/v1/biblios/" + => { Accept => 'application/marc', 'x-koha-query' => $search } ) + ->status_is(200); + + $t->get_ok( "//$userid:$password@/api/v1/biblios/" + => { Accept => 'text/plain', 'x-koha-query' => $search } ) + ->status_is(200); + + $schema->storage->txn_rollback; }; \ No newline at end of file -- 2.25.1