use Modern::Perl;
use Koha::Acquisition::Orders;
+use Koha::AuthorisedValueCategories;
+use Koha::AuthorisedValues;
use Koha::Cities;
-use Koha::Holds;
use Koha::Biblios;
+use Koha::Patrons;
+
+use Mojo::JSON qw(encode_json);
# Dummy app for testing the plugin
use Mojolicious::Lite;
$c->render( status => 200, json => $cities );
};
+get '/cities/:city_id' => sub {
+ my $c = shift;
+ my $id = $c->stash("city_id");
+ my $city = $c->objects->find(Koha::Cities->new, $id);
+ $c->render( status => 200, json => $city );
+};
+
get '/orders' => sub {
my $c = shift;
$c->stash('koha.embed', ( { fund => {} } ) );
$c->render( status => 200, json => $orders );
};
-get '/patrons/:patron_id/holds' => sub {
+get '/orders/:order_id' => sub {
my $c = shift;
- my $params = $c->req->params->to_hash;
- $params->{patron_id} = $c->stash("patron_id");
- $c->validation->output($params);
- my $holds_set = Koha::Holds->new;
- my $holds = $c->objects->search( $holds_set );
- $c->render( status => 200, json => {count => scalar(@$holds)} );
+ $c->stash('koha.embed', ( { fund => {} } ) );
+ my $id = $c->stash("order_id");
+ my $order = $c->objects->find(Koha::Acquisition::Orders->new, $id);
+ $c->render( status => 200, json => $order );
};
get '/biblios' => sub {
$c->render( status => 200, json => {count => scalar(@$biblios), biblios => $biblios} );
};
+get '/libraries/:library_id_1/:library_id_2' => sub {
+
+ my $c = shift;
+
+ # Emulate a public route by stashing the is_public value
+ $c->stash( 'is_public' => 1 );
+
+ my $library_id_1 = $c->param('library_id_1');
+ my $library_id_2 = $c->param('library_id_2');
+
+ my $libraries_rs = Koha::Libraries->search(
+ { branchcode => [ $library_id_1, $library_id_2 ] },
+ { order_by => 'branchname' }
+ );
+ my $libraries = $c->objects->search( $libraries_rs );
+
+ $c->render(
+ status => 200,
+ json => $libraries
+ );
+};
+
+get '/my_patrons' => sub {
+
+ my $c = shift;
+
+ my $patrons = $c->objects->search( scalar Koha::Patrons->search( {}, { order_by => 'borrowernumber' }) );
+
+ $c->render(
+ status => 200,
+ json => $patrons
+ );
+};
# The tests
-use Test::More tests => 11;
+use Test::More tests => 16;
use Test::Mojo;
use t::lib::Mocks;
subtest 'objects.search helper, sorting on mapped column' => sub {
- plan tests => 14;
+ plan tests => 42;
$schema->storage->txn_begin;
$builder->build_object({ class => 'Koha::Cities', value => { city_name => 'A', city_country => 'Argentina' } });
$builder->build_object({ class => 'Koha::Cities', value => { city_name => 'B', city_country => 'Argentina' } });
+ $builder->build_object({ class => 'Koha::Cities', value => { city_name => 'C', city_country => 'Argentina' } });
+ $builder->build_object({ class => 'Koha::Cities', value => { city_name => 'C', city_country => 'Belarus' } });
my $t = Test::Mojo->new;
- $t->get_ok('/cities?_order_by=%2Bname&_order_by=+country')
+ # CSV-param
+ $t->get_ok('/cities?_order_by=%2Bname,-country')
->status_is(200)
->json_has('/0')
->json_has('/1')
- ->json_hasnt('/2')
->json_is('/0/name' => 'A')
- ->json_is('/1/name' => 'B');
-
+ ->json_is('/1/name' => 'B')
+ ->json_is('/2/name' => 'C')
+ ->json_is('/2/country' => 'Belarus')
+ ->json_is('/3/name' => 'C')
+ ->json_is('/3/country' => 'Argentina')
+ ->json_hasnt('/4');
+
+ # Multi-param: traditional
+ $t->get_ok('/cities?_order_by=%2Bname&_order_by=-country')
+ ->status_is(200)
+ ->json_has('/0')
+ ->json_has('/1')
+ ->json_is('/0/name' => 'A')
+ ->json_is('/1/name' => 'B')
+ ->json_is('/2/name' => 'C')
+ ->json_is('/2/country' => 'Belarus')
+ ->json_is('/3/name' => 'C')
+ ->json_is('/3/country' => 'Argentina')
+ ->json_hasnt('/4');
+
+ # Multi-param: PHP Style, Passes validation as above, subsequntly explodes
+ $t->get_ok('/cities?_order_by[]=%2Bname&_order_by[]=-country')
+ ->status_is(200)
+ ->json_has('/0')
+ ->json_has('/1')
+ ->json_is('/0/name' => 'A')
+ ->json_is('/1/name' => 'B')
+ ->json_is('/2/name' => 'C')
+ ->json_is('/2/country' => 'Belarus')
+ ->json_is('/3/name' => 'C')
+ ->json_is('/3/country' => 'Argentina')
+ ->json_hasnt('/4');
+
+ # Single-param
$t->get_ok('/cities?_order_by=-name')
->status_is(200)
->json_has('/0')
->json_has('/1')
- ->json_hasnt('/2')
- ->json_is('/0/name' => 'B')
- ->json_is('/1/name' => 'A');
+ ->json_is('/0/name' => 'C')
+ ->json_is('/1/name' => 'C')
+ ->json_is('/2/name' => 'B')
+ ->json_is('/3/name' => 'A')
+ ->json_hasnt('/4');
$schema->storage->txn_rollback;
};
$schema->storage->txn_rollback;
};
-subtest 'objects.search helper, with path parameters and _match' => sub {
- plan tests => 8;
-
- $schema->storage->txn_begin;
-
- Koha::Holds->search()->delete;
-
- my $patron = Koha::Patrons->find(10);
- $patron->delete if $patron;
- $patron = $builder->build_object( { class => "Koha::Patrons" } );
- $patron->borrowernumber(10)->store;
- $builder->build_object(
- {
- class => "Koha::Holds",
- value => { borrowernumber => $patron->borrowernumber }
- }
- );
-
- my $t = Test::Mojo->new;
- $t->get_ok('/patrons/1/holds?_match=exact')
- ->json_is('/count' => 0, 'there should be no holds for borrower 1 with _match=exact');
-
- $t->get_ok('/patrons/1/holds?_match=contains')
- ->json_is('/count' => 0, 'there should be no holds for borrower 1 with _match=contains');
-
- $t->get_ok('/patrons/10/holds?_match=exact')
- ->json_is('/count' => 1, 'there should be 1 hold for borrower 10 with _match=exact');
-
- $t->get_ok('/patrons/10/holds?_match=contains')
- ->json_is('/count' => 1, 'there should be 1 hold for borrower 10 with _match=contains');
-
- $schema->storage->txn_rollback;
-};
-
-subtest 'object.search helper with query parameter' => sub {
+subtest 'objects.search helper with query parameter' => sub {
plan tests => 4;
$schema->storage->txn_begin;
$schema->storage->txn_rollback;
};
-subtest 'object.search helper with q parameter' => sub {
+subtest 'objects.search helper with q parameter' => sub {
plan tests => 4;
$schema->storage->txn_begin;
$schema->storage->txn_rollback;
};
-subtest 'object.search helper with x-koha-query header' => sub {
+subtest 'objects.search helper with x-koha-query header' => sub {
plan tests => 4;
$schema->storage->txn_begin;
$schema->storage->txn_rollback;
};
-subtest 'object.search helper with all query methods' => sub {
+subtest 'objects.search helper with all query methods' => sub {
plan tests => 6;
$schema->storage->txn_begin;
$schema->storage->txn_rollback;
};
-subtest 'object.search helper order by embedded columns' => sub {
+subtest 'objects.search helper order by embedded columns' => sub {
plan tests => 3;
+ $schema->storage->txn_begin;
+
my $patron1 = $builder->build_object( { class => "Koha::Patrons" , value => {firstname=>'patron1'} } );
my $patron2 = $builder->build_object( { class => "Koha::Patrons" , value => {firstname=>'patron2'} } );
my $biblio1 = $builder->build_sample_biblio;
->json_is('/biblios/0/biblio_id' => $biblio2->biblionumber, 'Biblio 2 should be first')
->json_is('/biblios/1/biblio_id' => $biblio1->biblionumber, 'Biblio 1 should be second');
+ $schema->storage->txn_rollback;
+};
+
+subtest 'objects.find helper' => sub {
+
+ plan tests => 9;
+
+ my $t = Test::Mojo->new;
+
+ $schema->storage->txn_begin;
+
+ my $city_1 = $builder->build_object( { class => 'Koha::Cities' } );
+ my $city_2 = $builder->build_object( { class => 'Koha::Cities' } );
+
+ $t->get_ok( '/cities/' . $city_1->id )
+ ->status_is(200)
+ ->json_is( $city_1->to_api );
+
+ $t->get_ok( '/cities/' . $city_2->id )
+ ->status_is(200)
+ ->json_is( $city_2->to_api );
+
+ # Remove the city
+ my $city_2_id = $city_2->id;
+ $city_2->delete;
+ $t->get_ok( '/cities/' . $city_2_id )
+ ->status_is(200)
+ ->json_is( undef );
+
+ $schema->storage->txn_rollback;
+};
+
+subtest 'objects.find helper, embed' => sub {
+
+ plan tests => 2;
+
+ my $t = Test::Mojo->new;
+
+ $schema->storage->txn_begin;
+
+ my $order = $builder->build_object({ class => 'Koha::Acquisition::Orders' });
+
+ $t->get_ok( '/orders/' . $order->ordernumber )
+ ->json_is( $order->to_api( { embed => ( { fund => {} } ) } ) );
+
+ $schema->storage->txn_rollback;
+};
+
+subtest 'objects.search helper, public requests' => sub {
+
+ plan tests => 3;
+
+ $schema->storage->txn_begin;
+
+ my $library_1 = $builder->build_object({ class => 'Koha::Libraries', value => { branchname => 'A' } });
+ my $library_2 = $builder->build_object({ class => 'Koha::Libraries', value => { branchname => 'B' } });
+
+ my $t = Test::Mojo->new;
+
+ $t->get_ok( '/libraries/'.$library_1->id.'/'.$library_2->id )
+ ->json_is('/0' => $library_1->to_api({ public => 1 }), 'Public representation of $library_1 is retrieved')
+ ->json_is('/1' => $library_2->to_api({ public => 1 }), 'Public representation of $library_2 is retrieved');
+
+ $schema->storage->txn_rollback;
+};
+
+subtest 'objects.search helper, search_limited() tests' => sub {
+
+ plan tests => 9;
+
$schema->storage->txn_begin;
-}
+
+ my $library_1 = $builder->build_object({ class => 'Koha::Libraries' });
+ my $library_2 = $builder->build_object({ class => 'Koha::Libraries' });
+
+ my $patron_1 = $builder->build_object({ class => 'Koha::Patrons', value => { branchcode => $library_1->id } });
+ my $patron_2 = $builder->build_object({ class => 'Koha::Patrons', value => { branchcode => $library_1->id } });
+ my $patron_3 = $builder->build_object({ class => 'Koha::Patrons', value => { branchcode => $library_2->id } });
+
+ my @libraries_where_can_see_patrons = ( $library_1->id, $library_2->id );
+
+ my $t = Test::Mojo->new;
+
+ my $mocked_patron = Test::MockModule->new('Koha::Patron');
+ $mocked_patron->mock( 'libraries_where_can_see_patrons', sub
+ {
+ return @libraries_where_can_see_patrons;
+ }
+ );
+
+ my $patron = $builder->build_object(
+ {
+ class => 'Koha::Patrons',
+ value => { flags => 2**4 } # borrowers flag = 4
+ }
+ );
+
+ t::lib::Mocks::mock_userenv({ patron => $patron });
+
+ $t->get_ok( "/my_patrons?q=" . encode_json( { library_id => [ $library_1->id, $library_2->id ] } ) )
+ ->status_is(200)
+ ->json_is( '/0/patron_id' => $patron_1->id )
+ ->json_is( '/1/patron_id' => $patron_2->id )
+ ->json_is( '/2/patron_id' => $patron_3->id );
+
+ @libraries_where_can_see_patrons = ( $library_2->id );
+
+ my $res = $t->get_ok( "/my_patrons?q=" . encode_json( { library_id => [ $library_1->id, $library_2->id ] } ) )
+ ->status_is(200)
+ ->json_is( '/0/patron_id' => $patron_3->id, 'Returns the only allowed patron' )
+ ->tx->res->json;
+
+ is( scalar @{$res}, 1, 'Only one patron returned' );
+
+ $schema->storage->txn_rollback;
+};
+
+subtest 'objects.find helper with expanded authorised values' => sub {
+
+ plan tests => 18;
+
+ $schema->storage->txn_begin;
+
+ my $t = Test::Mojo->new;
+
+ Koha::AuthorisedValues->search( { category => 'Countries' } )->delete;
+ Koha::AuthorisedValueCategories->search( { category_name => 'Countries' } )
+ ->delete;
+
+ my $cat = $builder->build_object(
+ {
+ class => 'Koha::AuthorisedValueCategories',
+ value => { category_name => 'Countries' }
+ }
+ );
+ my $fr = $builder->build_object(
+ {
+ class => 'Koha::AuthorisedValues',
+ value => {
+ authorised_value => 'FR',
+ lib => 'France',
+ category => $cat->category_name
+ }
+ }
+ );
+ my $us = $builder->build_object(
+ {
+ class => 'Koha::AuthorisedValues',
+ value => {
+ authorised_value => 'US',
+ lib => 'United States of America',
+ category => $cat->category_name
+ }
+ }
+ );
+ my $ar = $builder->build_object(
+ {
+ class => 'Koha::AuthorisedValues',
+ value => {
+ authorised_value => 'AR',
+ lib => 'Argentina',
+ category => $cat->category_name
+ }
+ }
+ );
+
+ my $city_class = Test::MockModule->new('Koha::City');
+ $city_class->mock(
+ 'api_av_mapping',
+ sub {
+ my ($self, $params) = @_;
+ use Koha::AuthorisedValues;
+
+ my $av = Koha::AuthorisedValues->find(
+ {
+ authorised_value => $self->city_country,
+ category => 'Countries'
+ }
+ );
+
+ return {
+ city_country => {
+ category => $av->category,
+ str => ( $params->{public} ) ? $av->lib_opac : $av->lib,
+ type => 'av',
+ }
+ };
+ }
+ );
+
+ my $manuel = $builder->build_object(
+ {
+ class => 'Koha::Cities',
+ value => {
+ city_name => 'Manuel',
+ city_country => 'AR'
+ }
+ }
+ );
+ my $manuela = $builder->build_object(
+ {
+ class => 'Koha::Cities',
+ value => {
+ city_name => 'Manuela',
+ city_country => 'US'
+ }
+ }
+ );
+
+ $t->get_ok( '/cities/' . $manuel->id => { 'x-koha-av-expand' => 1 } )
+ ->status_is(200)->json_is( '/name' => 'Manuel' )
+ ->json_has('/_str')
+ ->json_is( '/_str/country/type' => 'av' )
+ ->json_is( '/_str/country/category' => $cat->category_name )
+ ->json_is( '/_str/country/str' => $ar->lib );
+
+ $t->get_ok( '/cities/' . $manuel->id => { 'x-koha-av-expand' => 0 } )
+ ->status_is(200)->json_is( '/name' => 'Manuel' )
+ ->json_hasnt('/_str');
+
+ $t->get_ok( '/cities/' . $manuela->id => { 'x-koha-av-expand' => 1 } )
+ ->status_is(200)->json_is( '/name' => 'Manuela' )
+ ->json_has('/_str')
+ ->json_is( '/_str/country/type' => 'av' )
+ ->json_is( '/_str/country/category' => $cat->category_name )
+ ->json_is( '/_str/country/str' => $us->lib );
+
+ $schema->storage->txn_rollback;
+};
+
+subtest 'objects.search helper with expanded authorised values' => sub {
+
+ plan tests => 24;
+
+ my $t = Test::Mojo->new;
+
+ $schema->storage->txn_begin;
+
+ Koha::AuthorisedValues->search( { category => 'Countries' } )->delete;
+ Koha::AuthorisedValueCategories->search( { category_name => 'Countries' } )
+ ->delete;
+
+ my $cat = $builder->build_object(
+ {
+ class => 'Koha::AuthorisedValueCategories',
+ value => { category_name => 'Countries' }
+ }
+ );
+ my $fr = $builder->build_object(
+ {
+ class => 'Koha::AuthorisedValues',
+ value => {
+ authorised_value => 'FR',
+ lib => 'France',
+ category => $cat->category_name
+ }
+ }
+ );
+ my $us = $builder->build_object(
+ {
+ class => 'Koha::AuthorisedValues',
+ value => {
+ authorised_value => 'US',
+ lib => 'United States of America',
+ category => $cat->category_name
+ }
+ }
+ );
+ my $ar = $builder->build_object(
+ {
+ class => 'Koha::AuthorisedValues',
+ value => {
+ authorised_value => 'AR',
+ lib => 'Argentina',
+ category => $cat->category_name
+ }
+ }
+ );
+
+ my $city_class = Test::MockModule->new('Koha::City');
+ $city_class->mock(
+ 'api_av_mapping',
+ sub {
+ my ($self, $params) = @_;
+ use Koha::AuthorisedValues;
+
+ my $av = Koha::AuthorisedValues->find(
+ {
+ authorised_value => $self->city_country,
+ category => 'Countries'
+ }
+ );
+
+ return {
+ city_country => {
+ category => $av->category,
+ str => ( $params->{public} ) ? $av->lib_opac : $av->lib,
+ type => 'av',
+ }
+ };
+ }
+ );
+
+
+ $builder->build_object(
+ {
+ class => 'Koha::Cities',
+ value => {
+ city_name => 'Manuel',
+ city_country => 'AR'
+ }
+ }
+ );
+ $builder->build_object(
+ {
+ class => 'Koha::Cities',
+ value => {
+ city_name => 'Manuela',
+ city_country => 'US'
+ }
+ }
+ );
+
+ $t->get_ok( '/cities?name=manuel&_per_page=4&_page=1&_match=starts_with' =>
+ { 'x-koha-av-expand' => 1 } )->status_is(200)
+ ->json_has('/0')->json_has('/1')->json_hasnt('/2')
+ ->json_is( '/0/name' => 'Manuel' )
+ ->json_has('/0/_str')
+ ->json_is( '/0/_str/country/str' => $ar->lib )
+ ->json_is( '/0/_str/country/type' => 'av' )
+ ->json_is( '/0/_str/country/category' => $cat->category_name )
+ ->json_is( '/1/name' => 'Manuela' )
+ ->json_has('/1/_str')
+ ->json_is( '/1/_str/country/str' => $us->lib )
+ ->json_is( '/1/_str/country/type' => 'av' )
+ ->json_is( '/1/_str/country/category' => $cat->category_name );
+
+ $t->get_ok( '/cities?name=manuel&_per_page=4&_page=1&_match=starts_with' =>
+ { 'x-koha-av-expand' => 0 } )->status_is(200)
+ ->json_has('/0')->json_has('/1')->json_hasnt('/2')
+ ->json_is( '/0/name' => 'Manuel' )->json_hasnt('/0/_str')
+ ->json_is( '/1/name' => 'Manuela' )->json_hasnt('/1/_str');
+
+
+ $schema->storage->txn_rollback;
+};