Passed
Pull Request — main (#8)
by Jesús
02:11
created

RouterTest::test_multiple_optional_argument()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 0
dl 0
loc 9
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace GacelaTest\Unit\Router;
6
7
use Gacela\Router\Entities\Request;
8
use Gacela\Router\Exceptions\UnsupportedHttpMethodException;
9
use Gacela\Router\MappingInterfaces;
10
use Gacela\Router\Router;
11
use Gacela\Router\Routes;
12
use GacelaTest\Unit\Router\Fake\Name;
13
use GacelaTest\Unit\Router\Fake\NameInterface;
14
use GacelaTest\Unit\Router\Fixtures\FakeController;
15
use GacelaTest\Unit\Router\Fixtures\FakeControllerWithDependencies;
16
use GacelaTest\Unit\Router\Fixtures\FakeControllerWithRequest;
17
use Generator;
18
use PHPUnit\Framework\TestCase;
19
20
final class RouterTest extends TestCase
21
{
22
    private const PROVIDER_TRIES = 10;
23
24
    public function test_it_should_respond_if_everything_matches(): void
25
    {
26
        $_SERVER['REQUEST_URI'] = 'https://example.org/expected/uri';
27
        $_SERVER['REQUEST_METHOD'] = 'GET';
28
29
        $this->expectOutputString('Expected!');
30
31
        Router::configure(static function (Routes $routes): void {
32
            $routes->get('expected/uri', FakeController::class, 'basicAction');
33
        });
34
    }
35
36
    public function test_it_should_not_respond_if_the_uri_does_not_matches(): void
37
    {
38
        $_SERVER['REQUEST_URI'] = 'https://example.org/unexpected/uri';
39
        $_SERVER['REQUEST_METHOD'] = 'GET';
40
41
        $this->expectOutputString('');
42
43
        Router::configure(static function (Routes $routes): void {
44
            $routes->get('other/uri', FakeController::class, 'basicAction');
45
        });
46
    }
47
48
    public function test_it_should_not_respond_if_the_method_does_not_matches(): void
49
    {
50
        $_SERVER['REQUEST_URI'] = 'https://example.org/expected/uri';
51
        $_SERVER['REQUEST_METHOD'] = 'GET';
52
53
        $this->expectOutputString('');
54
55
        Router::configure(static function (Routes $routes): void {
56
            $routes->post('expected/uri', FakeController::class, 'basicAction');
57
        });
58
    }
59
60
    public function test_it_should_pass_many_params_to_the_action(): void
61
    {
62
        $params = ['foo', 'bar', 'baz'];
63
64
        $_SERVER['REQUEST_URI'] = "https://example.org/{$params[0]}/{$params[1]}/{$params[2]}";
65
        $_SERVER['REQUEST_METHOD'] = 'GET';
66
67
        $this->expectOutputString("The params are '{$params[0]}', '{$params[1]}' and '{$params[2]}'!");
68
69
        Router::configure(static function (Routes $routes): void {
70
            $routes->get('{firstParam}/{secondParam}/{thirdParam}', FakeController::class, 'manyParamsAction');
71
        });
72
    }
73
74
    public function test_it_should_pass_associated_params_by_name_to_the_action(): void
75
    {
76
        $params = ['foo', 'bar', 'baz'];
77
78
        $_SERVER['REQUEST_URI'] = "https://example.org/{$params[0]}/{$params[1]}/{$params[2]}";
79
        $_SERVER['REQUEST_METHOD'] = 'GET';
80
81
        $this->expectOutputString("The params are '{$params[1]}', '{$params[0]}' and '{$params[2]}'!");
82
83
        Router::configure(static function (Routes $routes): void {
84
            $routes->get('{secondParam}/{firstParam}/{thirdParam}', FakeController::class, 'manyParamsAction');
85
        });
86
    }
87
88
    /**
89
     * @dataProvider stringProvider
90
     */
91
    public function test_it_should_pass_string_params_to_the_action(string $string): void
92
    {
93
        $_SERVER['REQUEST_URI'] = "https://example.org/expected/string/is/{$string}";
94
        $_SERVER['REQUEST_METHOD'] = 'GET';
95
96
        $this->expectOutputString("The 'string' param is '{$string}'!");
97
98
        Router::configure(static function (Routes $routes): void {
99
            $routes->get('expected/string/is/{param}', FakeController::class, 'stringParamAction');
100
        });
101
    }
102
103
    public function stringProvider(): Generator
104
    {
105
        for ($try = 0; $try < self::PROVIDER_TRIES; ++$try) {
106
            $randomString = (string)'word-' . mt_rand();
107
            yield $randomString => ['string' => $randomString];
108
        }
109
    }
110
111
    /**
112
     * @dataProvider intProvider
113
     */
114
    public function test_it_should_pass_int_params_to_the_action(string $int): void
115
    {
116
        $_SERVER['REQUEST_URI'] = "https://example.org/expected/integer/is/{$int}";
117
        $_SERVER['REQUEST_METHOD'] = 'GET';
118
119
        $this->expectOutputString("The 'int' param is '{$int}'!");
120
121
        Router::configure(static function (Routes $routes): void {
122
            $routes->get('expected/integer/is/{param}', FakeController::class, 'intParamAction');
123
        });
124
    }
125
126
    public function intProvider(): Generator
127
    {
128
        for ($try = 0; $try < self::PROVIDER_TRIES; ++$try) {
129
            $randomInt = (string)random_int(1, 9999);
130
            yield "#{$randomInt}" => ['int' => $randomInt];
131
        }
132
    }
133
134
    /**
135
     * @dataProvider floatProvider
136
     */
137
    public function test_it_should_pass_float_params_to_the_action(string $float): void
138
    {
139
        $_SERVER['REQUEST_URI'] = "https://example.org/expected/float/is/{$float}";
140
        $_SERVER['REQUEST_METHOD'] = 'GET';
141
142
        $this->expectOutputString("The 'float' param is '{$float}'!");
143
144
        Router::configure(static function (Routes $routes): void {
145
            $routes->get('expected/float/is/{param}', FakeController::class, 'floatParamAction');
146
        });
147
    }
148
149
    public function floatProvider(): Generator
150
    {
151
        for ($try = 0; $try < self::PROVIDER_TRIES; ++$try) {
152
            $randomFloat = (string)mt_rand();
153
            yield "#{$randomFloat}" => ['float' => $randomFloat];
154
        }
155
    }
156
157
    /**
158
     * @dataProvider boolProvider
159
     */
160
    public function test_it_should_pass_bool_params_to_the_action(string $given, string $expected): void
161
    {
162
        $_SERVER['REQUEST_URI'] = "https://example.org/expected/bool/is/{$given}";
163
        $_SERVER['REQUEST_METHOD'] = 'GET';
164
165
        $this->expectOutputString("The 'bool' param is '{$expected}'!");
166
167
        Router::configure(static function (Routes $routes): void {
168
            $routes->get('expected/bool/is/{param}', FakeController::class, 'boolParamAction');
169
        });
170
    }
171
172
    public function boolProvider(): iterable
173
    {
174
        yield 'true' => ['given' => 'true', 'expected' => 'true'];
175
        yield 'false' => ['given' => 'false', 'expected' => 'false'];
176
        yield '1' => ['given' => '1', 'expected' => 'true'];
177
        yield '0' => ['given' => '0', 'expected' => 'false'];
178
    }
179
180
    public function test_it_should_respond_only_the_first_match(): void
181
    {
182
        $_SERVER['REQUEST_URI'] = 'https://example.org/expected/uri';
183
        $_SERVER['REQUEST_METHOD'] = 'GET';
184
185
        $this->expectOutputString('Expected!');
186
187
        Router::configure(static function (Routes $routes): void {
188
            $routes->get('expected/uri', FakeController::class, 'basicAction');
189
            $routes->get('expected/{param}', FakeController::class, 'stringParamAction');
190
        });
191
    }
192
193
    public function test_optional_argument(): void
194
    {
195
        $_SERVER['REQUEST_URI'] = 'https://example.org/optional';
196
        $_SERVER['REQUEST_METHOD'] = 'GET';
197
198
        $this->expectOutputString('Expected!');
199
200
        Router::configure(static function (Routes $routes): void {
201
            $routes->get('optional/{param?}', FakeController::class, 'basicAction');
202
        });
203
    }
204
205
    public function test_multiple_optional_argument(): void
206
    {
207
        $_SERVER['REQUEST_URI'] = 'https://example.org/optional';
208
        $_SERVER['REQUEST_METHOD'] = 'GET';
209
210
        $this->expectOutputString('Expected!');
211
212
        Router::configure(static function (Routes $routes): void {
213
            $routes->get('optional/{param1?}/{param2?}', FakeController::class, 'basicAction');
214
        });
215
    }
216
217
    public function test_it_should_thrown_exception_if_method_does_not_exist(): void
218
    {
219
        $this->expectException(UnsupportedHttpMethodException::class);
220
221
        Router::configure(static function (Routes $routes): void {
222
            $routes->invalidName('', FakeController::class);
0 ignored issues
show
Bug introduced by
The method invalidName() does not exist on Gacela\Router\Routes. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

222
            $routes->/** @scrutinizer ignore-call */ 
223
                     invalidName('', FakeController::class);
Loading history...
223
        });
224
    }
225
226
    /**
227
     * @dataProvider anyHttpMethodProvider
228
     */
229
    public function test_any_http_method(string $httpMethod): void
230
    {
231
        $_SERVER['REQUEST_URI'] = 'https://example.org/expected/uri';
232
        $_SERVER['REQUEST_METHOD'] = $httpMethod;
233
234
        $this->expectOutputString('Expected!');
235
236
        Router::configure(static function (Routes $routes): void {
237
            $routes->any('expected/uri', FakeController::class, 'basicAction');
238
        });
239
    }
240
241
    public function anyHttpMethodProvider(): Generator
242
    {
243
        yield ['METHOD_GET' => Request::METHOD_GET];
244
        yield ['METHOD_CONNECT' => Request::METHOD_CONNECT];
245
        yield ['METHOD_DELETE' => Request::METHOD_DELETE];
246
        yield ['METHOD_HEAD' => Request::METHOD_HEAD];
247
        yield ['METHOD_OPTIONS' => Request::METHOD_OPTIONS];
248
        yield ['METHOD_PATCH' => Request::METHOD_PATCH];
249
        yield ['METHOD_POST' => Request::METHOD_POST];
250
        yield ['METHOD_PUT' => Request::METHOD_PUT];
251
        yield ['METHOD_TRACE' => Request::METHOD_TRACE];
252
    }
253
254
    public function test_inject_dependencies_in_controllers(): void
255
    {
256
        $_SERVER['REQUEST_URI'] = 'https://example.org/expected/uri';
257
        $_SERVER['REQUEST_METHOD'] = 'GET';
258
259
        $this->expectOutputString('default-Expected!');
260
261
        Router::configure(static function (Routes $routes, MappingInterfaces $mappingInterfaces): void {
262
            $routes->get('expected/uri', FakeControllerWithDependencies::class);
263
            $mappingInterfaces->add(NameInterface::class, new Name('Expected!'));
264
        });
265
    }
266
267
    public function test_inject_controller_with_request_dependency(): void
268
    {
269
        $_SERVER['REQUEST_URI'] = 'https://example.org/expected';
270
        $_SERVER['REQUEST_METHOD'] = 'GET';
271
        $_GET['name'] = 'Katarn';
272
273
        $this->expectOutputString('Katarn');
274
275
        Router::configure(static function (Routes $routes): void {
276
            $routes->get('expected', FakeControllerWithRequest::class);
277
        });
278
    }
279
}
280