Passed
Pull Request — master (#5)
by Alex
13:12
created

testCreateFromFormatWillThrowDateTimeFactoryException()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 17
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
eloc 8
c 1
b 1
f 0
dl 0
loc 17
rs 10
cc 1
nc 1
nop 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ArpTest\DateTime;
6
7
use Arp\DateTime\DateTimeFactory;
8
use Arp\DateTime\DateTimeFactoryInterface;
9
use Arp\DateTime\Exception\DateTimeFactoryException;
10
use PHPUnit\Framework\MockObject\MockObject;
11
use PHPUnit\Framework\TestCase;
12
13
/**
14
 * @author  Alex Patterson <[email protected]>
15
 * @package ArpTest\DateTime
16
 */
17
class DateTimeFactoryTest extends TestCase
18
{
19
    /**
20
     * Ensure that the factory implements DateTimeFactoryInterface.
21
     *
22
     * @covers \Arp\DateTime\DateTimeFactory
23
     */
24
    public function testImplementsDateTimeTimeFactoryInterface(): void
25
    {
26
        $factory = new DateTimeFactory();
27
28
        $this->assertInstanceOf(DateTimeFactoryInterface::class, $factory);
29
    }
30
31
    /**
32
     * Ensure that calls to createDateTime() will return the valid configured \DateTime instance.
33
     *
34
     * @param string $spec    The date and time specification.
35
     * @param array  $options Optional date time creation options.
36
     *
37
     * @dataProvider getCreateDateTimeData
38
     *
39
     * @covers \Arp\DateTime\DateTimeFactory::createDateTime
40
     * @covers \Arp\DateTime\DateTimeFactory::resolveDateTimeZone
41
     */
42
    public function testCreateDateTime(string $spec, array $options = []): void
43
    {
44
        $factory = new DateTimeFactory();
45
46
        $dateTime = $factory->createDateTime($spec, $options);
47
48
        $this->assertSame($spec, $dateTime->format('Y-m-d H:i:s'));
49
    }
50
51
    /**
52
     * @return array
53
     */
54
    public function getCreateDateTimeData(): array
55
    {
56
        return [
57
            [
58
                '2019-05-14 12:33:00',
59
            ],
60
61
            [
62
                '2019-08-14 17:34:55',
63
                [
64
                    'time_zone' => 'UTC',
65
                ],
66
            ],
67
        ];
68
    }
69
70
    /**
71
     * Ensure that if the DateTime cannot be create a new DateTimeFactoryException will be thrown.
72
     *
73
     * @covers \Arp\DateTime\DateTimeFactory::createDateTime
74
     */
75
    public function testCreateDateTimeWillThrowDateTimeFactoryException(): void
76
    {
77
        $factory = new DateTimeFactory();
78
79
        $spec = 'foo'; // invalid argument
80
        $options = [];
81
82
        $this->expectException(DateTimeFactoryException::class);
83
        $this->expectExceptionMessage(
84
            sprintf(
85
                'Failed to create a valid \DateTime instance using specification \'%s\' in \'%s\'.',
86
                $spec,
87
                DateTimeFactory::class
88
            )
89
        );
90
91
        $factory->createDateTime($spec, $options);
92
    }
93
94
    /**
95
     * Ensure that a createFromFormat() will throw a DateTimeFactoryException if a \DateTime instance cannot be created.
96
     *
97
     * @param string $spec
98
     * @param string $format
99
     * @param array  $options
100
     *
101
     * @dataProvider getCreateFromFormatWillThrowDateTimeFactoryExceptionData
102
     *
103
     * @covers \Arp\DateTime\DateTimeFactory::createFromFormat
104
     */
105
    public function testCreateFromFormatWillThrowDateTimeFactoryException(
106
        string $spec,
107
        string $format,
108
        array $options = []
109
    ): void {
110
        $factory = new DateTimeFactory();
111
112
        $this->expectException(DateTimeFactoryException::class);
113
        $this->expectExceptionMessage(
114
            sprintf(
115
                'Failed to create a valid \DateTime instance using specification \'%s\' in \'%s\'.',
116
                $spec,
117
                DateTimeFactory::class
118
            )
119
        );
120
121
        $factory->createFromFormat($spec, $format, $options);
122
    }
123
124
    /**
125
     * @return array
126
     */
127
    public function getCreateFromFormatWillThrowDateTimeFactoryExceptionData(): array
128
    {
129
        return [
130
            [
131
                'test',
132
                'Y-m-d',
133
            ],
134
        ];
135
    }
136
137
    /**
138
     * Ensure that a \DateTime instance can be created from the provided format.
139
     *
140
     * @param string $spec
141
     * @param string $format
142
     * @param array  $options
143
     *
144
     * @dataProvider getCreateFromFormatData
145
     *
146
     * @covers \Arp\DateTime\DateTimeFactory::createFromFormat
147
     * @covers \Arp\DateTime\DateTimeFactory::resolveDateTimeZone
148
     */
149
    public function testCreateFromFormat(string $spec, string $format, array $options = []): void
150
    {
151
        /** @var DateTimeFactory|MockObject $factory */
152
        $factory = $this->getMockBuilder(DateTimeFactory::class)
153
                        ->onlyMethods(['createDateTimeZone'])
154
                        ->getMock();
155
156
        if (! empty($options['time_zone'])) {
157
            $dateTimeZone = new \DateTimeZone($options['time_zone']);
158
159
            $factory->expects($this->once())
160
                    ->method('createDateTimeZone')
161
                    ->with($options['time_zone'])
162
                    ->willReturn($dateTimeZone);
163
        }
164
165
        $dateTime = $factory->createFromFormat($spec, $format, $options);
166
167
        $this->assertSame($spec, $dateTime->format($format));
168
169
        if (isset($dateTimeZone)) {
170
            $this->assertSame($options['time_zone'], $dateTimeZone->getName());
171
        }
172
    }
173
174
    /**
175
     * @see https://www.php.net/manual/en/timezones.europe.php
176
     *
177
     * @return array
178
     */
179
    public function getCreateFromFormatData(): array
180
    {
181
        return [
182
183
            [
184
                '2019-04-01',
185
                'Y-m-d',
186
            ],
187
188
            [
189
                '1976/01/14',
190
                'Y/m/d',
191
            ],
192
193
            [
194
                '2019-08-14 17:34:55',
195
                'Y-m-d H:i:s',
196
                [
197
                    'time_zone' => 'UTC',
198
                ],
199
            ],
200
201
            [
202
                '2010-10-26 11:19:32',
203
                'Y-m-d H:i:s',
204
                [
205
                    'time_zone' => 'Europe/London',
206
                ],
207
            ],
208
209
        ];
210
    }
211
212
    /**
213
     * Ensure a \DateTimeZone instance is returned according to the provided $spec and $options.
214
     *
215
     * @param string $spec
216
     * @param array  $options
217
     *
218
     * @dataProvider getCreateDateTimeZoneData
219
     *
220
     * @covers \Arp\DateTime\DateTimeFactory::createDateTimeZone
221
     */
222
    public function testCreateDateTimeZone(string $spec, array $options = []): void
223
    {
224
        $factory = new DateTimeFactory();
225
226
        $dateTimeZone = $factory->createDateTimeZone($spec, $options);
227
228
        $this->assertSame($spec, $dateTimeZone->getName());
229
    }
230
231
    /**
232
     * @see https://www.php.net/manual/en/timezones.europe.php
233
     *
234
     * @return array
235
     */
236
    public function getCreateDateTimeZoneData(): array
237
    {
238
        return [
239
            [
240
                'Europe/London',
241
            ],
242
            [
243
                'Europe/Amsterdam',
244
            ],
245
            [
246
                'Europe/Rome',
247
            ],
248
            [
249
                'Atlantic/Bermuda',
250
            ],
251
            [
252
                'Atlantic/Azores',
253
            ],
254
            [
255
                'Antarctica/DumontDUrville',
256
            ],
257
        ];
258
    }
259
260
    /**
261
     * Ensure that if providing an invalid $spec argument to createDateTimeZone() a new DateTimeFactoryException
262
     * is thrown.
263
     *
264
     * @param string $spec The invalid timezone specification.
265
     *
266
     * @throws DateTimeFactoryException
267
     *
268
     * @dataProvider getCreateDateTimeZoneWillThrowDateTimeFactoryExceptionIfSpecIsInvalidData
269
     *
270
     * @covers \Arp\DateTime\DateTimeFactory::createDateTimeZone
271
     */
272
    public function testCreateDateTimeZoneWillThrowDateTimeFactoryExceptionIfSpecIsInvalid(string $spec): void
273
    {
274
        $factory = new DateTimeFactory();
275
276
        $this->expectException(DateTimeFactoryException::class);
277
        $this->expectExceptionMessage(
278
            sprintf(
279
                'Failed to create a valid \DateTimeZone instance using \'%s\' in \'%s\'.',
280
                $spec,
281
                DateTimeFactory::class
282
            )
283
        );
284
285
        $factory->createDateTimeZone($spec);
286
    }
287
288
    /**
289
     * @return array
290
     */
291
    public function getCreateDateTimeZoneWillThrowDateTimeFactoryExceptionIfSpecIsInvalidData(): array
292
    {
293
        return [
294
            [
295
                'skjdvbnksd',
296
            ],
297
            [
298
                '2345234',
299
            ],
300
            [
301
                'Europe/MyEmpire',
302
            ],
303
        ];
304
    }
305
}
306