PeriodServiceTest   A
last analyzed

Complexity

Total Complexity 23

Size/Duplication

Total Lines 366
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 23
c 1
b 0
f 0
lcom 1
cbo 4
dl 0
loc 366
rs 10

22 Methods

Rating   Name   Duplication   Size   Complexity  
A setUp() 0 4 1
A getOptions() 0 8 1
A testHourDiffCalculatorThrowsExceptionWhenEndBeforeStart() 0 8 1
A testHourDiffCalculatorThrowsExceptionWhenEndSameAsStart() 0 8 1
A testHourDiffCalculator() 0 5 1
A hourDiffProvider() 0 20 1
A testRemainingHoursInMonth() 0 5 1
A remainingHoursProvider() 0 11 1
A testGetTotalHoursInMonth() 0 5 1
A monthProvider() 0 13 1
A testGetFirstAndLastDayOfWeek() 0 5 1
B firstAndLastDayOfWeekProvider() 0 41 1
A testGetWeeksInMonth() 0 5 1
B getWeeksInMonthProvider() 0 33 1
A createPeriod() 0 16 1
A testRemoveNonWorkingDays() 0 9 2
A testGetDaysInWeek() 0 5 1
A daysInWeekProvider() 0 7 1
A testGetNumWorkingDaysInWeek() 0 5 1
A testGetDaysInWeekThrowsExceptionIfDateNotInAnyWeek() 0 19 1
A testIsDateAfterDay() 0 5 1
A isDateAfterDayProvider() 0 10 1
1
<?php
2
3
namespace JhFlexiTimeTest\Service;
4
5
use JhFlexiTime\Service\PeriodService;
6
use JhFlexiTime\Options\ModuleOptions;
7
use JhFlexiTime\DateTime\DateTime;
8
9
/**
10
 * Class PeriodServiceTest
11
 * @package JhFlexiTimeTest\Service
12
 * @author Aydin Hassan <[email protected]>
13
 */
