Bug 24757: Leap day failing tests - Fix the tests!
[koha.git] / t / db_dependent / Koha / IssuingRules.t
1 #!/usr/bin/perl
2
3 # Copyright 2016 Koha-Suomi Oy
4 #
5 # This file is part of Koha
6 #
7 # Koha is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
11 #
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20 use Modern::Perl;
21
22 use Test::More tests => 3;
23 use Test::Deep qw( cmp_methods );
24 use Test::Exception;
25
26 use Benchmark;
27
28 use Koha::CirculationRules;
29
30 use t::lib::TestBuilder;
31 use t::lib::Mocks;
32
33 my $schema = Koha::Database->new->schema;
34 $schema->storage->txn_begin;
35
36 my $builder      = t::lib::TestBuilder->new;
37
38 subtest 'get_effective_issuing_rule' => sub {
39     plan tests => 3;
40
41     my $categorycode = $builder->build({ source => 'Category' })->{'categorycode'};
42     my $itemtype     = $builder->build({ source => 'Itemtype' })->{'itemtype'};
43     my $branchcode   = $builder->build({ source => 'Branch' })->{'branchcode'};
44
45     subtest 'Call with undefined values' => sub {
46         plan tests => 5;
47
48         my $rule;
49         Koha::CirculationRules->delete;
50
51         is(Koha::CirculationRules->search->count, 0, 'There are no issuing rules.');
52         # undef, undef, undef => 1
53         $rule = Koha::CirculationRules->get_effective_rule({
54             branchcode   => undef,
55             categorycode => undef,
56             itemtype     => undef,
57             rule_name    => 'fine',
58             rule_value   => 1,
59         });
60         is($rule, undef, 'When I attempt to get effective issuing rule by'
61            .' providing undefined values, then undef is returned.');
62
63        # undef, undef, undef => 2
64         ok(
65             Koha::CirculationRule->new(
66                 {
67                     branchcode   => undef,
68                     categorycode => undef,
69                     itemtype     => undef,
70                     rule_name    => 'fine',
71                     rule_value   => 2,
72                 }
73               )->store,
74             'Given I added an issuing rule branchcode => undef,'
75            .' categorycode => undef, itemtype => undef,');
76         $rule = Koha::CirculationRules->get_effective_rule({
77             branchcode   => undef,
78             categorycode => undef,
79             itemtype     => undef,
80             rule_name    => 'fine',
81         });
82         _is_row_match(
83             $rule,
84             {
85                 branchcode   => undef,
86                 categorycode => undef,
87                 itemtype     => undef,
88                 rule_name    => 'fine',
89                 rule_value   => 2,
90             },
91             'When I attempt to get effective'
92            .' issuing rule by providing undefined values, then the above one is'
93            .' returned.'
94         );
95     };
96
97     subtest 'Get effective issuing rule in correct order' => sub {
98         plan tests => 26;
99
100         my $rule;
101         Koha::CirculationRules->delete;
102         is(Koha::CirculationRules->search->count, 0, 'There are no issuing rules.');
103         $rule = Koha::CirculationRules->get_effective_rule({
104             branchcode   => $branchcode,
105             categorycode => $categorycode,
106             itemtype     => $itemtype,
107             rule_name    => 'fine',
108         });
109         is($rule, undef, 'When I attempt to get effective issuing rule, then undef'
110                         .' is returned.');
111
112         # undef, undef, undef => 5
113         ok(Koha::CirculationRule->new({
114             branchcode => undef,
115             categorycode => undef,
116             itemtype => undef,
117             rule_name => 'fine',
118             rule_value   => 5,
119         })->store, 'Given I added an issuing rule branchcode => undef, categorycode => undef, itemtype => undef,');
120         $rule = Koha::CirculationRules->get_effective_rule({
121             branchcode   => $branchcode,
122             categorycode => $categorycode,
123             itemtype     => $itemtype,
124             rule_name    => 'fine',
125         });
126         _is_row_match(
127             $rule,
128             {
129                 branchcode   => undef,
130                 categorycode => undef,
131                 itemtype     => undef,
132                 rule_name    => 'fine',
133                 rule_value   => 5,
134             },
135             'When I attempt to get effective issuing rule,'
136            .' then the above one is returned.'
137         );
138
139         # undef, undef, undef     => 5
140         # undef, undef, $itemtype => 7
141         ok(
142             Koha::CirculationRule->new(
143                 {
144                     branchcode   => undef,
145                     categorycode => undef,
146                     itemtype     => $itemtype,
147                     rule_name    => 'fine',
148                     rule_value   => 7,
149                 }
150               )->store,
151             "Given I added an issuing rule branchcode => undef, categorycode => undef, itemtype => $itemtype,"
152         );
153         $rule = Koha::CirculationRules->get_effective_rule({
154             branchcode   => $branchcode,
155             categorycode => $categorycode,
156             itemtype     => $itemtype,
157             rule_name    => 'fine',
158         });
159         _is_row_match(
160             $rule,
161             {
162                 branchcode   => undef,
163                 categorycode => undef,
164                 itemtype     => $itemtype,
165                 rule_name    => 'fine',
166                 rule_value   => 7,
167             },
168             'When I attempt to get effective issuing rule,'
169            .' then the above one is returned.'
170         );
171
172         # undef, undef,         undef     => 5
173         # undef, undef,         $itemtype => 7
174         # undef, $categorycode, undef     => 9
175         ok(
176             Koha::CirculationRule->new(
177                 {
178                     branchcode   => undef,
179                     categorycode => $categorycode,
180                     itemtype     => undef,
181                     rule_name    => 'fine',
182                     rule_value   => 9,
183                 }
184               )->store,
185             "Given I added an issuing rule branchcode => undef, categorycode => $categorycode, itemtype => undef,"
186         );
187         $rule = Koha::CirculationRules->get_effective_rule({
188             branchcode   => $branchcode,
189             categorycode => $categorycode,
190             itemtype     => $itemtype,
191             rule_name    => 'fine',
192         });
193         _is_row_match(
194             $rule,
195             {
196                 branchcode   => undef,
197                 categorycode => $categorycode,
198                 itemtype     => undef,
199                 rule_name    => 'fine',
200                 rule_value   => 9,
201             },
202             'When I attempt to get effective issuing rule,'
203            .' then the above one is returned.'
204         );
205
206         # undef, undef,         undef     => 5
207         # undef, undef,         $itemtype => 7
208         # undef, $categorycode, undef     => 9
209         # undef, $categorycode, $itemtype => 11
210         ok(
211             Koha::CirculationRule->new(
212                 {
213                     branchcode   => undef,
214                     categorycode => $categorycode,
215                     itemtype     => $itemtype,
216                     rule_name    => 'fine',
217                     rule_value   => 11,
218                 }
219               )->store,
220             "Given I added an issuing rule branchcode => undef, categorycode => $categorycode, itemtype => $itemtype,"
221         );
222         $rule = Koha::CirculationRules->get_effective_rule({
223             branchcode   => $branchcode,
224             categorycode => $categorycode,
225             itemtype     => $itemtype,
226             rule_name    => 'fine',
227         });
228         _is_row_match(
229             $rule,
230             {
231                 branchcode   => undef,
232                 categorycode => $categorycode,
233                 itemtype     => $itemtype,
234                 rule_name    => 'fine',
235                 rule_value   => 11,
236             },
237             'When I attempt to get effective issuing rule,'
238            .' then the above one is returned.'
239         );
240
241         # undef,       undef,         undef     => 5
242         # undef,       undef,         $itemtype => 7
243         # undef,       $categorycode, undef     => 9
244         # undef,       $categorycode, $itemtype => 11
245         # $branchcode, undef,         undef     => 13
246         ok(
247             Koha::CirculationRule->new(
248                 {
249                     branchcode   => $branchcode,
250                     categorycode => undef,
251                     itemtype     => undef,
252                     rule_name    => 'fine',
253                     rule_value   => 13,
254                 }
255               )->store,
256             "Given I added an issuing rule branchcode => $branchcode, categorycode => undef, itemtype => undef,"
257         );
258         $rule = Koha::CirculationRules->get_effective_rule({
259             branchcode   => $branchcode,
260             categorycode => $categorycode,
261             itemtype     => $itemtype,
262             rule_name    => 'fine',
263         });
264         _is_row_match(
265             $rule,
266             {
267                 branchcode   => $branchcode,
268                 categorycode => undef,
269                 itemtype     => undef,
270                 rule_name    => 'fine',
271                 rule_value   => 13,
272             },
273             'When I attempt to get effective issuing rule,'
274            .' then the above one is returned.'
275         );
276
277         # undef,       undef,         undef     => 5
278         # undef,       undef,         $itemtype => 7
279         # undef,       $categorycode, undef     => 9
280         # undef,       $categorycode, $itemtype => 11
281         # $branchcode, undef,         undef     => 13
282         # $branchcode, undef,         $itemtype => 15
283         ok(
284             Koha::CirculationRule->new(
285                 {
286                     branchcode   => $branchcode,
287                     categorycode => undef,
288                     itemtype     => $itemtype,
289                     rule_name    => 'fine',
290                     rule_value   => 15,
291                 }
292               )->store,
293             "Given I added an issuing rule branchcode => $branchcode, categorycode => undef, itemtype => $itemtype,"
294         );
295         $rule = Koha::CirculationRules->get_effective_rule({
296             branchcode   => $branchcode,
297             categorycode => $categorycode,
298             itemtype     => $itemtype,
299             rule_name    => 'fine',
300         });
301         _is_row_match(
302             $rule,
303             {
304                 branchcode   => $branchcode,
305                 categorycode => undef,
306                 itemtype     => $itemtype,
307                 rule_name    => 'fine',
308                 rule_value   => 15,
309             },
310             'When I attempt to get effective issuing rule,'
311            .' then the above one is returned.'
312         );
313
314         # undef,       undef,         undef     => 5
315         # undef,       undef,         $itemtype => 7
316         # undef,       $categorycode, undef     => 9
317         # undef,       $categorycode, $itemtype => 11
318         # $branchcode, undef,         undef     => 13
319         # $branchcode, undef,         $itemtype => 15
320         # $branchcode, $categorycode, undef     => 17
321         ok(
322             Koha::CirculationRule->new(
323                 {
324                     branchcode   => $branchcode,
325                     categorycode => $categorycode,
326                     itemtype     => undef,
327                     rule_name    => 'fine',
328                     rule_value   => 17,
329                 }
330               )->store,
331             "Given I added an issuing rule branchcode => $branchcode, categorycode => $categorycode, itemtype => undef,"
332         );
333         $rule = Koha::CirculationRules->get_effective_rule({
334             branchcode   => $branchcode,
335             categorycode => $categorycode,
336             itemtype     => $itemtype,
337             rule_name    => 'fine',
338         });
339         _is_row_match(
340             $rule,
341             {
342                 branchcode   => $branchcode,
343                 categorycode => $categorycode,
344                 itemtype     => undef,
345                 rule_name    => 'fine',
346                 rule_value   => 17,
347             },
348             'When I attempt to get effective issuing rule,'
349            .' then the above one is returned.'
350         );
351
352         # undef,       undef,         undef     => 5
353         # undef,       undef,         $itemtype => 7
354         # undef,       $categorycode, undef     => 9
355         # undef,       $categorycode, $itemtype => 11
356         # $branchcode, undef,         undef     => 13
357         # $branchcode, undef,         $itemtype => 15
358         # $branchcode, $categorycode, undef     => 17
359         # $branchcode, $categorycode, $itemtype => 19
360         ok(
361             Koha::CirculationRule->new(
362                 {
363                     branchcode   => $branchcode,
364                     categorycode => $categorycode,
365                     itemtype     => $itemtype,
366                     rule_name    => 'fine',
367                     rule_value   => 19,
368                 }
369               )->store,
370             "Given I added an issuing rule branchcode => $branchcode, categorycode => $categorycode, itemtype => $itemtype,"
371         );
372         $rule = Koha::CirculationRules->get_effective_rule({
373             branchcode   => $branchcode,
374             categorycode => $categorycode,
375             itemtype     => $itemtype,
376             rule_name    => 'fine',
377         });
378         _is_row_match(
379             $rule,
380             {
381                 branchcode   => $branchcode,
382                 categorycode => $categorycode,
383                 itemtype     => $itemtype,
384                 rule_name    => 'fine',
385                 rule_value   => 19,
386             },
387             'When I attempt to get effective issuing rule,'
388            .' then the above one is returned.'
389         );
390     };
391
392     subtest 'Performance' => sub {
393         plan tests => 4;
394
395         my $worst_case = timethis(500,
396                     sub { Koha::CirculationRules->get_effective_rule({
397                             branchcode   => 'nonexistent',
398                             categorycode => 'nonexistent',
399                             itemtype     => 'nonexistent',
400                             rule_name    => 'nonexistent',
401                         });
402                     }
403                 );
404         my $mid_case = timethis(500,
405                     sub { Koha::CirculationRules->get_effective_rule({
406                             branchcode   => $branchcode,
407                             categorycode => 'nonexistent',
408                             itemtype     => 'nonexistent',
409                             rule_name    => 'nonexistent',
410                         });
411                     }
412                 );
413         my $sec_best_case = timethis(500,
414                     sub { Koha::CirculationRules->get_effective_rule({
415                             branchcode   => $branchcode,
416                             categorycode => $categorycode,
417                             itemtype     => 'nonexistent',
418                             rule_name    => 'nonexistent',
419                         });
420                     }
421                 );
422         my $best_case = timethis(500,
423                     sub { Koha::CirculationRules->get_effective_rule({
424                             branchcode   => $branchcode,
425                             categorycode => $categorycode,
426                             itemtype     => $itemtype,
427                             rule_name    => 'nonexistent',
428                         });
429                     }
430                 );
431         ok($worst_case, 'In worst case, get_effective_issuing_rule finds matching'
432            .' rule '.sprintf('%.2f', $worst_case->iters/$worst_case->cpu_a)
433            .' times per second.');
434         ok($mid_case, 'In mid case, get_effective_issuing_rule finds matching'
435            .' rule '.sprintf('%.2f', $mid_case->iters/$mid_case->cpu_a)
436            .' times per second.');
437         ok($sec_best_case, 'In second best case, get_effective_issuing_rule finds matching'
438            .' rule '.sprintf('%.2f', $sec_best_case->iters/$sec_best_case->cpu_a)
439            .' times per second.');
440         ok($best_case, 'In best case, get_effective_issuing_rule finds matching'
441            .' rule '.sprintf('%.2f', $best_case->iters/$best_case->cpu_a)
442            .' times per second.');
443     };
444 };
445
446 subtest 'set_rule' => sub {
447     plan tests => 3;
448
449     my $branchcode   = $builder->build({ source => 'Branch' })->{'branchcode'};
450     my $categorycode = $builder->build({ source => 'Category' })->{'categorycode'};
451     my $itemtype     = $builder->build({ source => 'Itemtype' })->{'itemtype'};
452
453     subtest 'Correct call' => sub {
454         plan tests => 4;
455
456         Koha::CirculationRules->delete;
457
458         lives_ok( sub {
459             Koha::CirculationRules->set_rule( {
460                 branchcode => $branchcode,
461                 rule_name => 'refund',
462                 rule_value => '',
463             } );
464         }, 'setting refund with branch' );
465
466         lives_ok( sub {
467             Koha::CirculationRules->set_rule( {
468                 branchcode => $branchcode,
469                 categorycode => $categorycode,
470                 rule_name => 'patron_maxissueqty',
471                 rule_value => '',
472             } );
473         }, 'setting patron_maxissueqty with branch/category succeeds' );
474
475         lives_ok( sub {
476             Koha::CirculationRules->set_rule( {
477                 branchcode => $branchcode,
478                 itemtype => $itemtype,
479                 rule_name => 'holdallowed',
480                 rule_value => '',
481             } );
482         }, 'setting holdallowed with branch/itemtype succeeds' );
483
484         lives_ok( sub {
485             Koha::CirculationRules->set_rule( {
486                 branchcode => $branchcode,
487                 categorycode => $categorycode,
488                 itemtype => $itemtype,
489                 rule_name => 'fine',
490                 rule_value => '',
491             } );
492         }, 'setting fine with branch/category/itemtype succeeds' );
493     };
494
495     subtest 'Call with missing params' => sub {
496         plan tests => 4;
497
498         Koha::CirculationRules->delete;
499
500         throws_ok( sub {
501             Koha::CirculationRules->set_rule( {
502                 rule_name => 'refund',
503                 rule_value => '',
504             } );
505         }, qr/branchcode/, 'setting refund without branch fails' );
506
507         throws_ok( sub {
508             Koha::CirculationRules->set_rule( {
509                 branchcode => $branchcode,
510                 rule_name => 'patron_maxissueqty',
511                 rule_value => '',
512             } );
513         }, qr/categorycode/, 'setting patron_maxissueqty without categorycode fails' );
514
515         throws_ok( sub {
516             Koha::CirculationRules->set_rule( {
517                 branchcode => $branchcode,
518                 rule_name => 'holdallowed',
519                 rule_value => '',
520             } );
521         }, qr/itemtype/, 'setting holdallowed without itemtype fails' );
522
523         throws_ok( sub {
524             Koha::CirculationRules->set_rule( {
525                 branchcode => $branchcode,
526                 categorycode => $categorycode,
527                 rule_name => 'fine',
528                 rule_value => '',
529             } );
530         }, qr/itemtype/, 'setting fine without itemtype fails' );
531     };
532
533     subtest 'Call with extra params' => sub {
534         plan tests => 3;
535
536         Koha::CirculationRules->delete;
537
538         throws_ok( sub {
539             Koha::CirculationRules->set_rule( {
540                 branchcode => $branchcode,
541                 categorycode => $categorycode,
542                 rule_name => 'refund',
543                 rule_value => '',
544             } );
545         }, qr/categorycode/, 'setting refund with categorycode fails' );
546
547         throws_ok( sub {
548             Koha::CirculationRules->set_rule( {
549                 branchcode => $branchcode,
550                 categorycode => $categorycode,
551                 itemtype => $itemtype,
552                 rule_name => 'patron_maxissueqty',
553                 rule_value => '',
554             } );
555         }, qr/itemtype/, 'setting patron_maxissueqty with itemtype fails' );
556
557         throws_ok( sub {
558             Koha::CirculationRules->set_rule( {
559                 branchcode => $branchcode,
560                 rule_name => 'holdallowed',
561                 categorycode => $categorycode,
562                 itemtype => $itemtype,
563                 rule_value => '',
564             } );
565         }, qr/categorycode/, 'setting holdallowed with categorycode fails' );
566     };
567 };
568
569 subtest 'clone' => sub {
570     plan tests => 2;
571
572     my $branchcode   = $builder->build({ source => 'Branch' })->{'branchcode'};
573     my $categorycode = $builder->build({ source => 'Category' })->{'categorycode'};
574     my $itemtype     = $builder->build({ source => 'Itemtype' })->{'itemtype'};
575
576     subtest 'Clone multiple rules' => sub {
577         plan tests => 4;
578
579         Koha::CirculationRules->delete;
580
581         Koha::CirculationRule->new({
582             branchcode   => undef,
583             categorycode => $categorycode,
584             itemtype     => $itemtype,
585             rule_name    => 'fine',
586             rule_value   => 5,
587         })->store;
588
589         Koha::CirculationRule->new({
590             branchcode   => undef,
591             categorycode => $categorycode,
592             itemtype     => $itemtype,
593             rule_name    => 'lengthunit',
594             rule_value   => 'days',
595         })->store;
596
597         Koha::CirculationRules->search({ branchcode => undef })->clone($branchcode);
598
599         my $rule_fine = Koha::CirculationRules->get_effective_rule({
600             branchcode   => $branchcode,
601             categorycode => $categorycode,
602             itemtype     => $itemtype,
603             rule_name    => 'fine',
604         });
605         my $rule_lengthunit = Koha::CirculationRules->get_effective_rule({
606             branchcode   => $branchcode,
607             categorycode => $categorycode,
608             itemtype     => $itemtype,
609             rule_name    => 'lengthunit',
610         });
611
612         _is_row_match(
613             $rule_fine,
614             {
615                 branchcode   => $branchcode,
616                 categorycode => $categorycode,
617                 itemtype     => $itemtype,
618                 rule_name    => 'fine',
619                 rule_value   => 5,
620             },
621             'When I attempt to get cloned fine rule,'
622            .' then the above one is returned.'
623         );
624         _is_row_match(
625             $rule_lengthunit,
626             {
627                 branchcode   => $branchcode,
628                 categorycode => $categorycode,
629                 itemtype     => $itemtype,
630                 rule_name    => 'lengthunit',
631                 rule_value   => 'days',
632             },
633             'When I attempt to get cloned lengthunit rule,'
634            .' then the above one is returned.'
635         );
636
637     };
638
639     subtest 'Clone one rule' => sub {
640         plan tests => 2;
641
642         Koha::CirculationRules->delete;
643
644         Koha::CirculationRule->new({
645             branchcode   => undef,
646             categorycode => $categorycode,
647             itemtype     => $itemtype,
648             rule_name    => 'fine',
649             rule_value   => 5,
650         })->store;
651
652         my $rule = Koha::CirculationRules->search({ branchcode => undef })->next;
653         $rule->clone($branchcode);
654
655         my $cloned_rule = Koha::CirculationRules->get_effective_rule({
656             branchcode   => $branchcode,
657             categorycode => $categorycode,
658             itemtype     => $itemtype,
659             rule_name    => 'fine',
660         });
661
662         _is_row_match(
663             $cloned_rule,
664             {
665                 branchcode   => $branchcode,
666                 categorycode => $categorycode,
667                 itemtype     => $itemtype,
668                 rule_name    => 'fine',
669                 rule_value   => '5',
670             },
671             'When I attempt to get cloned fine rule,'
672            .' then the above one is returned.'
673         );
674
675     };
676 };
677
678 sub _is_row_match {
679     my ( $rule, $expected, $message ) = @_;
680
681     ok( $rule, $message ) ?
682         cmp_methods( $rule, [ %$expected ], $message ) :
683         fail( $message );
684 }
685
686 $schema->storage->txn_rollback;
687