Bug 9209 - Mocked Koha::Calendar tests
[koha.git] / t / Calendar.t
1 #!/usr/bin/env perl
2
3 use strict;
4 use warnings;
5 use DateTime;
6 use DateTime::Duration;
7 use Test::More tests => 35;
8 use Test::MockModule;
9 use DBD::Mock;
10 use Koha::DateUtils;
11
12 BEGIN {
13     use_ok('Koha::Calendar');
14
15     # This was the only test C4 had
16     # Remove when no longer used
17     use_ok('C4::Calendar');
18 }
19
20 my $module_context = new Test::MockModule('C4::Context');
21 $module_context->mock(
22     '_new_dbh',
23     sub {
24         my $dbh = DBI->connect( 'DBI:Mock:', '', '' )
25           || die "Cannot create handle: $DBI::errstr\n";
26         return $dbh;
27     }
28 );
29
30 # We need to mock the C4::Context->preference method for
31 # simplicity and re-usability of the session definition. Any
32 # syspref fits for syspref-agnostic tests.
33 $module_context->mock(
34     'preference',
35     sub {
36         return 'Calendar';
37     }
38 );
39
40
41 my $holidays_session = DBD::Mock::Session->new('holidays_session' => (
42     { # weekly holidays
43         statement => "SELECT weekday FROM repeatable_holidays WHERE branchcode = ? AND weekday IS NOT NULL",
44         results   => [
45                         ['weekday'],
46                         [0],    # sundays
47                         [6]     # saturdays
48                      ]
49     },
50     { # day and month repeatable holidays
51         statement => "SELECT day, month FROM repeatable_holidays WHERE branchcode = ? AND weekday IS NULL",
52         results   => [
53                         [ 'month', 'day' ],
54                         [ 1, 1 ],   # new year's day
55                         [12,25]     # christmas
56                      ]
57     },
58     { # exception holidays
59         statement => "SELECT day, month, year FROM special_holidays WHERE branchcode = ? AND isexception = 1",
60         results   => [
61                         [ 'day', 'month', 'year' ],
62                         [ 11, 11, 2012 ] # sunday exception
63                      ]
64     },
65     { # single holidays
66         statement => "SELECT day, month, year FROM special_holidays WHERE branchcode = ? AND isexception = 0",
67         results   => [
68                         [ 'day', 'month', 'year' ],
69                         [ 1, 6, 2011 ],  # single holiday
70                         [ 4, 7, 2012 ]
71                      ]
72     }
73 ));
74
75 # Initialize the global $dbh variable
76 my $dbh = C4::Context->dbh();
77 # Apply the mock session
78 $dbh->{ mock_session } = $holidays_session;
79 # 'MPL' branch is arbitrary, is not used at all but is needed for initialization
80 my $cal = Koha::Calendar->new( branchcode => 'MPL' );
81
82 isa_ok( $cal, 'Koha::Calendar', 'Calendar class returned' );
83
84
85 my $saturday = DateTime->new(
86     year      => 2012,
87     month     => 11,
88     day       => 24,
89 );
90
91 my $sunday = DateTime->new(
92     year      => 2012,
93     month     => 11,
94     day       => 25,
95 );
96
97 my $monday = DateTime->new(
98     year      => 2012,
99     month     => 11,
100     day       => 26,
101 );
102
103 my $new_year = DateTime->new(
104     year        => 2013,
105     month       => 1,
106     day         => 1,
107 );
108
109 my $single_holiday = DateTime->new(
110     year      => 2011,
111     month     => 6,
112     day       => 1,
113 );    # should be a holiday
114
115 my $notspecial = DateTime->new(
116     year      => 2011,
117     month     => 6,
118     day       => 2
119 );    # should NOT be a holiday
120
121 my $sunday_exception = DateTime->new(
122     year      => 2012,
123     month     => 11,
124     day       => 11
125 );
126
127 my $day_after_christmas = DateTime->new(
128     year    => 2012,
129     month   => 12,
130     day     => 26
131 );  # for testing negative addDate
132
133
134 {   # Syspref-agnostic tests
135     is ( $saturday->day_of_week, 6, '\'$saturday\' is actually a saturday (6th day of week)');
136     is ( $sunday->day_of_week, 7, '\'$sunday\' is actually a sunday (7th day of week)');
137     is ( $monday->day_of_week, 1, '\'$monday\' is actually a monday (1st day of week)');
138     is ( $cal->is_holiday($saturday), 1, 'Saturday is a closed day' );
139     is ( $cal->is_holiday($sunday), 1, 'Sunday is a closed day' );
140     is ( $cal->is_holiday($monday), 0, 'Monday is not a closed day' );
141     is ( $cal->is_holiday($new_year), 1, 'Month/Day closed day test (New year\'s day)' );
142     is ( $cal->is_holiday($single_holiday), 1, 'Single holiday closed day test' );
143     is ( $cal->is_holiday($notspecial), 0, 'Fixed single date that is not a holiday test' );
144     is ( $cal->is_holiday($sunday_exception), 0, 'Exception holiday is not a closed day test' );
145 }
146
147
148 {   # Bugzilla #8966 - is_holiday truncates referenced date
149     my $later_dt = DateTime->new(    # Monday
150         year      => 2012,
151         month     => 9,
152         day       => 17,
153         hour      => 17,
154         minute    => 30,
155         time_zone => 'Europe/London',
156     );
157
158
159     is( $cal->is_holiday($later_dt), 0, 'bz-8966 (1/2) Apply is_holiday for the next test' );
160     cmp_ok( $later_dt, 'eq', '2012-09-17T17:30:00', 'bz-8966 (2/2) Date should be the same after is_holiday' );
161 }
162
163
164 {   # Bugzilla #8800 - is_holiday should use truncated date for 'contains' call
165     my $single_holiday_time = DateTime->new(
166         year  => 2011,
167         month => 6,
168         day   => 1,
169         hour  => 11,
170         minute  => 2
171     );
172
173     is( $cal->is_holiday($single_holiday_time),
174         $cal->is_holiday($single_holiday) ,
175         'bz-8800 is_holiday should truncate the date for holiday validation' );
176 }
177
178
179     my $one_day_dur = DateTime::Duration->new( days => 1 );
180     my $two_day_dur = DateTime::Duration->new( days => 2 );
181     my $seven_day_dur = DateTime::Duration->new( days => 7 );
182
183     my $dt = dt_from_string( '2012-07-03','iso' );
184     my $test_dt = DateTime->new(    # Monday
185         year      => 2012,
186         month     => 7,
187         day       => 23,
188         hour      => 11,
189         minute    => 53,
190     );
191
192     my $later_dt = DateTime->new(    # Monday
193         year      => 2012,
194         month     => 9,
195         day       => 17,
196         hour      => 17,
197         minute    => 30,
198         time_zone => 'Europe/London',
199     );
200
201
202 {    ## 'Datedue' tests
203
204     $module_context->unmock('preference');
205     $module_context->mock(
206         'preference',
207         sub {
208             return 'Datedue';
209         }
210     );
211     # rewind dbh session
212     $holidays_session->reset;
213
214
215     $cal = Koha::Calendar->new( branchcode => 'MPL' );
216
217     is($cal->addDate( $dt, $one_day_dur, 'days' ),
218         dt_from_string('2012-07-05','iso'),
219         'Single day add (Datedue, matches holiday, shift)' );
220
221     is($cal->addDate( $dt, $two_day_dur, 'days' ),
222         dt_from_string('2012-07-05','iso'),
223         'Two days add, skips holiday (Datedue)' );
224
225     cmp_ok($cal->addDate( $test_dt, $seven_day_dur, 'days' ), 'eq',
226         '2012-07-30T11:53:00',
227         'Add 7 days (Datedue)' );
228
229     is( $cal->addDate( $saturday, $one_day_dur, 'days' )->day_of_week, 1,
230         'addDate skips closed Sunday (Datedue)' );
231
232     is( $cal->addDate($day_after_christmas, -1, 'days')->ymd(), '2012-12-24',
233         'Negative call to addDate (Datedue)' );
234
235     ## Note that the days_between API says closed days are not considered.
236     ## This tests are here as an API test.
237     cmp_ok( $cal->days_between( $test_dt, $later_dt )->in_units('days'),
238                 '==', 40, 'days_between calculates correctly (Days)' );
239
240     cmp_ok( $cal->days_between( $later_dt, $test_dt )->in_units('days'),
241                 '==', 40, 'Test parameter order not relevant (Days)' );
242
243
244 }
245
246
247 {   ## 'Calendar' tests'
248
249     $module_context->unmock('preference');
250     $module_context->mock(
251         'preference',
252         sub {
253             return 'Calendar';
254         }
255     );
256     # rewind dbh session
257     $holidays_session->reset;
258
259     $cal = Koha::Calendar->new( branchcode => 'MPL' );
260
261     $dt = dt_from_string('2012-07-03','iso');
262
263     is($cal->addDate( $dt, $one_day_dur, 'days' ),
264         dt_from_string('2012-07-05','iso'),
265         'Single day add (Calendar)' );
266
267     cmp_ok($cal->addDate( $test_dt, $seven_day_dur, 'days' ), 'eq',
268        '2012-08-01T11:53:00',
269        'Add 7 days (Calendar)' );
270
271     is( $cal->addDate( $saturday, $one_day_dur, 'days' )->day_of_week, 1,
272             'addDate skips closed Sunday (Calendar)' );
273
274     is( $cal->addDate($day_after_christmas, -1, 'days')->ymd(), '2012-12-24',
275             'Negative call to addDate (Calendar)' );
276
277     cmp_ok( $cal->days_between( $test_dt, $later_dt )->in_units('days'),
278                 '==', 40, 'days_between calculates correctly (Calendar)' );
279
280     cmp_ok( $cal->days_between( $later_dt, $test_dt )->in_units('days'),
281                 '==', 40, 'Test parameter order not relevant (Calendar)' );
282 }
283
284
285 {   ## 'Days' tests
286     $module_context->unmock('preference');
287     $module_context->mock(
288         'preference',
289         sub {
290             return 'Days';
291         }
292     );
293     # rewind dbh session
294     $holidays_session->reset;
295
296     $cal = Koha::Calendar->new( branchcode => 'MPL' );
297
298     $dt = dt_from_string('2012-07-03','iso');
299
300     is($cal->addDate( $dt, $one_day_dur, 'days' ),
301         dt_from_string('2012-07-04','iso'),
302         'Single day add (Days)' );
303
304     cmp_ok($cal->addDate( $test_dt, $seven_day_dur, 'days' ),'eq',
305         '2012-07-30T11:53:00',
306         'Add 7 days (Days)' );
307
308     is( $cal->addDate( $saturday, $one_day_dur, 'days' )->day_of_week, 7,
309         'addDate doesn\'t skip closed Sunday (Days)' );
310
311     is( $cal->addDate($day_after_christmas, -1, 'days')->ymd(), '2012-12-25',
312         'Negative call to addDate (Days)' );
313
314     ## Note that the days_between API says closed days are not considered.
315     ## This tests are here as an API test.
316     cmp_ok( $cal->days_between( $test_dt, $later_dt )->in_units('days'),
317                 '==', 40, 'days_between calculates correctly (Days)' );
318
319     cmp_ok( $cal->days_between( $later_dt, $test_dt )->in_units('days'),
320                 '==', 40, 'Test parameter order not relevant (Days)' );
321
322 }