14
class PeriodServiceTest extends \PHPUnit_Framework_TestCase
15
{
16
    /**
17
     * @var \JhFlexiTime\Service\PeriodService
18
     */
19
    protected $periodService;
20
21
    /**
22
     * @var float
23
     */
24
    protected $timeInDay = 7.5;
25
26
    /**
27
     * @var int
28
     */
29
    protected $lunchDuration = 1;
30
31
    /**
32
     * @var array
33
     */
34
    protected $config = [];
35
36
    /**
37
     * Create Service
38
     */
39
    public function setUp()
40
    {
41
        $this->periodService = new PeriodService($this->getOptions());
42
    }
43
44
    /**
45
     * @return ModuleOptions
46
     */
47
    public function getOptions()
48
    {
49
        $options = new ModuleOptions();
50
        $options->setHoursInDay($this->timeInDay)
51
            ->setLunchDuration($this->lunchDuration);
52
53
        return $options;
54
    }
55
56
    /**
57
     * Function should throw exception when end date is less than start date
58
     */
59
    public function testHourDiffCalculatorThrowsExceptionWhenEndBeforeStart()
60
    {
61
        $start  = new DateTime("10:00");
62
        $end    = new DateTime("09:00");
63
64
        $this->setExpectedException('InvalidArgumentException', 'End time should be after start time');
65
        $this->periodService->calculateHourDiff($start, $end);
66
    }
67
68
    /**
69
     * Function should throw exception when end date is same as start date
70
     */
71
    public function testHourDiffCalculatorThrowsExceptionWhenEndSameAsStart()
72
    {
73
        $start  = new DateTime("10:00");
74
        $end    = new DateTime("10:00");
75
76
        $this->setExpectedException('InvalidArgumentException', 'End time should be after start time');
77
        $this->periodService->calculateHourDiff($start, $end);
78
    }
79
80
    /**
81
     * Test that when a new total is set, the getRunningTotal function
82
     * returns the difference between the new balance and the old balance,
83
     * minus the lunch duration
84
     *
85
     * @param DateTime $start
86
     * @param DateTime $end
87
     * @param int $expected
88
     *
89
     * @dataProvider hourDiffProvider
90
     */
91
    public function testHourDiffCalculator($start, $end, $expected)
92
    {
93
        $totalHours = $this->periodService->calculateHourDiff($start, $end);
94
        $this->assertEquals($expected, $totalHours);
95
    }
96
97
    /**
98
     * Provider for Start & End Times - incl expected hour diff
99
     *
100
     * TODO: test with different lunch durations
101
     * @return array
102
     */
103
    public function hourDiffProvider()
104
    {
105
        /**
106
         *  Start Time | End Time | Expected Hour Diff
107
         */
108
        return [
109
            [new DateTime("09:00"),   new DateTime("10:00"), 0],
110
            [new DateTime("09:00"),   new DateTime("9:30"), -0.5],
111
            [new DateTime("09:00"),   new DateTime("17:30"), 7.5],
112
            [new DateTime("07:00"),   new DateTime("17:30"), 9.5],
113
            //only calculates hours not days
114
            [new DateTime("yesterday 09:00"),   new DateTime("17:30"), 7.5],
115
            [new DateTime("yesterday 09:00"),   new DateTime("tomorrow 17:30"), 7.5],
116
117
            [new DateTime("09:15"),   new DateTime("17:30"), 7.25],
118
            [new DateTime("09:00"),   new DateTime("17:45"), 7.75],
119
            [new DateTime("09:20"),   new DateTime("17:00"), 6.67],
120
            [new DateTime("09:25"),   new DateTime("17:00"), 6.58],
121
        ];
122
    }
123
124
    /**
125
     * @param DateTime $date
126
     * @param int $expectedTotal
127
     *
128
     * @dataProvider remainingHoursProvider
129
     */
130
    public function testRemainingHoursInMonth(DateTime $date, $expectedTotal)
131
    {
132
        $remainingHours = $this->periodService->getRemainingHoursInMonth($date);
133
        $this->assertEquals($expectedTotal, $remainingHours);
134
    }
135
136
    /**
137
     * @return array
138
     */
139
    public function remainingHoursProvider()
140
    {
141
        /**
142
         *  Date | Expected Remaining Hours
143
         */
144
        return [
145
            [new DateTime("10 March 2014"),   112.5],
146
            [new DateTime("01 January 2014"), 165.00],
147
            [new DateTime("27 April 2014"),   22.5],
148
        ];
149
    }
150
151
    /**
152
     * @param DateTime $month
153
     * @param $expectedTotal
154
     *
155
     * @dataProvider monthProvider
156
     */
157
    public function testGetTotalHoursInMonth(DateTime $month, $expectedTotal)
158
    {
159
        $hours = $this->periodService->getTotalHoursInMonth($month);
160
        $this->assertEquals($expectedTotal, $hours);
161
    }
162
163
    /**
164
     * @return array
165
     */
166
    public function monthProvider()
167
    {
168
        /**
169
         *  Date | Expected Total Month Hours
170
         */
171
        return [
172
            [new DateTime("10 March 2014"), 157.5],
173
            [new DateTime("01 March 2014 00:00"), 157.5],
174
            [new DateTime("31 March 2014 23:59:59"), 157.5],
175
            [new DateTime("01 April 1988"), 157.5],
176
            [new DateTime("08 February 2011"), 150],
177
        ];
178
    }
179
180
    /**
181
     * @param DateTime $date
182
     * @param array $expected
183
     * @dataProvider firstAndLastDayOfWeekProvider
184
     */
185
    public function testGetFirstAndLastDayOfWeek(DateTime $date, array $expected)
186
    {
187
        $result = $this->periodService->getFirstAndLastDayOfWeek($date);
188
        $this->assertEquals($expected, $result);
189
    }
190
191
    public function firstAndLastDayOfWeekProvider()
192
    {
193
        return [
194
            [
195
                new DateTime("28 April 2014"),
196
                [
197
                    'firstDay' => new DateTime("28th April 2014"),
198
                    'lastDay' => new DateTime("30th April 2014"),
199
                ]
200
            ],
201
            [
202
                new DateTime("1 May 2014"),
203
                [
204
                    'firstDay' => new DateTime("1 May 2014"),
205
                    'lastDay' => new DateTime("4 May 2014"),
206
                ]
207
            ],
208
            [
209
                new DateTime("29 February 2012"),
210
                [
211
                    'firstDay' => new DateTime("27 February 2012"),
212
                    'lastDay' => new DateTime("29 February 2012"),
213
                ]
214
            ],
215
            [
216
                new DateTime("12 November 2014"),
217
                [
218
                    'firstDay' => new DateTime("10 November 2014"),
219
                    'lastDay' => new DateTime("16 November 2014"),
220
                ]
221
            ],
222
            [
223
                new DateTime("10 December 2014"),
224
                [
225
                    'firstDay' => new DateTime("8 December 2014"),
226
                    'lastDay' => new DateTime("14 December 2014"),
227
                ]
228
            ],
229
        ];
230
231
    }
232
233
    /**
234
     * @param DateTime $date
235
     * @param $expected
236
     * @dataProvider getWeeksInMonthProvider
237
     */
238
    public function testGetWeeksInMonth(DateTime $date, $expected)
239
    {
240
        $weeks = $this->periodService->getWeeksInMonth($date);
241
        $this->assertEquals($expected, $weeks);
242
    }
243
244
    public function getWeeksInMonthProvider()
245
    {
246
247
        $April2014periods = [
248
            $this->createPeriod("1 April 2014", "6 April 2014"),
249
            $this->createPeriod("7 April 2014", "13 April 2014"),
250
            $this->createPeriod("14 April 2014", "20 April 2014"),
251
            $this->createPeriod("21 April 2014", "27 April 2014"),
252
            $this->createPeriod("28 April 2014", "30 April 2014"),
253
        ];
254
255
        $march2011Periods = [
256
            $this->createPeriod("1 March 2011", "6 March 2011"),
257
            $this->createPeriod("7 March 2011", "13 March 2011"),
258
            $this->createPeriod("14 March 2011", "20 March 2011"),
259
            $this->createPeriod("21 March 2011", "27 March 2011"),
260
            $this->createPeriod("28 March 2011", "31 March 2011"),
261
        ];
262
263
        $february2011Periods = [
264
            $this->createPeriod("1 February 2011", "6 February 2011"),
265
            $this->createPeriod("7 February 2011", "13 February 2011"),
266
            $this->createPeriod("14 February 2011", "20 February 2011"),
267
            $this->createPeriod("21 February 2011", "27 February 2011"),
268
            $this->createPeriod("28 February 2011", "28 February 2011"),
269
        ];
270
271
        return [
272
            [new DateTime("April 28 2014"), $April2014periods],
273
            [new DateTime("March 28 2011"), $march2011Periods],
274
            [new DateTime("February 1 2011"), $february2011Periods],
275
        ];
276
    }
277
278
    /**
279
     * Helper function to generate a \DatePeriod object
280
     *
281
     * @param string $start
282
     * @param string $end
283
     * @return array
284
     */
285
    public function createPeriod($start, $end)
286
    {
287
        //hack to include last day in DatePeriod
288
        $end = new DateTime($end);
289
        $end->modify('+1 day');
290
        $period = new \DatePeriod(new DateTime($start), new \DateInterval('P1D'), $end);
291
292
        return array_map(
293
            function (\DateTime $date) {
294
                $jhDate = new DateTime();
295
                $jhDate->setTimestamp($date->getTimestamp());
296
                return $jhDate;
297
            },
298
            iterator_to_array($period)
299
        );
300
    }
301
302
    public function testRemoveNonWorkingDays()
303
    {
304
        $period = $this->createPeriod("1 April 2014", "30 April 2014");
305
        $dates = $this->periodService->removeNonWorkingDays($period);
306
307
        foreach ($dates as $day) {
308
            $this->assertLessThan(6, $day->format('N'));
309
        }
310
    }
311
312
    /**
313
     * @param DateTime $date
314
     * @param $expected
315
     * @dataProvider daysInWeekProvider
316
     */
317
    public function testGetDaysInWeek($date, $expected)
318
    {
319
        $result = $this->periodService->getDaysInWeek($date);
320
        $this->assertEquals($expected, $result);
321
    }
322
323
    public function daysInWeekProvider()
324
    {
325
        return [
326
            [new DateTime("6 April 2014"), $this->createPeriod("1 April 2014", "6 April 2014")],
327
            [new DateTime("12 June 2014"), $this->createPeriod("9 June 2014", "15 June 2014")],
328
        ];
329
    }
330
331
    public function testGetNumWorkingDaysInWeek()
332
    {
333
        $date = new DateTime("6 April 2014");
334
        $this->assertSame(4, $this->periodService->getNumWorkingDaysInWeek($date));
335
    }
336
337
    public function testGetDaysInWeekThrowsExceptionIfDateNotInAnyWeek()
338
    {
339
        $date = new DateTime("6 April 2014");
340
341
        $this->periodService = $this->getMock(
342
            'JhFlexiTime\Service\PeriodService',
343
            ['getWeeksInMonth'],
344
            [$this->getOptions()]
345
        );
346
347
        $this->periodService
348
            ->expects($this->once())
349
            ->method('getWeeksInMonth')
350
            ->with($date)
351
            ->will($this->returnValue([[new DateTime("1 January 2014")]]));
352
353
        $this->setExpectedException("Exception", "Day is not present in returned month");
354
        $this->periodService->getDaysInWeek($date);
355
    }
356
357
    /**
358
     * @param DateTime $a
359
     * @param DateTime $b
360
     * @param bool $expected
361
     * @dataProvider isDateAfterDayProvider
362
     */
363
    public function testIsDateAfterDay(DateTime $a, DateTime $b, $expected)
364
    {
365
        $result = $this->periodService->isDateAfterDay($a, $b);
366
        $this->assertEquals($result, $expected);
367
    }
368
369
    public function isDateAfterDayProvider()
370
    {
371
        return [
372
            [new DateTime("12 April 2014"),            new DateTime("12 April 2014 23:59:59"),    false],
373
            [new DateTime("13 April 2014 00:00:00"),   new DateTime("12 April 2014 23:59:59"),    true],
374
            [new DateTime("13 April 2014"),            new DateTime("12 April 2014 23:59:59"),    true],
375
            [new DateTime("14 April 2014"),            new DateTime("12 April 2014"),             true],
376
            [new DateTime("13 April 2014 00:00"),      new DateTime("12 April 2014"),             true],
377
        ];
378
    }
379
}
380