Passed
Pull Request — master (#7)
by Alex
12:47
created

DateFactoryTest::testDiffWillReturnDateInterval()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 17
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 10
c 1
b 0
f 0
dl 0
loc 17
rs 9.9332
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ArpTest\DateTime;
6
7
use Arp\DateTime\DateFactory;
8
use Arp\DateTime\DateFactoryInterface;
9
use Arp\DateTime\DateIntervalFactoryInterface;
10
use Arp\DateTime\DateTimeFactoryInterface;
11
use Arp\DateTime\Exception\DateFactoryException;
12
use Arp\DateTime\Exception\DateIntervalFactoryException;
13
use Arp\DateTime\Exception\DateTimeFactoryException;
14
use PHPUnit\Framework\MockObject\MockObject;
15
use PHPUnit\Framework\TestCase;
16
17
/**
18
 * @author  Alex Patterson <[email protected]>
19
 * @package ArpTest\DateTime
20
 */
21
final class DateFactoryTest extends TestCase
22
{
23
    /**
24
     * @var DateTimeFactoryInterface|MockObject
25
     */
26
    private $dateTimeFactory;
27
28
    /**
29
     * @var DateIntervalFactoryInterface|MockObject
30
     */
31
    private $dateIntervalFactory;
32
33
    /**
34
     * Set up the test case dependencies
35
     */
36
    public function setUp(): void
37
    {
38
        $this->dateTimeFactory = $this->createMock(DateTimeFactoryInterface::class);
39
40
        $this->dateIntervalFactory = $this->createMock(DateIntervalFactoryInterface::class);
41
    }
42
43
    /**
44
     * Ensure that the factory implements DateFactoryInterface.
45
     *
46
     * @covers \Arp\DateTime\DateFactory
47
     */
48
    public function testImplementsDateFactoryInterface(): void
49
    {
50
        $factory = new DateFactory($this->dateTimeFactory, $this->dateIntervalFactory);
51
52
        $this->assertInstanceOf(DateFactoryInterface::class, $factory);
53
    }
54
55
    /**
56
     * Assert that calls to creatDateInterval() will return the expected DateInterval instance.
57
     *
58
     * @param string $spec
59
     *
60
     * @covers       \Arp\DateTime\DateFactory::createDateInterval
61
     * @dataProvider getCreateDateIntervalWillReturnANewDateIntervalToSpecData
62
     *
63
     * @throws DateFactoryException
64
     */
65
    public function testCreateDateIntervalWillReturnANewDateIntervalToSpec(string $spec): void
66
    {
67
        $factory = new DateFactory($this->dateTimeFactory, $this->dateIntervalFactory);
68
69
        /** @var \DateInterval|MockObject $dateInterval */
70
        $dateInterval = $this->createMock(\DateInterval::class);
71
72
        $this->dateIntervalFactory->expects($this->once())
73
            ->method('createDateInterval')
74
            ->willReturn($dateInterval);
75
76
        $this->assertSame($dateInterval, $factory->createDateInterval($spec));
77
    }
78
79
    /**
80
     * @return array
81
     */
82
    public function getCreateDateIntervalWillReturnANewDateIntervalToSpecData(): array
83
    {
84
        return [
85
            ['P100D'],
86
            ['P4Y1DT9H11M3S'],
87
            ['P2Y4DT6H8M'],
88
            ['P7Y8M'],
89
        ];
90
    }
91
92
93
    /**
94
     * Assert that an invalid $spec passed to createDateInterval() will raise a DateTimeFactoryException.
95
     *
96
     * @covers \Arp\DateTime\DateFactory::createDateInterval
97
     *
98
     * @throws DateFactoryException
99
     */
100
    public function testDateIntervalWillThrowDateTimeFactoryExceptionIfUnableToCreateADateInterval(): void
101
    {
102
        $spec = 'Hello';
103
104
        $factory = new DateFactory($this->dateTimeFactory, $this->dateIntervalFactory);
105
106
        $exceptionCode = 123;
107
        $exceptionMessage = 'This is a test exception message';
108
        $exception = new DateIntervalFactoryException($exceptionMessage, $exceptionCode);
109
110
        $this->dateIntervalFactory->expects($this->once())
111
            ->method('createDateInterval')
112
            ->willThrowException($exception);
113
114
        $errorMessage = sprintf(
115
            'Failed to create date interval \'%s\': %s',
116
            $spec,
117
            $exceptionMessage
118
        );
119
120
        $this->expectDeprecationMessage(DateTimeFactoryException::class);
121
        $this->expectExceptionMessage($errorMessage);
122
        $this->expectExceptionCode($exceptionCode);
123
124
        $factory->createDateInterval($spec);
125
    }
126
127
    /**
128
     * Assert that the calls to diff will return a valid DateInterval.
129
     *
130
     * @covers \Arp\DateTime\DateFactory::diff
131
     *
132
     * @throws DateFactoryException
133
     */
134
    public function testDiffWillReturnDateInterval(): void
135
    {
136
        // @todo Data provider
137
        $origin = new \DateTime();
138
        $target = new \DateTime();
139
        $absolute = false;
140
141
        $dateInterval = $origin->diff($target);
142
143
        $factory = new DateFactory($this->dateTimeFactory, $this->dateIntervalFactory);
144
145
        $this->dateIntervalFactory->expects($this->once())
146
            ->method('diff')
147
            ->with($origin, $target, $absolute)
148
            ->willReturn($dateInterval);
149
150
        $this->assertSame($dateInterval, $factory->diff($origin, $target, $absolute));
151
    }
152
153
    /**
154
     * Assert that a DateTimeFactoryException is thrown when unable to diff the provided dates.
155
     *
156
     * @covers \Arp\DateTime\DateFactory::diff
157
     *
158
     * @throws DateFactoryException
159
     */
160
    public function testDateTimeFactoryExceptionWillBeThrownIfDiffFails(): void
161
    {
162
        $factory = new DateFactory($this->dateTimeFactory, $this->dateIntervalFactory);
163
164
        $origin = new \DateTime();
165
        $target = new \DateTime();
166
167
        $exceptionCode = 123;
168
        $exceptionMessage = 'This is a test exception message';
169
        $exception = new DateIntervalFactoryException($exceptionMessage, $exceptionCode);
170
171
        $this->dateIntervalFactory->expects($this->once())
172
            ->method('diff')
173
            ->with($origin, $target, false)
174
            ->willThrowException($exception);
175
176
        $this->expectException(DateFactoryException::class);
177
        $this->expectExceptionMessage(sprintf('Failed to perform date diff: %s', $exceptionMessage));
178
        $this->expectExceptionCode($exceptionCode);
179
180
        $factory->diff($origin, $target);
181
    }
182
183
}
184