Bug 24502: object.search also filter by prefetched columns
[koha.git] / t / Koha / REST / Plugin / Query.t
blob0ddd6fcb0a7bbb4b9627e75f8846a36093ba22ef
1 #!/usr/bin/perl
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>.
18 use Modern::Perl;
20 # Dummy app for testing the plugin
21 use Mojolicious::Lite;
22 use Try::Tiny;
24 use Koha::Cities;
25 use Koha::Holds;
26 use Koha::Biblios;
28 app->log->level('error');
30 plugin 'Koha::REST::Plugin::Query';
32 get '/empty' => sub {
33 my $c = shift;
34 $c->render( json => undef, status => 200 );
37 get '/query' => sub {
38 my $c = shift;
39 my ( $filtered_params, $reserved_params ) = $c->extract_reserved_params($c->req->params->to_hash);
40 $c->render(
41 json => {
42 filtered_params => $filtered_params,
43 reserved_params => $reserved_params
45 status => 200
49 get '/query_full/:id/:subid' => sub {
50 my $c = shift;
51 my $params = $c->req->params->to_hash;
52 $params->{id} = $c->stash->{id};
53 $params->{subid} = $c->stash->{subid};
54 my ( $filtered_params, $reserved_params, $path_params ) = $c->extract_reserved_params($params);
55 $c->render(
56 json => {
57 filtered_params => $filtered_params,
58 reserved_params => $reserved_params,
59 path_params => $path_params
61 status => 200
65 get '/dbic_merge_sorting' => sub {
66 my $c = shift;
67 my $attributes = { a => 'a', b => 'b' };
68 $attributes = $c->dbic_merge_sorting(
70 attributes => $attributes,
71 params => { _match => 'exact', _order_by => [ 'uno', '-dos', '+tres', ' cuatro' ] }
74 $c->render( json => $attributes, status => 200 );
77 get '/dbic_merge_sorting_single' => sub {
78 my $c = shift;
79 my $attributes = { a => 'a', b => 'b' };
80 $attributes = $c->dbic_merge_sorting(
82 attributes => $attributes,
83 params => { _match => 'exact', _order_by => '-uno' }
86 $c->render( json => $attributes, status => 200 );
89 get '/dbic_merge_sorting_result_set' => sub {
90 my $c = shift;
91 my $attributes = { a => 'a', b => 'b' };
92 my $result_set = Koha::Cities->new;
93 $attributes = $c->dbic_merge_sorting(
95 attributes => $attributes,
96 params => { _match => 'exact', _order_by => [ 'name', '-postal_code', '+country', ' state' ] },
97 result_set => $result_set
100 $c->render( json => $attributes, status => 200 );
103 get '/dbic_merge_sorting_date' => sub {
104 my $c = shift;
105 my $attributes = { a => 'a', b => 'b' };
106 my $result_set = Koha::Holds->new;
107 $attributes = $c->dbic_merge_sorting(
109 attributes => $attributes,
110 params => { _match => 'exact', _order_by => [ '-hold_date' ] },
111 result_set => $result_set
114 $c->render( json => $attributes, status => 200 );
117 get '/dbic_merge_prefetch' => sub {
118 my $c = shift;
119 my $attributes = {};
120 my $result_set = Koha::Holds->new;
121 $c->stash('koha.embed', {
122 "item" => {},
123 "biblio" => {
124 children => {
125 "orders" => {}
130 $c->dbic_merge_prefetch({
131 attributes => $attributes,
132 result_set => $result_set
135 $c->render( json => $attributes, status => 200 );
138 get '/merge_q_params' => sub {
139 my $c = shift;
140 my $filtered_params = {'biblio_id' => 1};
141 my $result_set = Koha::Biblios->new;
142 $filtered_params = $c->merge_q_params($filtered_params, $c->req->json->{q}, $result_set);
144 $c->render( json => $filtered_params, status => 200 );
147 get '/build_query' => sub {
148 my $c = shift;
149 my ( $filtered_params, $reserved_params ) =
150 $c->extract_reserved_params( $c->req->params->to_hash );
151 my $query;
152 try {
153 $query = $c->build_query_params( $filtered_params, $reserved_params );
154 $c->render( json => { query => $query }, status => 200 );
156 catch {
157 $c->render(
158 json => { exception_msg => $_->message, exception_type => ref($_) },
159 status => 400
164 get '/stash_embed' => sub {
165 my $c = shift;
167 try {
168 $c->stash_embed(
170 spec => {
171 'x-koha-embed' => [
172 'checkouts',
173 'checkouts.item',
174 'library',
175 'holds+count'
181 $c->render(
182 status => 200,
183 json => $c->stash( 'koha.embed' )
186 catch {
187 $c->render(
188 status => 400,
189 json => { error => "$_" }
194 get '/stash_embed_no_spec' => sub {
195 my $c = shift;
197 try {
198 $c->stash_embed({ spec => {} });
200 $c->render(
201 status => 200,
202 json => $c->stash( 'koha.embed' )
205 catch {
206 $c->render(
207 status => 400,
208 json => { error => "$_" }
213 sub to_model {
214 my ($args) = @_;
215 $args->{three} = delete $args->{tres}
216 if exists $args->{tres};
217 return $args;
220 # The tests
222 use Test::More tests => 6;
223 use Test::Mojo;
225 subtest 'extract_reserved_params() tests' => sub {
227 plan tests => 9;
229 my $t = Test::Mojo->new;
231 $t->get_ok('/query?_page=2&_per_page=3&firstname=Manuel&surname=Cohen%20Arazi')->status_is(200)
232 ->json_is( '/filtered_params' =>
233 { firstname => 'Manuel', surname => 'Cohen Arazi' } )
234 ->json_is( '/reserved_params' => { _page => 2, _per_page => 3 } );
236 $t->get_ok('/query_full/with/path?_match=exact&_order_by=blah&_page=2&_per_page=3&firstname=Manuel&surname=Cohen%20Arazi')->status_is(200)
237 ->json_is(
238 '/filtered_params' => {
239 firstname => 'Manuel',
240 surname => 'Cohen Arazi'
242 ->json_is(
243 '/reserved_params' => {
244 _page => 2,
245 _per_page => 3,
246 _match => 'exact',
247 _order_by => 'blah'
249 ->json_is(
250 '/path_params' => {
251 id => 'with',
252 subid => 'path'
253 } );
257 subtest 'dbic_merge_sorting() tests' => sub {
259 plan tests => 20;
261 my $t = Test::Mojo->new;
263 $t->get_ok('/dbic_merge_sorting')->status_is(200)
264 ->json_is( '/a' => 'a', 'Existing values are kept (a)' )
265 ->json_is( '/b' => 'b', 'Existing values are kept (b)' )->json_is(
266 '/order_by' => [
267 'uno',
268 { -desc => 'dos' },
269 { -asc => 'tres' },
270 { -asc => 'cuatro' }
274 $t->get_ok('/dbic_merge_sorting_result_set')->status_is(200)
275 ->json_is( '/a' => 'a', 'Existing values are kept (a)' )
276 ->json_is( '/b' => 'b', 'Existing values are kept (b)' )->json_is(
277 '/order_by' => [
278 'city_name',
279 { -desc => 'city_zipcode' },
280 { -asc => 'city_country' },
281 { -asc => 'city_state' }
285 $t->get_ok('/dbic_merge_sorting_date')->status_is(200)
286 ->json_is( '/a' => 'a', 'Existing values are kept (a)' )
287 ->json_is( '/b' => 'b', 'Existing values are kept (b)' )->json_is(
288 '/order_by' => [
289 { -desc => 'reservedate' }
293 $t->get_ok('/dbic_merge_sorting_single')->status_is(200)
294 ->json_is( '/a' => 'a', 'Existing values are kept (a)' )
295 ->json_is( '/b' => 'b', 'Existing values are kept (b)' )->json_is(
296 '/order_by' => { '-desc' => 'uno' }
300 subtest '/dbic_merge_prefetch' => sub {
301 plan tests => 4;
303 my $t = Test::Mojo->new;
305 $t->get_ok('/dbic_merge_prefetch')->status_is(200)
306 ->json_like( '/prefetch/0' => qr/item|biblio/ )
307 ->json_like( '/prefetch/1' => qr/item|biblio/ );
310 subtest '/merge_q_params' => sub {
311 plan tests => 3;
312 my $t = Test::Mojo->new;
314 $t->get_ok('/merge_q_params' => json => {
315 q => {
316 "-not_bool" => "suggestions.suggester.patron_card_lost",
317 "-or" => [
319 "creation_date" => {
320 "!=" => ["fff", "zzz", "xxx"]
323 { "suggestions.suggester.housebound_profile.frequency" => "123" },
325 "suggestions.suggester.library_id" => {"like" => "%CPL%"}
329 })->status_is(200)
330 ->json_is( '/-and' => [
332 "-not_bool" => "suggester.lost",
333 "-or" => [
335 "datecreated" => {
336 "!=" => [
337 "fff",
338 "zzz",
339 "xxx"
344 "housebound_profile.frequency" => 123
347 "suggester.branchcode" => {
348 "like" => "\%CPL\%"
354 "biblio_id" => 1
359 subtest '_build_query_params_from_api' => sub {
361 plan tests => 16;
363 my $t = Test::Mojo->new;
365 # _match => contains
366 $t->get_ok('/build_query?_match=contains&title=Ender&author=Orson')
367 ->status_is(200)
368 ->json_is( '/query' =>
369 { author => { like => '%Orson%' }, title => { like => '%Ender%' } } );
371 # _match => starts_with
372 $t->get_ok('/build_query?_match=starts_with&title=Ender&author=Orson')
373 ->status_is(200)
374 ->json_is( '/query' =>
375 { author => { like => 'Orson%' }, title => { like => 'Ender%' } } );
377 # _match => ends_with
378 $t->get_ok('/build_query?_match=ends_with&title=Ender&author=Orson')
379 ->status_is(200)
380 ->json_is( '/query' =>
381 { author => { like => '%Orson' }, title => { like => '%Ender' } } );
383 # _match => exact
384 $t->get_ok('/build_query?_match=exact&title=Ender&author=Orson')
385 ->status_is(200)
386 ->json_is( '/query' => { author => 'Orson', title => 'Ender' } );
388 # _match => blah
389 $t->get_ok('/build_query?_match=blah&title=Ender&author=Orson')
390 ->status_is(400)
391 ->json_is( '/exception_msg' => 'Invalid value for _match param (blah)' )
392 ->json_is( '/exception_type' => 'Koha::Exceptions::WrongParameter' );
396 subtest 'stash_embed() tests' => sub {
398 plan tests => 15;
400 my $t = Test::Mojo->new;
402 $t->get_ok( '/stash_embed' => { 'x-koha-embed' => 'checkouts,checkouts.item' } )
403 ->status_is(200)
404 ->json_is( { checkouts => { children => { item => {} } } } );
406 $t->get_ok( '/stash_embed' => { 'x-koha-embed' => 'checkouts,checkouts.item,library' } )
407 ->status_is(200)
408 ->json_is( { checkouts => { children => { item => {} } }, library => {} } );
410 $t->get_ok( '/stash_embed' => { 'x-koha-embed' => 'holds+count' } )
411 ->status_is(200)
412 ->json_is( { holds_count => { is_count => 1 } } );
414 $t->get_ok( '/stash_embed' => { 'x-koha-embed' => 'checkouts,checkouts.item,patron' } )
415 ->status_is(400)
416 ->json_is(
418 error => 'Embeding patron is not authorised. Check your x-koha-embed headers or remove it.'
422 $t->get_ok( '/stash_embed_no_spec' => { 'x-koha-embed' => 'checkouts,checkouts.item,patron' } )
423 ->status_is(400)
424 ->json_is(
426 error => 'Embedding objects is not allowed on this endpoint.'