Passed
Pull Request — main (#4)
by Chema
02:22
created

test_it_should_respond_if_everything_matches()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

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

223
            $routes->/** @scrutinizer ignore-call */ 
224
                     invalidName('', FakeController::class);
Loading history...
224
        });
225
    }
226
227
    /**
228
     * @dataProvider anyHttpMethodProvider
229
     */
230
    public function test_any_http_method(string $httpMethod): void
231
    {
232
        $_SERVER['REQUEST_URI'] = 'https://example.org/expected/uri';
233
        $_SERVER['REQUEST_METHOD'] = $httpMethod;
234
235
        $this->expectOutputString('Expected!');
236
237
        Route::configure(static function (RoutingConfigurator $routes): void {
238
            $routes->any('expected/uri', FakeController::class, 'basicAction');
239
        });
240
    }
241
242
    public function anyHttpMethodProvider(): Generator
243
    {
244
        yield ['METHOD_GET' => Request::METHOD_GET];
245
        yield ['METHOD_CONNECT' => Request::METHOD_CONNECT];
246
        yield ['METHOD_DELETE' => Request::METHOD_DELETE];
247
        yield ['METHOD_HEAD' => Request::METHOD_HEAD];
248
        yield ['METHOD_OPTIONS' => Request::METHOD_OPTIONS];
249
        yield ['METHOD_PATCH' => Request::METHOD_PATCH];
250
        yield ['METHOD_POST' => Request::METHOD_POST];
251
        yield ['METHOD_PUT' => Request::METHOD_PUT];
252
        yield ['METHOD_TRACE' => Request::METHOD_TRACE];
253
    }
254
}
255