View | Details | Raw Unified | Return to bug 41950
Collapse All | Expand All

(-)a/t/Koha/REST/Plugin/Query.t (-3 / +164 lines)
Lines 24-29 use Try::Tiny; Link Here
24
use Koha::Cities;
24
use Koha::Cities;
25
use Koha::Holds;
25
use Koha::Holds;
26
use Koha::Biblios;
26
use Koha::Biblios;
27
use Koha::Patrons;
27
use Koha::Patron::Relationship;
28
use Koha::Patron::Relationship;
28
29
29
app->log->level('error');
30
app->log->level('error');
Lines 180-185 get '/dbic_merge_prefetch_count' => sub { Link Here
180
    $c->render( json => $attributes, status => 200 );
181
    $c->render( json => $attributes, status => 200 );
181
};
182
};
182
183
184
get '/dbic_merge_prefetch_count_sorted' => sub {
185
    my $c          = shift;
186
    my $attributes = { order_by => [ { '-desc' => 'me.guarantee_count' } ] };
187
    my $result_set = Koha::Patron::Relationship->new;
188
    $c->stash( 'koha.embed', { "guarantee_count" => { "is_count" => 1 } } );
189
190
    $c->dbic_merge_prefetch(
191
        {
192
            attributes => $attributes,
193
            result_set => $result_set
194
        }
195
    );
196
197
    # Serialize: scalar refs become the string they point to
198
    my $order_by = $attributes->{order_by};
199
    for my $atom (@$order_by) {
200
        if ( ref($atom) eq 'HASH' ) {
201
            for my $dir ( keys %$atom ) {
202
                $atom->{$dir} = ${ $atom->{$dir} } if ref( $atom->{$dir} ) eq 'SCALAR';
203
            }
204
        }
205
    }
206
207
    $c->render( json => $attributes, status => 200 );
208
};
209
210
get '/dbic_merge_prefetch_count_unsortable' => sub {
211
    my $c          = shift;
212
    my $attributes = { order_by => [ { '-desc' => 'me.checkouts_count' } ] };
213
    my $result_set = Koha::Patrons->new;
214
215
    # checkouts is a Koha-only method, not a DBIC relationship
216
    $c->stash( 'koha.embed', { "checkouts_count" => { "is_count" => 1 } } );
217
218
    try {
219
        $c->dbic_merge_prefetch(
220
            {
221
                attributes => $attributes,
222
                result_set => $result_set
223
            }
224
        );
225
        $c->render( json => { error => 'no exception thrown' }, status => 500 );
226
    } catch {
227
        if ( ref($_) eq 'Koha::Exceptions::BadParameter' ) {
228
            $c->render( json => { error => $_->message, error_code => 'bad_parameter' }, status => 400 );
229
        } else {
230
            $c->render( json => { error => "$_" }, status => 500 );
231
        }
232
    };
233
};
234
235
get '/dbic_merge_prefetch_count_unsortable_display' => sub {
236
    my $c          = shift;
237
    my $attributes = {};
238
    my $result_set = Koha::Patrons->new;
239
240
    # checkouts is a Koha-only method — no order_by, so no error
241
    $c->stash( 'koha.embed', { "checkouts_count" => { "is_count" => 1 } } );
242
243
    $c->dbic_merge_prefetch(
244
        {
245
            attributes => $attributes,
246
            result_set => $result_set
247
        }
248
    );
249
250
    $c->render( json => $attributes, status => 200 );
251
};
252
253
get '/dbic_merge_prefetch_nested_count' => sub {
254
    my $c          = shift;
255
    my $attributes = { order_by => [ { '-asc' => 'guarantee.article_requests_count' } ] };
256
    my $result_set = Koha::Patron::Relationship->new;
257
    $c->stash(
258
        'koha.embed',
259
        { "guarantee" => { "children" => { "article_requests_count" => { "is_count" => 1 } } } }
260
    );
261
262
    $c->dbic_merge_prefetch(
263
        {
264
            attributes => $attributes,
265
            result_set => $result_set
266
        }
267
    );
268
269
    # Serialize scalar refs
270
    my $order_by = $attributes->{order_by};
271
    for my $atom (@$order_by) {
272
        if ( ref($atom) eq 'HASH' ) {
273
            for my $dir ( keys %$atom ) {
274
                $atom->{$dir} = ${ $atom->{$dir} } if ref( $atom->{$dir} ) eq 'SCALAR';
275
            }
276
        }
277
    }
278
279
    $c->render( json => $attributes, status => 200 );
280
};
281
282
get '/dbic_merge_prefetch_nested_count_unsortable' => sub {
283
    my $c          = shift;
284
    my $attributes = { order_by => [ { '-desc' => 'guarantee.checkouts_count' } ] };
285
    my $result_set = Koha::Patron::Relationship->new;
286
287
    # checkouts is NOT in Patron's prefetch_whitelist
288
    $c->stash(
289
        'koha.embed',
290
        { "guarantee" => { "children" => { "checkouts_count" => { "is_count" => 1 } } } }
291
    );
292
293
    try {
294
        $c->dbic_merge_prefetch(
295
            {
296
                attributes => $attributes,
297
                result_set => $result_set
298
            }
299
        );
300
        $c->render( json => { error => 'no exception thrown' }, status => 500 );
301
    } catch {
302
        if ( ref($_) eq 'Koha::Exceptions::BadParameter' ) {
303
            $c->render( json => { error => $_->message, error_code => 'bad_parameter' }, status => 400 );
304
        } else {
305
            $c->render( json => { error => "$_" }, status => 500 );
306
        }
307
    };
308
};
309
183
get '/merge_q_params' => sub {
310
get '/merge_q_params' => sub {
184
    my $c               = shift;
311
    my $c               = shift;
185
    my $filtered_params = { 'biblio_id' => 1 };
312
    my $filtered_params = { 'biblio_id' => 1 };
Lines 466-472 subtest 'dbic_merge_sorting() tests' => sub { Link Here
466
};
593
};
467
594
468
subtest '/dbic_merge_prefetch' => sub {
595
subtest '/dbic_merge_prefetch' => sub {
469
    plan tests => 10;
596
    plan tests => 32;
470
597
471
    my $t = Test::Mojo->new;
598
    my $t = Test::Mojo->new;
472
599
Lines 485-491 subtest '/dbic_merge_prefetch' => sub { Link Here
485
        }
612
        }
486
    );
613
    );
