Bug 25113: Refactor CirculationRules.t when testing scope combinations
[koha-equinox.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 => 2;
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 'Performance' => sub {
98         plan tests => 4;
99
100         my $worst_case = timethis(500,
101                     sub { Koha::CirculationRules->get_effective_rule({
102                             branchcode   => 'nonexistent',
103                             categorycode => 'nonexistent',
104                             itemtype     => 'nonexistent',
105                             rule_name    => 'nonexistent',
106                         });
107                     }
108                 );
109         my $mid_case = timethis(500,
110                     sub { Koha::CirculationRules->get_effective_rule({
111                             branchcode   => $branchcode,
112                             categorycode => 'nonexistent',
113                             itemtype     => 'nonexistent',
114                             rule_name    => 'nonexistent',
115                         });
116                     }
117                 );
118         my $sec_best_case = timethis(500,
119                     sub { Koha::CirculationRules->get_effective_rule({
120                             branchcode   => $branchcode,
121                             categorycode => $categorycode,
122                             itemtype     => 'nonexistent',
123                             rule_name    => 'nonexistent',
124                         });
125                     }
126                 );
127         my $best_case = timethis(500,
128                     sub { Koha::CirculationRules->get_effective_rule({
129                             branchcode   => $branchcode,
130                             categorycode => $categorycode,
131                             itemtype     => $itemtype,
132                             rule_name    => 'nonexistent',
133                         });
134                     }
135                 );
136         ok($worst_case, 'In worst case, get_effective_issuing_rule finds matching'
137            .' rule '.sprintf('%.2f', $worst_case->iters/$worst_case->cpu_a)
138            .' times per second.');
139         ok($mid_case, 'In mid case, get_effective_issuing_rule finds matching'
140            .' rule '.sprintf('%.2f', $mid_case->iters/$mid_case->cpu_a)
141            .' times per second.');
142         ok($sec_best_case, 'In second best case, get_effective_issuing_rule finds matching'
143            .' rule '.sprintf('%.2f', $sec_best_case->iters/$sec_best_case->cpu_a)
144            .' times per second.');
145         ok($best_case, 'In best case, get_effective_issuing_rule finds matching'
146            .' rule '.sprintf('%.2f', $best_case->iters/$best_case->cpu_a)
147            .' times per second.');
148     };
149 };
150
151 subtest 'set_rule' => sub {
152     plan tests => 3;
153
154     my $branchcode   = $builder->build({ source => 'Branch' })->{'branchcode'};
155     my $categorycode = $builder->build({ source => 'Category' })->{'categorycode'};
156     my $itemtype     = $builder->build({ source => 'Itemtype' })->{'itemtype'};
157
158     subtest 'Correct call' => sub {
159         plan tests => 4;
160
161         Koha::CirculationRules->delete;
162
163         lives_ok( sub {
164             Koha::CirculationRules->set_rule( {
165                 branchcode => $branchcode,
166                 rule_name => 'refund',
167                 rule_value => '',
168             } );
169         }, 'setting refund with branch' );
170
171         lives_ok( sub {
172             Koha::CirculationRules->set_rule( {
173                 branchcode => $branchcode,
174                 categorycode => $categorycode,
175                 rule_name => 'patron_maxissueqty',
176                 rule_value => '',
177             } );
178         }, 'setting patron_maxissueqty with branch/category succeeds' );
179
180         lives_ok( sub {
181             Koha::CirculationRules->set_rule( {
182                 branchcode => $branchcode,
183                 itemtype => $itemtype,
184                 rule_name => 'holdallowed',
185                 rule_value => '',
186             } );
187         }, 'setting holdallowed with branch/itemtype succeeds' );
188
189         lives_ok( sub {
190             Koha::CirculationRules->set_rule( {
191                 branchcode => $branchcode,
192                 categorycode => $categorycode,
193                 itemtype => $itemtype,
194                 rule_name => 'fine',
195                 rule_value => '',
196             } );
197         }, 'setting fine with branch/category/itemtype succeeds' );
198     };
199
200     subtest 'Call with missing params' => sub {
201         plan tests => 4;
202
203         Koha::CirculationRules->delete;
204
205         throws_ok( sub {
206             Koha::CirculationRules->set_rule( {
207                 rule_name => 'refund',
208                 rule_value => '',
209             } );
210         }, qr/branchcode/, 'setting refund without branch fails' );
211
212         throws_ok( sub {
213             Koha::CirculationRules->set_rule( {
214                 branchcode => $branchcode,
215                 rule_name => 'patron_maxissueqty',
216                 rule_value => '',
217             } );
218         }, qr/categorycode/, 'setting patron_maxissueqty without categorycode fails' );
219
220         throws_ok( sub {
221             Koha::CirculationRules->set_rule( {
222                 branchcode => $branchcode,
223                 rule_name => 'holdallowed',
224                 rule_value => '',
225             } );
226         }, qr/itemtype/, 'setting holdallowed without itemtype fails' );
227
228         throws_ok( sub {
229             Koha::CirculationRules->set_rule( {
230                 branchcode => $branchcode,
231                 categorycode => $categorycode,
232                 rule_name => 'fine',
233                 rule_value => '',
234             } );
235         }, qr/itemtype/, 'setting fine without itemtype fails' );
236     };
237
238     subtest 'Call with extra params' => sub {
239         plan tests => 3;
240
241         Koha::CirculationRules->delete;
242
243         throws_ok( sub {
244             Koha::CirculationRules->set_rule( {
245                 branchcode => $branchcode,
246                 categorycode => $categorycode,
247                 rule_name => 'refund',
248                 rule_value => '',
249             } );
250         }, qr/categorycode/, 'setting refund with categorycode fails' );
251
252         throws_ok( sub {
253             Koha::CirculationRules->set_rule( {
254                 branchcode => $branchcode,
255                 categorycode => $categorycode,
256                 itemtype => $itemtype,
257                 rule_name => 'patron_maxissueqty',
258                 rule_value => '',
259             } );
260         }, qr/itemtype/, 'setting patron_maxissueqty with itemtype fails' );
261
262         throws_ok( sub {
263             Koha::CirculationRules->set_rule( {
264                 branchcode => $branchcode,
265                 rule_name => 'holdallowed',
266                 categorycode => $categorycode,
267                 itemtype => $itemtype,
268                 rule_value => '',
269             } );
270         }, qr/categorycode/, 'setting holdallowed with categorycode fails' );
271     };
272 };
273
274 subtest 'clone' => sub {
275     plan tests => 2;
276
277     my $branchcode   = $builder->build({ source => 'Branch' })->{'branchcode'};
278     my $categorycode = $builder->build({ source => 'Category' })->{'categorycode'};
279     my $itemtype     = $builder->build({ source => 'Itemtype' })->{'itemtype'};
280
281     subtest 'Clone multiple rules' => sub {
282         plan tests => 4;
283
284         Koha::CirculationRules->delete;
285
286         Koha::CirculationRule->new({
287             branchcode   => undef,
288             categorycode => $categorycode,
289             itemtype     => $itemtype,
290             rule_name    => 'fine',
291             rule_value   => 5,
292         })->store;
293
294         Koha::CirculationRule->new({
295             branchcode   => undef,
296             categorycode => $categorycode,
297             itemtype     => $itemtype,
298             rule_name    => 'lengthunit',
299             rule_value   => 'days',
300         })->store;
301
302         Koha::CirculationRules->search({ branchcode => undef })->clone($branchcode);
303
304         my $rule_fine = Koha::CirculationRules->get_effective_rule({
305             branchcode   => $branchcode,
306             categorycode => $categorycode,
307             itemtype     => $itemtype,
308             rule_name    => 'fine',
309         });
310         my $rule_lengthunit = Koha::CirculationRules->get_effective_rule({
311             branchcode   => $branchcode,
312             categorycode => $categorycode,
313             itemtype     => $itemtype,
314             rule_name    => 'lengthunit',
315         });
316
317         _is_row_match(
318             $rule_fine,
319             {
320                 branchcode   => $branchcode,
321                 categorycode => $categorycode,
322                 itemtype     => $itemtype,
323                 rule_name    => 'fine',
324                 rule_value   => 5,
325             },
326             'When I attempt to get cloned fine rule,'
327            .' then the above one is returned.'
328         );
329         _is_row_match(
330             $rule_lengthunit,
331             {
332                 branchcode   => $branchcode,
333                 categorycode => $categorycode,
334                 itemtype     => $itemtype,
335                 rule_name    => 'lengthunit',
336                 rule_value   => 'days',
337             },
338             'When I attempt to get cloned lengthunit rule,'
339            .' then the above one is returned.'
340         );
341
342     };
343
344     subtest 'Clone one rule' => sub {
345         plan tests => 2;
346
347         Koha::CirculationRules->delete;
348
349         Koha::CirculationRule->new({
350             branchcode   => undef,
351             categorycode => $categorycode,
352             itemtype     => $itemtype,
353             rule_name    => 'fine',
354             rule_value   => 5,
355         })->store;
356
357         my $rule = Koha::CirculationRules->search({ branchcode => undef })->next;
358         $rule->clone($branchcode);
359
360         my $cloned_rule = Koha::CirculationRules->get_effective_rule({
361             branchcode   => $branchcode,
362             categorycode => $categorycode,
363             itemtype     => $itemtype,
364             rule_name    => 'fine',
365         });
366
367         _is_row_match(
368             $cloned_rule,
369             {
370                 branchcode   => $branchcode,
371                 categorycode => $categorycode,
372                 itemtype     => $itemtype,
373                 rule_name    => 'fine',
374                 rule_value   => '5',
375             },
376             'When I attempt to get cloned fine rule,'
377            .' then the above one is returned.'
378         );
379
380     };
381 };
382
383 sub _is_row_match {
384     my ( $rule, $expected, $message ) = @_;
385
386     ok( $rule, $message ) ?
387         cmp_methods( $rule, [ %$expected ], $message ) :
388         fail( $message );
389 }
390
391 $schema->storage->txn_rollback;
392