8deee9da7dd988a24950597d7c526b1b643a78cc
[srvgit] / t / db_dependent / Koha / REST / Plugin / Objects.t
1 #!/usr/bin/perl
2
3 # This file is part of Koha.
4 #
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.
9 #
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.
14 #
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>.
17
18 use Modern::Perl;
19
20 use Koha::Acquisition::Orders;
21 use Koha::Cities;
22 use Koha::Biblios;
23 use Koha::Patrons;
24
25 use Mojo::JSON qw(encode_json);
26
27 # Dummy app for testing the plugin
28 use Mojolicious::Lite;
29
30 app->log->level('error');
31
32 plugin 'Koha::REST::Plugin::Objects';
33 plugin 'Koha::REST::Plugin::Query';
34 plugin 'Koha::REST::Plugin::Pagination';
35
36 get '/cities' => sub {
37     my $c = shift;
38     $c->validation->output($c->req->params->to_hash);
39     my $cities = $c->objects->search(Koha::Cities->new);
40     $c->render( status => 200, json => $cities );
41 };
42
43 get '/cities/:city_id' => sub {
44     my $c = shift;
45     my $id = $c->stash("city_id");
46     my $city = $c->objects->find(Koha::Cities->new, $id);
47     $c->render( status => 200, json => $city );
48 };
49
50 get '/orders' => sub {
51     my $c = shift;
52     $c->stash('koha.embed', ( { fund => {} } ) );
53     $c->validation->output($c->req->params->to_hash);
54     my $orders = $c->objects->search(Koha::Acquisition::Orders->new);
55     $c->render( status => 200, json => $orders );
56 };
57
58 get '/orders/:order_id' => sub {
59     my $c = shift;
60     $c->stash('koha.embed', ( { fund => {} } ) );
61     my $id = $c->stash("order_id");
62     my $order = $c->objects->find(Koha::Acquisition::Orders->new, $id);
63     $c->render( status => 200, json => $order );
64 };
65
66 get '/biblios' => sub {
67     my $c = shift;
68     my $output = $c->req->params->to_hash;
69     $output->{query} = $c->req->json if defined $c->req->json;
70     my $headers = $c->req->headers->to_hash;
71     $output->{'x-koha-query'} = $headers->{'x-koha-query'} if defined $headers->{'x-koha-query'};
72     $c->validation->output($output);
73     my $biblios_set = Koha::Biblios->new;
74     $c->stash("koha.embed", {
75         "suggestions" => {
76             children => {
77                 "suggester" => {}
78             }
79         }
80     });
81     my $biblios = $c->objects->search($biblios_set);
82     $c->render( status => 200, json => {count => scalar(@$biblios), biblios => $biblios} );
83 };
84
85 get '/libraries/:library_id_1/:library_id_2' => sub {
86
87     my $c = shift;
88
89     # Emulate a public route by stashing the is_public value
90     $c->stash( 'is_public' => 1 );
91
92     my $library_id_1 = $c->param('library_id_1');
93     my $library_id_2 = $c->param('library_id_2');
94
95     my $libraries_rs = Koha::Libraries->search(
96         { branchcode => [ $library_id_1, $library_id_2 ] },
97         { order_by   => 'branchname' }
98     );
99     my $libraries    = $c->objects->search( $libraries_rs );
100
101     $c->render(
102         status => 200,
103         json   => $libraries
104     );
105 };
106
107 get '/my_patrons' => sub {
108
109     my $c = shift;
110
111     my $patrons = $c->objects->search( scalar Koha::Patrons->search( {}, { order_by   => 'borrowernumber' }) );
112
113     $c->render(
114         status => 200,
115         json   => $patrons
116     );
117 };
118
119 # The tests
120 use Test::More tests => 14;
121 use Test::Mojo;
122
123 use t::lib::Mocks;
124 use t::lib::TestBuilder;
125 use Koha::Database;
126
127 my $schema  = Koha::Database->new()->schema();
128 my $builder = t::lib::TestBuilder->new;
129
130 subtest 'objects.search helper' => sub {
131
132     plan tests => 50;
133
134     $schema->storage->txn_begin;
135
136     # Remove existing cities to have more control on the search results
137     Koha::Cities->delete;
138
139     # Create three sample cities that match the query. This makes sure we
140     # always have a "next" link regardless of Mojolicious::Plugin::OpenAPI version.
141     $builder->build_object({
142         class => 'Koha::Cities',
143         value => {
144             city_name => 'Manuel'
145         }
146     });
147     $builder->build_object({
148         class => 'Koha::Cities',
149         value => {
150             city_name => 'Manuela'
151         }
152     });
153     $builder->build_object({
154         class => 'Koha::Cities',
155         value => {
156             city_name => 'Manuelab'
157         }
158     });
159
160     my $t = Test::Mojo->new;
161     $t->get_ok('/cities?name=manuel&_per_page=1&_page=1')
162         ->status_is(200)
163         ->header_like( 'Link' => qr/<http:\/\/.*[\?&]_page=2.*>; rel="next",/ )
164         ->json_has('/0')
165         ->json_hasnt('/1')
166         ->json_is('/0/name' => 'Manuel');
167
168     $builder->build_object({
169         class => 'Koha::Cities',
170         value => {
171             city_name => 'Emanuel'
172         }
173     });
174
175     # _match=starts_with
176     $t->get_ok('/cities?name=manuel&_per_page=4&_page=1&_match=starts_with')
177         ->status_is(200)
178         ->json_has('/0')
179         ->json_has('/1')
180         ->json_has('/2')
181         ->json_hasnt('/3')
182         ->json_is('/0/name' => 'Manuel')
183         ->json_is('/1/name' => 'Manuela')
184         ->json_is('/2/name' => 'Manuelab');
185
186     # _match=ends_with
187     $t->get_ok('/cities?name=manuel&_per_page=4&_page=1&_match=ends_with')
188         ->status_is(200)
189         ->json_has('/0')
190         ->json_has('/1')
191         ->json_hasnt('/2')
192         ->json_is('/0/name' => 'Manuel')
193         ->json_is('/1/name' => 'Emanuel');
194
195     # _match=exact
196     $t->get_ok('/cities?name=manuel&_per_page=4&_page=1&_match=exact')
197         ->status_is(200)
198         ->json_has('/0')
199         ->json_hasnt('/1')
200         ->json_is('/0/name' => 'Manuel');
201
202     # _match=contains
203     $t->get_ok('/cities?name=manuel&_per_page=4&_page=1&_match=contains')
204         ->status_is(200)
205         ->json_has('/0')
206         ->json_has('/1')
207         ->json_has('/2')
208         ->json_has('/3')
209         ->json_hasnt('/4')
210         ->json_is('/0/name' => 'Manuel')
211         ->json_is('/1/name' => 'Manuela')
212         ->json_is('/2/name' => 'Manuelab')
213         ->json_is('/3/name' => 'Emanuel');
214
215     # Add 20 more cities
216     for ( 1..20 ) {
217         $builder->build_object({ class => 'Koha::Cities' });
218     }
219
220     t::lib::Mocks::mock_preference('RESTdefaultPageSize', 20 );
221     $t->get_ok('/cities')
222       ->status_is(200);
223
224     my $response_count = scalar @{ $t->tx->res->json };
225     is( $response_count, 20, 'RESTdefaultPageSize is honoured by default (20)' );
226
227     t::lib::Mocks::mock_preference('RESTdefaultPageSize', 5 );
228     $t->get_ok('/cities')
229       ->status_is(200);
230
231     $response_count = scalar @{ $t->tx->res->json };
232     is( $response_count, 5, 'RESTdefaultPageSize is honoured by default (5)' );
233
234     $t->get_ok('/cities?_page=1&_per_page=-1')
235       ->status_is(200);
236
237     $response_count = scalar @{ $t->tx->res->json };
238     is( $response_count, 24, '_per_page=-1 means all resources' );
239
240     $t->get_ok('/cities?_page=100&_per_page=-1')
241       ->status_is(200);
242
243     $response_count = scalar @{ $t->tx->res->json };
244     is( $response_count, 24, 'When _per_page=-1 the page param is not considered' );
245
246     $schema->storage->txn_rollback;
247 };
248
249 subtest 'objects.search helper, sorting on mapped column' => sub {
250
251     plan tests => 42;
252
253     $schema->storage->txn_begin;
254
255     # Have complete control over the existing cities to ease testing
256     Koha::Cities->delete;
257
258     $builder->build_object({ class => 'Koha::Cities', value => { city_name => 'A', city_country => 'Argentina' } });
259     $builder->build_object({ class => 'Koha::Cities', value => { city_name => 'B', city_country => 'Argentina' } });
260     $builder->build_object({ class => 'Koha::Cities', value => { city_name => 'C', city_country => 'Argentina' } });
261     $builder->build_object({ class => 'Koha::Cities', value => { city_name => 'C', city_country => 'Belarus' } });
262
263     my $t = Test::Mojo->new;
264     # CSV-param
265     $t->get_ok('/cities?_order_by=%2Bname,-country')
266       ->status_is(200)
267       ->json_has('/0')
268       ->json_has('/1')
269       ->json_is('/0/name' => 'A')
270       ->json_is('/1/name' => 'B')
271       ->json_is('/2/name' => 'C')
272       ->json_is('/2/country' => 'Belarus')
273       ->json_is('/3/name' => 'C')
274       ->json_is('/3/country' => 'Argentina')
275       ->json_hasnt('/4');
276
277     # Multi-param: traditional
278     $t->get_ok('/cities?_order_by=%2Bname&_order_by=-country')
279       ->status_is(200)
280       ->json_has('/0')
281       ->json_has('/1')
282       ->json_is('/0/name' => 'A')
283       ->json_is('/1/name' => 'B')
284       ->json_is('/2/name' => 'C')
285       ->json_is('/2/country' => 'Belarus')
286       ->json_is('/3/name' => 'C')
287       ->json_is('/3/country' => 'Argentina')
288       ->json_hasnt('/4');
289
290     # Multi-param: PHP Style, Passes validation as above, subsequntly explodes
291     $t->get_ok('/cities?_order_by[]=%2Bname&_order_by[]=-country')
292       ->status_is(200)
293       ->json_has('/0')
294       ->json_has('/1')
295       ->json_is('/0/name' => 'A')
296       ->json_is('/1/name' => 'B')
297       ->json_is('/2/name' => 'C')
298       ->json_is('/2/country' => 'Belarus')
299       ->json_is('/3/name' => 'C')
300       ->json_is('/3/country' => 'Argentina')
301       ->json_hasnt('/4');
302
303     # Single-param
304     $t->get_ok('/cities?_order_by=-name')
305       ->status_is(200)
306       ->json_has('/0')
307       ->json_has('/1')
308       ->json_is('/0/name' => 'C')
309       ->json_is('/1/name' => 'C')
310       ->json_is('/2/name' => 'B')
311       ->json_is('/3/name' => 'A')
312       ->json_hasnt('/4');
313
314     $schema->storage->txn_rollback;
315 };
316
317 subtest 'objects.search helper, encoding' => sub {
318
319     plan tests => 5;
320
321     $schema->storage->txn_begin;
322
323     Koha::Cities->delete;
324
325     $builder->build_object({ class => 'Koha::Cities', value => { city_name => 'A', city_country => 'Argentina' } });
326     $builder->build_object({ class => 'Koha::Cities', value => { city_name => 'B', city_country => '❤Argentina❤' } });
327
328     my $t = Test::Mojo->new;
329     $t->get_ok('/cities?q={"country": "❤Argentina❤"}')
330       ->status_is(200)
331       ->json_has('/0')
332       ->json_hasnt('/1')
333       ->json_is('/0/name' => 'B');
334
335     $schema->storage->txn_rollback;
336 };
337
338 subtest 'objects.search helper, X-Total-Count and X-Base-Total-Count' => sub {
339
340     plan tests => 8;
341
342     $schema->storage->txn_begin;
343
344     Koha::Cities->delete;
345
346     my $long_city_name = 'Llanfairpwllgwyngyll';
347     for my $i ( 1 .. length($long_city_name) ) {
348         $builder->build_object(
349             {
350                 class => 'Koha::Cities',
351                 value => {
352                     city_name    => substr( $long_city_name, 0, $i ),
353                     city_country => 'Wales'
354                 }
355             }
356         );
357     }
358
359     my $t = Test::Mojo->new;
360     $t->get_ok('/cities?name=L&_per_page=10&_page=1&_match=starts_with')
361       ->status_is(200)
362       ->header_is( 'X-Total-Count' => 20, 'X-Total-Count header present' )
363       ->header_is( 'X-Base-Total-Count' => 20, 'X-Base-Total-Count header present' );
364
365     $t->get_ok('/cities?name=Llan&_per_page=10&_page=1&_match=starts_with')
366       ->status_is(200)
367       ->header_is( 'X-Total-Count' => 17, 'X-Total-Count header present' )
368       ->header_is('X-Base-Total-Count' => 20, 'X-Base-Total-Count header present' );
369
370     $schema->storage->txn_rollback;
371 };
372
373 subtest 'objects.search helper, embed' => sub {
374
375     plan tests => 2;
376
377     $schema->storage->txn_begin;
378
379     my $order = $builder->build_object({ class => 'Koha::Acquisition::Orders' });
380
381     my $t = Test::Mojo->new;
382     $t->get_ok('/orders?order_id=' . $order->ordernumber)
383       ->json_is('/0',$order->to_api({ embed => ( { fund => {} } ) }));
384
385     $schema->storage->txn_rollback;
386 };
387
388 subtest 'object.search helper with query parameter' => sub {
389     plan tests => 4;
390
391     $schema->storage->txn_begin;
392
393     my $patron1 = $builder->build_object( { class => "Koha::Patrons" } );
394     my $patron2 = $builder->build_object( { class => "Koha::Patrons" } );
395     my $biblio1 = $builder->build_sample_biblio;
396     my $biblio2 = $builder->build_sample_biblio;
397     my $biblio3 = $builder->build_sample_biblio;
398     my $suggestion1 = $builder->build_object( { class => "Koha::Suggestions", value => { suggestedby => $patron1->borrowernumber, biblionumber => $biblio1->biblionumber} } );
399     my $suggestion2 = $builder->build_object( { class => "Koha::Suggestions", value => { suggestedby => $patron2->borrowernumber, biblionumber => $biblio2->biblionumber} } );
400     my $suggestion3 = $builder->build_object( { class => "Koha::Suggestions", value => { suggestedby => $patron2->borrowernumber, biblionumber => $biblio3->biblionumber} } );
401
402     my $t = Test::Mojo->new;
403     $t->get_ok('/biblios' => json => {"suggestions.suggester.patron_id" => $patron1->borrowernumber })
404       ->json_is('/count' => 1, 'there should be 1 biblio with suggestions of patron 1');
405
406     $t->get_ok('/biblios' => json => {"suggestions.suggester.patron_id" => $patron2->borrowernumber })
407       ->json_is('/count' => 2, 'there should be 2 biblios with suggestions of patron 2');
408
409     $schema->storage->txn_rollback;
410 };
411
412 subtest 'object.search helper with q parameter' => sub {
413     plan tests => 4;
414
415     $schema->storage->txn_begin;
416
417     my $patron1 = $builder->build_object( { class => "Koha::Patrons" } );
418     my $patron2 = $builder->build_object( { class => "Koha::Patrons" } );
419     my $biblio1 = $builder->build_sample_biblio;
420     my $biblio2 = $builder->build_sample_biblio;
421     my $biblio3 = $builder->build_sample_biblio;
422     my $suggestion1 = $builder->build_object( { class => "Koha::Suggestions", value => { suggestedby => $patron1->borrowernumber, biblionumber => $biblio1->biblionumber} } );
423     my $suggestion2 = $builder->build_object( { class => "Koha::Suggestions", value => { suggestedby => $patron2->borrowernumber, biblionumber => $biblio2->biblionumber} } );
424     my $suggestion3 = $builder->build_object( { class => "Koha::Suggestions", value => { suggestedby => $patron2->borrowernumber, biblionumber => $biblio3->biblionumber} } );
425
426     my $t = Test::Mojo->new;
427     $t->get_ok('/biblios?q={"suggestions.suggester.patron_id": "'.$patron1->borrowernumber.'"}')
428       ->json_is('/count' => 1, 'there should be 1 biblio with suggestions of patron 1');
429
430     $t->get_ok('/biblios?q={"suggestions.suggester.patron_id": "'.$patron2->borrowernumber.'"}')
431       ->json_is('/count' => 2, 'there should be 2 biblios with suggestions of patron 2');
432
433     $schema->storage->txn_rollback;
434 };
435
436 subtest 'object.search helper with x-koha-query header' => sub {
437     plan tests => 4;
438
439     $schema->storage->txn_begin;
440
441     my $patron1 = $builder->build_object( { class => "Koha::Patrons" } );
442     my $patron2 = $builder->build_object( { class => "Koha::Patrons" } );
443     my $biblio1 = $builder->build_sample_biblio;
444     my $biblio2 = $builder->build_sample_biblio;
445     my $biblio3 = $builder->build_sample_biblio;
446     my $suggestion1 = $builder->build_object( { class => "Koha::Suggestions", value => { suggestedby => $patron1->borrowernumber, biblionumber => $biblio1->biblionumber} } );
447     my $suggestion2 = $builder->build_object( { class => "Koha::Suggestions", value => { suggestedby => $patron2->borrowernumber, biblionumber => $biblio2->biblionumber} } );
448     my $suggestion3 = $builder->build_object( { class => "Koha::Suggestions", value => { suggestedby => $patron2->borrowernumber, biblionumber => $biblio3->biblionumber} } );
449
450     my $t = Test::Mojo->new;
451     $t->get_ok('/biblios' => {'x-koha-query' => '{"suggestions.suggester.patron_id": "'.$patron1->borrowernumber.'"}'})
452       ->json_is('/count' => 1, 'there should be 1 biblio with suggestions of patron 1');
453
454     $t->get_ok('/biblios' => {'x-koha-query' => '{"suggestions.suggester.patron_id": "'.$patron2->borrowernumber.'"}'})
455       ->json_is('/count' => 2, 'there should be 2 biblios with suggestions of patron 2');
456
457     $schema->storage->txn_rollback;
458 };
459
460 subtest 'object.search helper with all query methods' => sub {
461     plan tests => 6;
462
463     $schema->storage->txn_begin;
464
465     my $patron1 = $builder->build_object( { class => "Koha::Patrons" , value => {firstname=>'patron1'} } );
466     my $patron2 = $builder->build_object( { class => "Koha::Patrons" , value => {firstname=>'patron2'} } );
467     my $biblio1 = $builder->build_sample_biblio;
468     my $biblio2 = $builder->build_sample_biblio;
469     my $biblio3 = $builder->build_sample_biblio;
470     my $suggestion1 = $builder->build_object( { class => "Koha::Suggestions", value => { suggestedby => $patron1->borrowernumber, biblionumber => $biblio1->biblionumber} } );
471     my $suggestion2 = $builder->build_object( { class => "Koha::Suggestions", value => { suggestedby => $patron2->borrowernumber, biblionumber => $biblio2->biblionumber} } );
472     my $suggestion3 = $builder->build_object( { class => "Koha::Suggestions", value => { suggestedby => $patron2->borrowernumber, biblionumber => $biblio3->biblionumber} } );
473
474     my $t = Test::Mojo->new;
475     $t->get_ok('/biblios?q={"suggestions.suggester.firstname": "'.$patron1->firstname.'"}' => {'x-koha-query' => '{"suggestions.suggester.patron_id": "'.$patron1->borrowernumber.'"}'} => json => {"suggestions.suggester.cardnumber" => $patron1->cardnumber})
476       ->json_is('/count' => 1, 'there should be 1 biblio with suggestions of patron 1');
477
478     $t->get_ok('/biblios?q={"suggestions.suggester.firstname": "'.$patron2->firstname.'"}' => {'x-koha-query' => '{"suggestions.suggester.patron_id": "'.$patron2->borrowernumber.'"}'} => json => {"suggestions.suggester.cardnumber" => $patron2->cardnumber})
479       ->json_is('/count' => 2, 'there should be 2 biblios with suggestions of patron 2');
480
481     $t->get_ok('/biblios?q={"suggestions.suggester.firstname": "'.$patron1->firstname.'"}' => {'x-koha-query' => '{"suggestions.suggester.patron_id": "'.$patron2->borrowernumber.'"}'} => json => {"suggestions.suggester.cardnumber" => $patron2->cardnumber})
482       ->json_is('/count' => 0, 'there shouldn\'t be biblios where suggester has patron1 fistname and patron2 id');
483
484     $schema->storage->txn_rollback;
485 };
486
487 subtest 'object.search helper order by embedded columns' => sub {
488
489     plan tests => 3;
490
491     $schema->storage->txn_begin;
492
493     my $patron1 = $builder->build_object( { class => "Koha::Patrons" , value => {firstname=>'patron1'} } );
494     my $patron2 = $builder->build_object( { class => "Koha::Patrons" , value => {firstname=>'patron2'} } );
495     my $biblio1 = $builder->build_sample_biblio;
496     my $biblio2 = $builder->build_sample_biblio;
497     my $suggestion1 = $builder->build_object( { class => "Koha::Suggestions", value => { suggestedby => $patron1->borrowernumber, biblionumber => $biblio1->biblionumber} } );
498     my $suggestion2 = $builder->build_object( { class => "Koha::Suggestions", value => { suggestedby => $patron2->borrowernumber, biblionumber => $biblio2->biblionumber} } );
499
500     my $t = Test::Mojo->new;
501     $t->get_ok('/biblios?_order_by=-suggestions.suggester.firstname' => json => [{"me.biblio_id" => $biblio1->biblionumber}, {"me.biblio_id" => $biblio2->biblionumber}])
502       ->json_is('/biblios/0/biblio_id' => $biblio2->biblionumber, 'Biblio 2 should be first')
503       ->json_is('/biblios/1/biblio_id' => $biblio1->biblionumber, 'Biblio 1 should be second');
504
505     $schema->storage->txn_rollback;
506 };
507
508 subtest 'objects.find helper' => sub {
509
510     plan tests => 9;
511
512     my $t = Test::Mojo->new;
513
514     $schema->storage->txn_begin;
515
516     my $city_1 = $builder->build_object( { class => 'Koha::Cities' } );
517     my $city_2 = $builder->build_object( { class => 'Koha::Cities' } );
518
519     $t->get_ok( '/cities/' . $city_1->id )
520       ->status_is(200)
521       ->json_is( $city_1->to_api );
522
523     $t->get_ok( '/cities/' . $city_2->id )
524       ->status_is(200)
525       ->json_is( $city_2->to_api );
526
527     # Remove the city
528     my $city_2_id = $city_2->id;
529     $city_2->delete;
530     $t->get_ok( '/cities/' . $city_2_id )
531       ->status_is(200)
532       ->json_is( undef );
533
534     $schema->storage->txn_rollback;
535 };
536
537 subtest 'objects.find helper, embed' => sub {
538
539     plan tests => 2;
540
541     my $t = Test::Mojo->new;
542
543     $schema->storage->txn_begin;
544
545     my $order = $builder->build_object({ class => 'Koha::Acquisition::Orders' });
546
547     $t->get_ok( '/orders/' . $order->ordernumber )
548       ->json_is( $order->to_api( { embed => ( { fund => {} } ) } ) );
549
550     $schema->storage->txn_rollback;
551 };
552
553 subtest 'objects.search helper, public requests' => sub {
554
555     plan tests => 3;
556
557     $schema->storage->txn_begin;
558
559     my $library_1 = $builder->build_object({ class => 'Koha::Libraries', value => { branchname => 'A' } });
560     my $library_2 = $builder->build_object({ class => 'Koha::Libraries', value => { branchname => 'B' } });
561
562     my $t = Test::Mojo->new;
563
564     $t->get_ok( '/libraries/'.$library_1->id.'/'.$library_2->id )
565       ->json_is('/0' => $library_1->to_api({ public => 1 }), 'Public representation of $library_1 is retrieved')
566       ->json_is('/1' => $library_2->to_api({ public => 1 }), 'Public representation of $library_2 is retrieved');
567
568     $schema->storage->txn_rollback;
569 };
570
571 subtest 'objects.search helper, search_limited() tests' => sub {
572
573     plan tests => 9;
574
575     $schema->storage->txn_begin;
576
577     my $library_1 = $builder->build_object({ class => 'Koha::Libraries' });
578     my $library_2 = $builder->build_object({ class => 'Koha::Libraries' });
579
580     my $patron_1 = $builder->build_object({ class => 'Koha::Patrons', value => { branchcode => $library_1->id } });
581     my $patron_2 = $builder->build_object({ class => 'Koha::Patrons', value => { branchcode => $library_1->id } });
582     my $patron_3 = $builder->build_object({ class => 'Koha::Patrons', value => { branchcode => $library_2->id } });
583
584     my @libraries_where_can_see_patrons = ( $library_1->id, $library_2->id );
585
586     my $t = Test::Mojo->new;
587
588     my $mocked_patron = Test::MockModule->new('Koha::Patron');
589     $mocked_patron->mock( 'libraries_where_can_see_patrons', sub
590         {
591             return @libraries_where_can_see_patrons;
592         }
593     );
594
595     my $patron = $builder->build_object(
596         {
597             class => 'Koha::Patrons',
598             value => { flags => 2**4 }    # borrowers flag = 4
599         }
600     );
601
602     t::lib::Mocks::mock_userenv({ patron => $patron });
603
604     $t->get_ok( "/my_patrons?q=" . encode_json( { library_id => [ $library_1->id, $library_2->id ] } ) )
605       ->status_is(200)
606       ->json_is( '/0/patron_id' => $patron_1->id )
607       ->json_is( '/1/patron_id' => $patron_2->id )
608       ->json_is( '/2/patron_id' => $patron_3->id );
609
610     @libraries_where_can_see_patrons = ( $library_2->id );
611
612     my $res = $t->get_ok( "/my_patrons?q=" . encode_json( { library_id => [ $library_1->id, $library_2->id ] } ) )
613       ->status_is(200)
614       ->json_is( '/0/patron_id' => $patron_3->id, 'Returns the only allowed patron' )
615       ->tx->res->json;
616
617     is( scalar @{$res}, 1, 'Only one patron returned' );
618
619     $schema->storage->txn_rollback;
620 };