487
614
488
    $t->get_ok('/dbic_merge_prefetch_count')->status_is(200)->json_is( '/prefetch/0' => 'guarantee' );
615
    # Top-level +count: produces +select/+as, no prefetch
616
    $t->get_ok('/dbic_merge_prefetch_count')
617
        ->status_is(200)
618
        ->json_is( '/+as/0' => 'guarantee_count' )
619
        ->json_hasnt('/prefetch');
620
621
    # Top-level +count sorted: order_by gets the subquery substituted
622
    $t->get_ok('/dbic_merge_prefetch_count_sorted')
623
        ->status_is(200)
624
        ->json_like( '/order_by/0/-desc' => qr/SELECT COUNT\(\*\) FROM borrowers/ )
625
        ->json_is( '/+as/0' => 'guarantee_count' );
626
627
    # Top-level unsortable +count with order_by: throws BadParameter (400)
628
    $t->get_ok('/dbic_merge_prefetch_count_unsortable')
629
        ->status_is(400)
630
        ->json_is( '/error_code' => 'bad_parameter' )
631
        ->json_like( '/error' => qr/Cannot sort on checkouts_count/ );
632
633
    # Top-level unsortable +count without order_by: no error (display-only fallback)
634
    $t->get_ok('/dbic_merge_prefetch_count_unsortable_display')
635
        ->status_is(200)
636
        ->json_hasnt('/prefetch')
637
        ->json_hasnt('/+select');
638
639
    # Nested +count sorted: subquery uses parent alias, dotted +as key
640
    $t->get_ok('/dbic_merge_prefetch_nested_count')
641
        ->status_is(200)
642
        ->json_like( '/order_by/0/-asc' => qr/SELECT COUNT\(\*\) FROM article_requests/ )
643
        ->json_like( '/order_by/0/-asc' => qr/guarantee\.borrowernumber/ )
644
        ->json_is( '/+as/0' => 'guarantee.article_requests_count' );
645
646
    # Nested unsortable +count with order_by: throws BadParameter (400)
647
    $t->get_ok('/dbic_merge_prefetch_nested_count_unsortable')
648
        ->status_is(400)
649
        ->json_is( '/error_code' => 'bad_parameter' )
650
        ->json_like( '/error' => qr/Cannot sort on guarantee\.checkouts_count/ );
489
};
651
};
490
652
491
subtest '/merge_q_params' => sub {
653
subtest '/merge_q_params' => sub {
492
- 

Return to bug 41950