Passed
Push — master ( 02721e...1546a1 )
by SignpostMarv
02:51
created

ImplementationTest::DataProviderBadSources()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 89
Code Lines 56

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 56
nc 1
nop 0
dl 0
loc 89
rs 8.5731
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
* @author SignpostMarv
4
*/
5
declare(strict_types=1);
6
7
namespace SignpostMarv\DaftFramework\Tests;
8
9
use BadMethodCallException;
10
use Generator;
11
use InvalidArgumentException;
12
use ParagonIE\EasyDB\EasyDB;
13
use PHPUnit\Framework\TestCase as Base;
14
use SignpostMarv\DaftFramework\Framework;
15
use SignpostMarv\DaftFramework\HttpHandler;
16
use SignpostMarv\DaftRouter\DaftSource;
17
use SignpostMarv\DaftRouter\Tests\Fixtures\Config as DaftRouterFixturesConfig;
18
use Symfony\Component\HttpFoundation\Request;
19
20
class ImplementationTest extends Base
21
{
22
    public function tearDown()
23
    {
24
        foreach (
25
            array_filter(
26
                array_filter([
27
                    realpath(__DIR__ . '/fixtures/http-kernel.fast-route.cache'),
28
                ], 'is_string'),
29
                'is_file'
30
            ) as $cleanup
31
        ) {
32
            unlink($cleanup);
33
        }
34
    }
35
36
    public function DataProviderGoodSources() : Generator
37
    {
38
        yield from [
39
            [
40
                Framework::class,
41
                [],
42
                'https://example.com/',
43
                realpath(__DIR__ . '/fixtures'),
44
                [],
45
            ],
46
            [
47
                Framework::class,
48
                [],
49
                'https://example.com:8080/',
50
                realpath(__DIR__ . '/fixtures'),
51
                [],
52
            ],
53
            [
54
                Framework::class,
55
                [
56
                    'ConfigureDatabaseConnection' => [
57
                        'sqlite::memory:',
58
                        null,
59
                        null,
60
                        [],
61
                    ],
62
                ],
63
                'https://example.com/',
64
                realpath(__DIR__ . '/fixtures'),
65
                [],
66
            ],
67
            [
68
                HttpHandler::class,
69
                [
70
                    'ConfigureDatabaseConnection' => [
71
                        'sqlite::memory:',
72
                        null,
73
                        null,
74
                        [],
75
                    ],
76
                ],
77
                'https://example.com/',
78
                realpath(__DIR__ . '/fixtures'),
79
                [
80
                    DaftSource::class => [
81
                        'cacheFile' => (__DIR__ . '/fixtures/http-kernel.fast-route.cache'),
82
                        'sources' => [
83
                            DaftRouterFixturesConfig::class,
84
                        ],
85
                    ],
86
                ],
87
            ],
88
        ];
89
    }
90
91
    public function DataProviderBadSources() : Generator
92
    {
93
        yield from [
94
            [
95
                Framework::class,
96
                InvalidArgumentException::class,
97
                'Base path must be a directory!',
98
                null,
99
                [],
100
                'https://example.com/',
101
                __FILE__,
102
                [],
103
            ],
104
            [
105
                Framework::class,
106
                InvalidArgumentException::class,
107
                'Path should be explicitly set to via realpath!',
108
                null,
109
                [],
110
                'https://example.com/',
111
                (__DIR__ . '/fixtures/'),
112
                [],
113
            ],
114
            [
115
                HttpHandler::class,
116
                InvalidArgumentException::class,
117
                sprintf(
118
                    '%s config not found!',
119
                    DaftSource::class
120
                ),
121
                null,
122
                [],
123
                'https://example.com/',
124
                realpath(__DIR__ . '/fixtures'),
125
                [],
126
            ],
127
            [
128
                HttpHandler::class,
129
                InvalidArgumentException::class,
130
                sprintf(
131
                    '%s config does not specify "%s" correctly.',
132
                    DaftSource::class,
133
                    'cacheFile'
134
                ),
135
                null,
136
                [],
137
                'https://example.com/',
138
                realpath(__DIR__ . '/fixtures'),
139
                [
140
                    DaftSource::class => [
141
                        'cacheFile' => false,
142
                        'sources' => false,
143
                    ],
144
                ],
145
            ],
146
            [
147
                HttpHandler::class,
148
                InvalidArgumentException::class,
149
                sprintf(
150
                    '%s config does not specify "%s" correctly.',
151
                    DaftSource::class,
152
                    'sources'
153
                ),
154
                null,
155
                [],
156
                'https://example.com/',
157
                realpath(__DIR__ . '/fixtures'),
158
                [
159
                    DaftSource::class => [
160
                        'cacheFile' => (__DIR__ . '/fixtures/http-kernel.fast-route.cache'),
161
                        'sources' => false,
162
                    ],
163
                ],
164
            ],
165
            [
166
                HttpHandler::class,
167
                InvalidArgumentException::class,
168
                sprintf(
169
                    '%s config property cacheFile does not exist under the framework base path.',
170
                    DaftSource::class
171
                ),
172
                null,
173
                [],
174
                'https://example.com/',
175
                realpath(__DIR__ . '/fixtures'),
176
                [
177
                    DaftSource::class => [
178
                        'cacheFile' => __FILE__,
179
                        'sources' => [],
180
                    ],
181
                ],
182
            ],
183
        ];
184
    }
185
186
    public function DataProviderGoodSourcesSansDatabaseConnection() : Generator
187
    {
188
        foreach ($this->DataProviderGoodSources() as $args) {
189
            if ( ! isset($args[1]['ConfigureDatabaseConnection'])) {
190
                yield $args;
191
            }
192
        }
193
    }
194
195
    public function DataProviderGoodSourcesWithDatabaseConnection() : Generator
196
    {
197
        foreach ($this->DataProviderGoodSources() as $args) {
198
            if (isset($args[1]['ConfigureDatabaseConnection'])) {
199
                yield $args;
200
            }
201
        }
202
    }
203
204
    /**
205
    * @param array<string, array<int, mixed>> $postConstructionCalls
206
    *
207
    * @dataProvider DataProviderGoodSources
208
    */
209
    public function testEverythingInitialisesFine(
210
        string $implementation,
211
        array $postConstructionCalls,
212
        ...$implementationArgs
213
    ) : Framework {
214
        $instance = $this->ObtainFrameworkInstance($implementation, ...$implementationArgs);
215
        $this->ConfigureFrameworkInstance($instance, $postConstructionCalls);
216
217
        list($baseUrl, $basePath, $config) = $this->extractDefaultFrameworkArgs(
218
            $implementationArgs
219
        );
220
221
        $this->assertSame($baseUrl, $instance->ObtainBaseUrl());
222
        $this->assertSame($basePath, $instance->ObtainBasePath());
223
        $this->assertSame($config, $instance->ObtainConfig());
224
225
        if (isset($postConstructionCalls['ConfigureDatabaseConnection'])) {
226
            $this->assertInstanceOf(EasyDB::class, $instance->ObtainDatabaseConnection());
227
        }
228
229
        return $instance;
230
    }
231
232
    /**
233
    * @param array<string, array<int, mixed>> $postConstructionCalls
234
    *
235
    * @dataProvider DataProviderBadSources
236
    *
237
    * @depends testEverythingInitialisesFine
238
    */
239
    public function testThingsFail(
240
        string $implementation,
241
        string $expectedExceptionClass,
242
        ? string $expectedExceptionMessage,
243
        ? int $expectedExceptionCode,
244
        array $postConstructionCalls,
245
        ...$implementationArgs
246
    ) : void {
247
        $this->expectException($expectedExceptionClass);
248
        if (is_string($expectedExceptionMessage)) {
249
            $this->expectExceptionMessage($expectedExceptionMessage);
250
        }
251
        if (is_int($expectedExceptionCode)) {
252
            $this->expectExceptionCode($expectedExceptionCode);
253
        }
254
255
        $instance = $this->ObtainFrameworkInstance($implementation, ...$implementationArgs);
256
        $this->ConfigureFrameworkInstance($instance, $postConstructionCalls);
257
    }
258
259
    /**
260
    * @param array<string, array<int, mixed>> $postConstructionCalls
261
    *
262
    * @dataProvider DataProviderGoodSourcesSansDatabaseConnection
263
    *
264
    * @depends testEverythingInitialisesFine
265
    */
266
    public function testGoodSourcesSansDatabaseConnection(
267
        string $implementation,
268
        array $postConstructionCalls,
269
        ...$implementationArgs
270
    ) : void {
271
        $instance = $this->ObtainFrameworkInstance($implementation, ...$implementationArgs);
272
        $this->ConfigureFrameworkInstance($instance, $postConstructionCalls);
273
274
        $this->expectException(BadMethodCallException::class);
275
        $this->expectExceptionMessage('Database Connection not available!');
276
277
        $instance->ObtainDatabaseConnection();
278
    }
279
280
    /**
281
    * @param array<string, array<int, mixed>> $postConstructionCalls
282
    *
283
    * @dataProvider DataProviderGoodSourcesWithDatabaseConnection
284
    *
285
    * @depends testEverythingInitialisesFine
286
    */
287
    public function testGoodSourcesWithDatabaseConnection(
288
        string $implementation,
289
        array $postConstructionCalls,
290
        ...$implementationArgs
291
    ) : void {
292
        $instance = $this->ObtainFrameworkInstance($implementation, ...$implementationArgs);
293
        $this->ConfigureFrameworkInstance($instance, $postConstructionCalls);
294
295
        $this->expectException(BadMethodCallException::class);
296
        $this->expectExceptionMessage('Database Connection already made!');
297
298
        $instance->ConfigureDatabaseConnection(
299
            ...($postConstructionCalls['ConfigureDatabaseConnection'])
300
        );
301
    }
302
303
    /**
304
    * @dataProvider DataProviderGoodSources
305
    *
306
    * @depends testEverythingInitialisesFine
307
    */
308
    public function testUnpairedFrameworksFail(string $implementation) : void
309
    {
310
        $this->assertTrue(is_a($implementation, Framework::class, true));
311
312
        $this->assertFalse(Request::createFromGlobals() === Request::createFromGlobals());
313
314
        $this->expectException(InvalidArgumentException::class);
315
        $this->expectExceptionMessage(
316
            'No framework instance has been paired with the provided request!'
317
        );
318
319
        $implementation::ObtainFrameworkForRequest(Request::createFromGlobals());
320
    }
321
322
    /**
323
    * @param array<string, array<int, mixed>> $postConstructionCalls
324
    *
325
    * @dataProvider DataProviderGoodSources
326
    *
327
    * @depends testEverythingInitialisesFine
328
    * @depends testUnpairedFrameworksFail
329
    */
330
    public function testDisposeOfFrameworkReferences(
331
        string $implementation,
332
        array $postConstructionCalls,
333
        ...$implementationArgs
334
    ) : void {
335
        list($instance, $requestA, $requestB) = $this->PrepareReferenceDisposalTest(
336
            $implementation,
337
            $postConstructionCalls,
338
            Request::createFromGlobals(),
339
            Request::createFromGlobals(),
340
            ...$implementationArgs
341
        );
342
343
        $implementation::DisposeOfFrameworkReferences($instance);
344
345
        $this->expectException(InvalidArgumentException::class);
346
        $this->expectExceptionMessage(
347
            'No framework instance has been paired with the provided request!'
348
        );
349
350
        $implementation::ObtainFrameworkForRequest($requestA);
351
    }
352
353
    /**
354
    * @param array<string, array<int, mixed>> $postConstructionCalls
355
    *
356
    * @dataProvider DataProviderGoodSources
357
    *
358
    * @depends testEverythingInitialisesFine
359
    * @depends testUnpairedFrameworksFail
360
    */
361
    public function testDisposeOfRequestReferences(
362
        string $implementation,
363
        array $postConstructionCalls,
364
        ...$implementationArgs
365
    ) : void {
366
        list($instance, $requestA, $requestB) = $this->PrepareReferenceDisposalTest(
367
            $implementation,
368
            $postConstructionCalls,
369
            Request::createFromGlobals(),
370
            Request::createFromGlobals(),
371
            ...$implementationArgs
372
        );
373
374
        $implementation::DisposeOfFrameworkReferences($instance);
375
        $implementation::DisposeOfRequestReferences($requestA);
376
        $implementation::PairWithRequest($instance, $requestB);
377
378
        $this->assertSame($instance, $implementation::ObtainFrameworkForRequest($requestB));
379
380
        $implementation::DisposeOfRequestReferences($requestB);
381
382
        $this->expectException(InvalidArgumentException::class);
383
        $this->expectExceptionMessage(
384
            'No framework instance has been paired with the provided request!'
385
        );
386
387
        $implementation::ObtainFrameworkForRequest($requestB);
388
    }
389
390
    protected function extractDefaultFrameworkArgs(array $implementationArgs) : array
391
    {
392
        list($baseUrl, $basePath, $config) = $implementationArgs;
393
394
        return [$baseUrl, $basePath, $config];
395
    }
396
397
    protected function PrepareReferenceDisposalTest(
398
        string $implementation,
399
        array $postConstructionCalls,
400
        Request $requestA,
401
        Request $requestB,
402
        ...$implementationArgs
403
    ) : array {
404
        $instance = $this->ObtainFrameworkInstance(
405
            $implementation,
406
            ...$implementationArgs
407
        );
408
        $this->ConfigureFrameworkInstance($instance, $postConstructionCalls);
409
410
        $requestA = Request::createFromGlobals();
411
        $requestB = Request::createFromGlobals();
412
413
        $implementation::PairWithRequest($instance, $requestA);
414
        $implementation::PairWithRequest($instance, $requestB);
415
416
        $this->assertSame($instance, $implementation::ObtainFrameworkForRequest($requestA));
417
        $this->assertSame($instance, $implementation::ObtainFrameworkForRequest($requestB));
418
419
        return [$instance, $requestA, $requestB];
420
    }
421
422
    protected function ObtainFrameworkInstance(
423
        string $implementation,
424
        ...$implementationArgs
425
    ) : Framework {
426
        return Utilities::ObtainFrameworkInstance(
427
            $this,
428
            $implementation,
429
            ...$implementationArgs
430
        );
431
    }
432
433
    protected function ConfigureFrameworkInstance(
434
        Framework $instance,
435
        array $postConstructionCalls
436
    ) : void {
437
        Utilities::ConfigureFrameworkInstance($this, $instance, $postConstructionCalls);
438
    }
439
}
440