Passed
Push — main ( deaffd...dea3f5 )
by Chema
55s queued 13s
created

test_throw_malformed_path_exception_due_static_part_after_optional_argument()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 8
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace GacelaTest\Feature\Router;
6
7
use Gacela\Router\Configure\Routes;
8
use Gacela\Router\Entities\Request;
9
use Gacela\Router\Exceptions\MalformedPathException;
10
use Gacela\Router\Exceptions\UnsupportedHttpMethodException;
11
use Gacela\Router\Router;
12
use GacelaTest\Feature\Router\Fixtures\FakeController;
13
use Generator;
14
use PHPUnit\Framework\TestCase;
15
16
final class RouterMatchTest extends TestCase
17
{
18
    public function test_respond_when_everything_matches(): void
19
    {
20
        $_SERVER['REQUEST_URI'] = 'https://example.org/expected/uri';
21
        $_SERVER['REQUEST_METHOD'] = Request::METHOD_GET;
22
23
        $this->expectOutputString('Expected!');
24
25
        $router = new Router(static function (Routes $routes): void {
26
            $routes->get('expected/uri', FakeController::class, 'basicAction');
27
        });
28
        $router->run();
29
    }
30
31
    public function test_respond_only_the_first_match(): void
32
    {
33
        $_SERVER['REQUEST_URI'] = 'https://example.org/expected/uri';
34
        $_SERVER['REQUEST_METHOD'] = Request::METHOD_GET;
35
36
        $this->expectOutputString('Expected!');
37
38
        $router = new Router(static function (Routes $routes): void {
39
            $routes->get('expected/uri', FakeController::class, 'basicAction');
40
            $routes->get('expected/{param}', FakeController::class, 'stringParamAction');
41
        });
42
        $router->run();
43
    }
44
45
    public function test_optional_argument(): void
46
    {
47
        $_SERVER['REQUEST_URI'] = 'https://example.org/optional';
48
        $_SERVER['REQUEST_METHOD'] = Request::METHOD_GET;
49
50
        $this->expectOutputString('Expected!');
51
52
        $router = new Router(static function (Routes $routes): void {
53
            $routes->get('optional/{param?}', FakeController::class, 'basicAction');
54
        });
55
        $router->run();
56
    }
57
58
    public function test_multiple_optional_argument(): void
59
    {
60
        $_SERVER['REQUEST_URI'] = 'https://example.org/optional';
61
        $_SERVER['REQUEST_METHOD'] = Request::METHOD_GET;
62
63
        $this->expectOutputString('Expected!');
64
65
        $router = new Router(static function (Routes $routes): void {
66
            $routes->get('optional/{param1?}/{param2?}', FakeController::class, 'basicAction');
67
        });
68
        $router->run();
69
    }
70
71
    public function test_multiple_optional_argument_with_only_first_provided(): void
72
    {
73
        $_SERVER['REQUEST_URI'] = 'https://example.org/optional/bob1';
74
        $_SERVER['REQUEST_METHOD'] = Request::METHOD_GET;
75
76
        $this->expectOutputString('Expected!');
77
78
        $router = new Router(static function (Routes $routes): void {
79
            $routes->get('optional/{param1?}/{param2?}', FakeController::class, 'basicAction');
80
        });
81
        $router->run();
82
    }
83
84
    public function test_multiple_optional_argument_with_both_provided(): void
85
    {
86
        $_SERVER['REQUEST_URI'] = 'https://example.org/optional/bob1/bob2';
87
        $_SERVER['REQUEST_METHOD'] = Request::METHOD_GET;
88
89
        $this->expectOutputString('Expected!');
90
91
        $router = new Router(static function (Routes $routes): void {
92
            $routes->get('optional/{param1?}/{param2?}', FakeController::class, 'basicAction');
93
        });
94
        $router->run();
95
    }
96
97
    public function test_throw_malformed_path_exception_due_mandatory_argument_after_optional_argument(): void
98
    {
99
        $this->expectException(MalformedPathException::class);
100
101
        $router = new Router(static function (Routes $routes): void {
102
            $routes->get('uri/{param1?}/{param2}', FakeController::class);
103
        });
104
        $router->run();
105
    }
106
107
    public function test_throw_malformed_path_exception_due_static_part_after_optional_argument(): void
108
    {
109
        $this->expectException(MalformedPathException::class);
110
111
        $router = new Router(static function (Routes $routes): void {
112
            $routes->get('uri/{param1?}/alice', FakeController::class);
113
        });
114
        $router->run();
115
    }
116
117
    public function test_throw_malformed_path_exception_due_route_start_with_slash(): void
118
    {
119
        $this->expectException(MalformedPathException::class);
120
121
        $router = new Router(static function (Routes $routes): void {
122
            $routes->get('/uri', FakeController::class);
123
        });
124
        $router->run();
125
    }
126
127
    public function test_throw_malformed_path_exception_due_route_end_with_slash(): void
128
    {
129
        $this->expectException(MalformedPathException::class);
130
131
        $router = new Router(static function (Routes $routes): void {
132
            $routes->get('uri/', FakeController::class);
133
        });
134
        $router->run();
135
    }
136
137
    public function test_throw_malformed_path_exception_due_empty_part(): void
138
    {
139
        $this->expectException(MalformedPathException::class);
140
141
        $router = new Router(static function (Routes $routes): void {
142
            $routes->get('uri//alice', FakeController::class);
143
        });
144
        $router->run();
145
    }
146
147
    public function test_throw_malformed_path_exception_due_empty_path(): void
148
    {
149
        $this->expectException(MalformedPathException::class);
150
151
        $router = new Router(static function (Routes $routes): void {
152
            $routes->get('', FakeController::class);
153
        });
154
        $router->run();
155
    }
156
157
    public function test_mandatory_argument(): void
158
    {
159
        $_SERVER['REQUEST_URI'] = 'https://example.org/mandatory/alice';
160
        $_SERVER['REQUEST_METHOD'] = Request::METHOD_GET;
161
162
        $this->expectOutputString('Expected!');
163
164
        $router = new Router(static function (Routes $routes): void {
165
            $routes->get('mandatory/{param1}', FakeController::class, 'basicAction');
166
        });
167
        $router->run();
168
    }
169
170
    public function test_mandatory_and_not_provided_optional_argument(): void
171
    {
172
        $_SERVER['REQUEST_URI'] = 'https://example.org/mandatory_and_not_provided_optional/alice';
173
        $_SERVER['REQUEST_METHOD'] = Request::METHOD_GET;
174
175
        $this->expectOutputString('Expected!');
176
177
        $router = new Router(static function (Routes $routes): void {
178
            $routes->get('mandatory_and_not_provided_optional/{param1}/{param2?}', FakeController::class, 'basicAction');
179
        });
180
        $router->run();
181
    }
182
183
    public function test_mandatory_and_provided_optional_argument(): void
184
    {
185
        $_SERVER['REQUEST_URI'] = 'https://example.org/mandatory_and_provided_optional/alice/bob';
186
        $_SERVER['REQUEST_METHOD'] = Request::METHOD_GET;
187
188
        $this->expectOutputString('Expected!');
189
190
        $router = new Router(static function (Routes $routes): void {
191
            $routes->get('mandatory_and_provided_optional/{param1}/{param2?}', FakeController::class, 'basicAction');
192
        });
193
        $router->run();
194
    }
195
196
    public function test_thrown_exception_when_method_does_not_exist(): void
197
    {
198
        $this->expectException(UnsupportedHttpMethodException::class);
199
200
        $router = new Router(static function (Routes $routes): void {
201
            $routes->invalidName('invalid', FakeController::class);
0 ignored issues
show
Bug introduced by
The method invalidName() does not exist on Gacela\Router\Configure\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

201
            $routes->/** @scrutinizer ignore-call */ 
202
                     invalidName('invalid', FakeController::class);
Loading history...
202
        });
203
        $router->run();
204
    }
205
206
    /**
207
     * @dataProvider anyHttpMethodProvider
208
     */
209
    public function test_any_http_method(string $httpMethod): void
210
    {
211
        $_SERVER['REQUEST_URI'] = 'https://example.org/expected/uri';
212
        $_SERVER['REQUEST_METHOD'] = $httpMethod;
213
214
        $this->expectOutputString('Expected!');
215
216
        $router = new Router(static function (Routes $routes): void {
217
            $routes->any('expected/uri', FakeController::class, 'basicAction');
218
        });
219
        $router->run();
220
    }
221
222
    public function anyHttpMethodProvider(): Generator
223
    {
224
        yield ['METHOD_GET' => Request::METHOD_GET];
225
        yield ['METHOD_CONNECT' => Request::METHOD_CONNECT];
226
        yield ['METHOD_DELETE' => Request::METHOD_DELETE];
227
        yield ['METHOD_HEAD' => Request::METHOD_HEAD];
228
        yield ['METHOD_OPTIONS' => Request::METHOD_OPTIONS];
229
        yield ['METHOD_PATCH' => Request::METHOD_PATCH];
230
        yield ['METHOD_POST' => Request::METHOD_POST];
231
        yield ['METHOD_PUT' => Request::METHOD_PUT];
232
        yield ['METHOD_TRACE' => Request::METHOD_TRACE];
233
    }
234
235
    /**
236
     * @dataProvider matchesMethodsProvider
237
     */
238
    public function test_match_matches_all_its_methods(string $testMethod, array $givenMethods): void
239
    {
240
        $_SERVER['REQUEST_URI'] = 'https://example.org/expected/uri';
241
        $_SERVER['REQUEST_METHOD'] = $testMethod;
242
243
        $this->expectOutputString('Expected!');
244
245
        $router = new Router(static function (Routes $routes) use ($givenMethods): void {
246
            $routes->match($givenMethods, 'expected/uri', FakeController::class, 'basicAction');
247
        });
248
        $router->run();
249
    }
250
251
    public function matchesMethodsProvider(): Generator
252
    {
253
        yield [Request::METHOD_GET, [Request::METHOD_GET, Request::METHOD_POST]];
254
        yield [Request::METHOD_POST, [Request::METHOD_GET, Request::METHOD_POST]];
255
        yield [Request::METHOD_PATCH, [Request::METHOD_PATCH, Request::METHOD_PUT]];
256
        yield [Request::METHOD_PUT, [Request::METHOD_PATCH, Request::METHOD_PUT]];
257
    }
258
}
259