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

ApplicationTest::DataProviderFastRouteCacheComamnd()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 27
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 14
nc 2
nop 0
dl 0
loc 27
rs 8.8571
c 0
b 0
f 0
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 PHPUnit\Framework\TestCase as Base;
12
use ReflectionMethod;
13
use SignpostMarv\DaftFramework\Framework;
14
use SignpostMarv\DaftFramework\Symfony\Console\Application;
15
use SignpostMarv\DaftFramework\Symfony\Console\Command\Command;
16
use SignpostMarv\DaftFramework\Symfony\Console\Command\FastRouteCacheCommand;
17
use SignpostMarv\DaftFramework\Symfony\Console\DaftConsoleSource;
18
use SignpostMarv\DaftFramework\Tests\fixtures\Console\Command\TestCommand;
19
use SignpostMarv\DaftRouter\DaftSource;
20
use SignpostMarv\DaftRouter\Tests\Fixtures\Config;
21
use Symfony\Component\Console\Command\Command as BaseCommand;
22
use Symfony\Component\Console\Input\InputArgument;
23
use Symfony\Component\Console\Tester\CommandTester;
24
25
class ApplicationTest extends Base
26
{
27
    final public function DataProviderConsoleApplicationConfigFiltered() : Generator
28
    {
29
        foreach ($this->DataProviderConsoleApplicationConfig() as $args) {
30
            if (6 === count($args) && is_string($args[0] ?? null) && is_file($args[0])) {
31
                $configFile = array_shift($args);
32
                end($args);
33
                $args[key($args)][] = (array) include($configFile);
34
35
                yield array_values($args);
36
            }
37
        }
38
    }
39
40
    final public function DataProviderDaftConsoleCommands() : Generator
41
    {
42
        foreach ($this->DataProviderConsoleApplicationConfigFiltered() as $args) {
43
            $this->assertTrue(is_a($args[3], Framework::class, true));
44
45
            /**
46
            * @var Framework $framework
47
            */
48
            $framework = new $args[3](...$args[4]);
49
50
            foreach (($args[2] ?? []) as $maybeCommand) {
51
                if (is_string($maybeCommand) && is_a($maybeCommand, Command::class, true)) {
52
                    /**
53
                    * @var Command $command
54
                    */
55
                    $command = new $maybeCommand($maybeCommand::getDefaultName());
56
57
                    yield [$framework, $command];
58
                }
59
            }
60
        }
61
    }
62
63
    /**
64
    * @dataProvider DataProviderConsoleApplicationConfigFiltered
65
    */
66
    public function testApplicationSetup(
67
        string $name,
68
        string $version,
69
        array $expectedCommandInstances,
70
        string $frameworkImplementation,
71
        array $frameworkArgs
72
    ) : void {
73
        $this->assertTrue(is_a($frameworkImplementation, Framework::class, true));
74
75
        /**
76
        * @var Framework $framework
77
        */
78
        $framework = new $frameworkImplementation(...$frameworkArgs);
79
80
        $this->assertSame($frameworkArgs[0], $framework->ObtainBaseUrl());
81
        $this->assertSame($frameworkArgs[1], $framework->ObtainBasePath());
82
        $this->assertSame($frameworkArgs[2], $framework->ObtainConfig());
83
84
        $application = Application::CollectApplicationWithCommands($name, $version, $framework);
85
86
        $this->assertSame($name, $application->getName());
87
        $this->assertSame($version, $application->getVersion());
88
89
        $commands = array_map('get_class', $application->all());
90
91
        foreach ($expectedCommandInstances as $expectedComamnd) {
92
            $this->assertTrue(class_exists($expectedComamnd));
93
            $this->assertContains($expectedComamnd, $commands);
94
        }
95
96
        $constructedApplication = new Application($name, $version);
97
98
        $constructedApplication->AttachDaftFramework($framework);
99
100
        $constructedApplication->CollectCommands(...$expectedCommandInstances);
101
102
        $commands = array_map('get_class', $application->all());
103
104
        foreach ($expectedCommandInstances as $expectedComamnd) {
105
            $this->assertTrue(class_exists($expectedComamnd));
106
            $this->assertContains($expectedComamnd, $commands);
107
        }
108
109
        $failingApplication = new Application($name, $version);
110
111
        $this->assertSame($name, $application->getName());
112
        $this->assertSame($version, $application->getVersion());
113
114
        foreach ($expectedCommandInstances as $expectedComamnd) {
115
            /**
116
            * @var BaseCommand $command
117
            */
118
            $command = new $expectedComamnd($expectedComamnd::getDefaultName());
119
120
            $this->expectException(BadMethodCallException::class);
121
            $this->expectExceptionMessage(
122
                'Cannot add a daft framework command without a framework being attached!'
123
            );
124
125
            $failingApplication->add($command);
126
        }
127
    }
128
129
    /**
130
    * @dataProvider DataProviderConsoleApplicationConfigFiltered
131
    *
132
    * @depends testApplicationSetup
133
    */
134
    public function testCommandCollectionWithoutFramework(
135
        string $name,
136
        string $version,
137
        array $expectedCommandInstances,
138
        string $frameworkImplementation,
139
        array $frameworkArgs
140
    ) : void {
141
        $constructedApplication = new Application($name, $version);
142
143
        $this->expectException(BadMethodCallException::class);
144
        $this->expectExceptionMessage(
145
            'Cannot collect commands without an attached framework instance!'
146
        );
147
148
        $constructedApplication->CollectCommands(...$expectedCommandInstances);
149
    }
150
151
    /**
152
    * @dataProvider DataProviderDaftConsoleCommands
153
    *
154
    * @depends testApplicationSetup
155
    */
156
    public function testCommandFrameworkAttachment(Framework $framework, Command $command) : void
157
    {
158
        $this->assertFalse($command->CheckIfUsingFrameworkInstance($framework));
159
160
        $command->AttachDaftFramework($framework);
161
162
        $this->assertTrue($command->CheckIfUsingFrameworkInstance($framework));
163
164
        $this->assertSame($framework, $command->DetachDaftFramework());
165
166
        $this->assertFalse($command->CheckIfUsingFrameworkInstance($framework));
167
168
        $command->AttachDaftFramework($framework);
169
170
        $this->assertTrue($command->CheckIfUsingFrameworkInstance($framework));
171
172
        $this->expectException(BadMethodCallException::class);
173
        $this->expectExceptionMessage(
174
            'Framework must not be attached if a framework is already attached!'
175
        );
176
177
        $command->AttachDaftFramework($framework);
178
    }
179
180
    public function DataProviderFastRouteCacheComamnd() : Generator
181
    {
182
        $expectedOutput = file_get_contents(
183
            __DIR__ .
184
            '/fixtures/here-is-one-i-made-earlier.fast-route.cache'
185
        );
186
187
        foreach ($this->DataProviderConsoleApplicationConfigFiltered() as $args) {
188
            $frameworkImplementation = $args[3];
189
190
            $args[4][2][DaftConsoleSource::class][] = FastRouteCacheCommand::class;
191
            $args[4][2][DaftSource::class]['sources'] = [
192
                Config::class,
193
            ];
194
195
            /**
196
            * @var Framework $framework
197
            */
198
            $framework = new $frameworkImplementation(...$args[4]);
199
200
            $application = Application::CollectApplicationWithCommands(
201
                $args[0],
202
                $args[1],
203
                $framework
204
            );
205
206
            yield [$application, $expectedOutput];
207
        }
208
    }
209
210
    /**
211
    * @dataProvider DataProviderFastRouteCacheComamnd
212
    */
213
    public function testFastRouteCacheCommand(
214
        Application $application,
215
        string $expectedOutput
216
    ) : void {
217
        $command = new FastRouteCacheCommand();
218
219
        $ref = new ReflectionMethod($command, 'configure');
220
        $ref->setAccessible(true);
221
222
        $command->getDefinition()->setDefinition([]);
223
224
        $ref->invoke($command);
225
226
        $this->assertSame(
227
            'Update the cache used by the daft framework router',
228
            $command->getDescription()
229
        );
230
231
        $this->assertSame(
232
            [
233
                'sources' => [
234
                    'name' => 'sources',
235
                    'required' => true,
236
                    'array' => true,
237
                    'default' => [],
238
                    'description' => 'class names for sources',
239
                ],
240
            ],
241
            array_map(
242
                function (InputArgument $arg) : array {
243
                    return [
244
                        'name' => $arg->getName(),
245
                        'required' => $arg->isRequired(),
246
                        'array' => $arg->isArray(),
247
                        'default' => $arg->getDefault(),
248
                        'description' => $arg->getDescription(),
249
                    ];
250
                },
251
                $command->getDefinition()->getArguments()
252
            )
253
        );
254
255
        // ref: https://stackoverflow.com/questions/47183273/test-command-symfony-with-phpunit
256
257
        $command = $application->find('daft-framework:router:update-cache');
258
259
        $this->assertInstanceOf(FastRouteCacheCommand::class, $command);
260
261
        $commandTester = new CommandTester($command);
262
263
        $commandTester->execute(
264
            [
265
                'sources' => [
266
                    Config::class,
267
                ],
268
            ],
269
            [
270
                'command' => $command->getName(),
271
            ]
272
        );
273
274
        $this->assertSame($expectedOutput, $commandTester->getDisplay());
275
    }
276
277
    protected function DataProviderConsoleApplicationConfig() : Generator
278
    {
279
        yield from [
280
            [
281
                __DIR__ . '/fixtures/config.php',
282
                'Test',
283
                '0.0.0',
284
                [
285
                    TestCommand::class,
286
                ],
287
                Framework::class,
288
                [
289
                    'https://example.com/',
290
                    realpath(__DIR__ . '/fixtures'),
291
                ],
292
            ],
293
        ];
294
    }
295
}
296