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