Completed
Push — master ( 293404...dec55c )
by Harry
02:41
created

testShouldRespondOkToHeadWithoutTrailingSlash()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 34
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 34
rs 8.8571
cc 1
eloc 19
nc 1
nop 0
1
<?php
2
3
namespace Graze\Silex\Tests\ControllerProvider;
4
5
use Graze\Silex\ControllerProvider\TrailingSlashControllerProvider;
6
use Mockery;
7
use Pimple\ServiceProviderInterface;
8
use Psr\Log\LoggerInterface;
9
use Silex\Application;
10
use Silex\Api\ControllerProviderInterface;
11
use Symfony\Component\HttpFoundation\Request;
12
use Symfony\Component\Routing\Matcher\UrlMatcher;
13
14
/**
15
 * TrailingSlashControllerProvider test cases.
16
 */
17
class TrailingSlashControllerProviderTest extends \PHPUnit_Framework_TestCase
18
{
19
    public function testShouldInitalize()
20
    {
21
        $provider = new TrailingSlashControllerProvider();
22
23
        $this->assertInstanceOf(ControllerProviderInterface::class, $provider);
24
        $this->assertInstanceOf(ServiceProviderInterface::class, $provider);
25
    }
26
27
    public function testShouldRegisterUrlMatcher()
28
    {
29
        $app = new Application();
30
31
        $app->register(new TrailingSlashControllerProvider());
32
33
        $this->assertInstanceOf(UrlMatcher::class, $app['request_matcher']);
34
    }
35
36
    public function testShouldMount()
37
    {
38
        $app = new Application();
39
40
        // `mount` should return the application.
41
        $this->assertSame(
42
            $app,
43
            $app->mount('/', new TrailingSlashControllerProvider())
0 ignored issues
show
Documentation introduced by
new \Graze\Silex\Control...ashControllerProvider() is of type object<Graze\Silex\Contr...lashControllerProvider>, but the function expects a callable.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
44
        );
45
    }
46
47
    /**
48
     * @dataProvider requestMethodProvider
49
     *
50
     * @param string $method
51
     */
52 View Code Duplication
    public function testShouldRespondOkWithoutTrailingSlash($method)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
53
    {
54
        $app = new Application();
55
56
        $app->match('/foo/', function () {
57
            return 'hunter42';
58
        })->method($method);
59
60
        $app->match('/foo/bar/', function () {
61
            return 'What\'s the question?';
62
        })->method($method);
63
64
        $app->match('/foo/bar/baz/', function () {
65
            return 'Fizz Buzz';
66
        })->method($method);
67
68
        $app->register(new TrailingSlashControllerProvider());
69
        $app->mount('/', new TrailingSlashControllerProvider());
0 ignored issues
show
Documentation introduced by
new \Graze\Silex\Control...ashControllerProvider() is of type object<Graze\Silex\Contr...lashControllerProvider>, but the function expects a callable.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
70
71
        $request = Request::create('/foo', $method);
72
        $response = $app->handle($request);
73
74
        $this->assertEquals(200, $response->getStatusCode());
75
76
        $request = Request::create('/foo/bar', $method);
77
        $response = $app->handle($request);
78
79
        $this->assertEquals(200, $response->getStatusCode());
80
81
        $request = Request::create('/foo/bar/baz', $method);
82
        $response = $app->handle($request);
83
84
        $this->assertEquals(200, $response->getStatusCode());
85
    }
86
87
    /**
88
     * This just shows that the mount order for the controller provider doesn't
89
     * matter when all routes are defined with a trailing slash.
90
     *
91
     * @dataProvider requestMethodProvider
92
     *
93
     * @param string $method
94
     */
95 View Code Duplication
    public function testShouldRespondOkWithoutTrailingSlashWhenMountedFirst($method)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
96
    {
97
        $app = new Application();
98
99
        $app->register(new TrailingSlashControllerProvider());
100
        $app->mount('/', new TrailingSlashControllerProvider());
0 ignored issues
show
Documentation introduced by
new \Graze\Silex\Control...ashControllerProvider() is of type object<Graze\Silex\Contr...lashControllerProvider>, but the function expects a callable.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
101
102
        $app->match('/foo/', function () {
103
            return 'hunter42';
104
        })->method($method);
105
106
        $app->match('/foo/bar/', function () {
107
            return 'What\'s the question?';
108
        })->method($method);
109
110
        $app->match('/foo/bar/baz/', function () {
111
            return 'Fizz Buzz';
112
        })->method($method);
113
114
        $request = Request::create('/foo', $method);
115
        $response = $app->handle($request);
116
117
        $this->assertEquals(200, $response->getStatusCode());
118
119
        $request = Request::create('/foo/bar', $method);
120
        $response = $app->handle($request);
121
122
        $this->assertEquals(200, $response->getStatusCode());
123
124
        $request = Request::create('/foo/bar/baz', $method);
125
        $response = $app->handle($request);
126
127
        $this->assertEquals(200, $response->getStatusCode());
128
    }
129
130
    /**
131
     * This just shows that the controller provider is compatiable with other
132
     * controller providers.
133
     *
134
     * @dataProvider requestMethodProvider
135
     *
136
     * @param string $method
137
     */
138
    public function testShouldRespondOkWithoutTrailingSlashWithMountedControllers($method)
139
    {
140
        $app = new Application();
141
142
        $app->register(new TrailingSlashControllerProvider());
143
        $app->mount('/', new TrailingSlashControllerProvider());
0 ignored issues
show
Documentation introduced by
new \Graze\Silex\Control...ashControllerProvider() is of type object<Graze\Silex\Contr...lashControllerProvider>, but the function expects a callable.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
144
145
        $controller = $app['controllers_factory'];
146
147
        $controller->match('/foo/', function () {
148
            return 'hunter42';
149
        })->method($method);
150
151
        $controller->match('/foo/bar/', function () {
152
            return 'hunter42';
153
        })->method($method);
154
155
        $controller->match('/foo/bar/baz/', function () {
156
            return 'hunter42';
157
        })->method($method);
158
159
        $provider = Mockery::mock(ControllerProviderInterface::class);
160
        $provider->shouldReceive('connect')->andReturn($controller);
161
162
        $app->mount('/', $provider);
163
164
        $request = Request::create('/foo', $method);
165
        $response = $app->handle($request);
166
167
        $this->assertEquals(200, $response->getStatusCode());
168
169
        $request = Request::create('/foo/bar', $method);
170
        $response = $app->handle($request);
171
172
        $this->assertEquals(200, $response->getStatusCode());
173
174
        $request = Request::create('/foo/bar/baz', $method);
175
        $response = $app->handle($request);
176
177
        $this->assertEquals(200, $response->getStatusCode());
178
    }
179
180
    /**
181
     * @return array
182
     */
183
    public function requestMethodProvider()
184
    {
185
        return [
186
            ['GET'],
187
            ['POST'],
188
            ['PUT'],
189
            ['PATCH'],
190
            ['DELETE'],
191
            ['PURGE'],
192
            ['OPTIONS'],
193
            ['TRACE'],
194
            ['CONNECT'],
195
        ];
196
    }
197
198
    public function testShouldRespondOkToHeadWithoutTrailingSlash()
199
    {
200
        $app = new Application();
201
202
        $app->get('/foo/', function () {
203
            return 'hunter42';
204
        });
205
206
        $app->get('/foo/bar/', function () {
207
            return 'What\'s the question?';
208
        });
209
210
        $app->get('/foo/bar/baz/', function () {
211
            return 'Fizz Buzz';
212
        });
213
214
        $app->register(new TrailingSlashControllerProvider());
215
        $app->mount('/', new TrailingSlashControllerProvider());
0 ignored issues
show
Documentation introduced by
new \Graze\Silex\Control...ashControllerProvider() is of type object<Graze\Silex\Contr...lashControllerProvider>, but the function expects a callable.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
216
217
        $request = Request::create('/foo', 'HEAD');
218
        $response = $app->handle($request);
219
220
        $this->assertEquals(200, $response->getStatusCode());
221
222
        $request = Request::create('/foo/bar', 'HEAD');
223
        $response = $app->handle($request);
224
225
        $this->assertEquals(200, $response->getStatusCode());
226
227
        $request = Request::create('/foo/bar/baz', 'HEAD');
228
        $response = $app->handle($request);
229
230
        $this->assertEquals(200, $response->getStatusCode());
231
    }
232
233
    /**
234
     * This is just to show when defining routes that the trailing slash is
235
     * required when the controller provider is mounted before any other routes.
236
     *
237
     * @dataProvider requestMethodProvider
238
     *
239
     * @param string $method
240
     */
241 View Code Duplication
    public function testWillRespondWithNotFoundForRouteWithNoTrailingSlashWhenMountedFirst($method)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
242
    {
243
        $app = new Application();
244
245
        $app->register(new TrailingSlashControllerProvider());
246
        $app->mount('/', new TrailingSlashControllerProvider());
0 ignored issues
show
Documentation introduced by
new \Graze\Silex\Control...ashControllerProvider() is of type object<Graze\Silex\Contr...lashControllerProvider>, but the function expects a callable.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
247
248
        $app->match('/foo', function () {
249
            return 'hunter42';
250
        })->method($method);
251
252
        $app->match('/foo/bar', function () {
253
            return 'hunter42';
254
        })->method($method);
255
256
        $request = Request::create('/foo', $method);
257
        $response = $app->handle($request);
258
259
        $this->assertEquals(404, $response->getStatusCode());
260
261
        $request = Request::create('/foo/bar', $method);
262
        $response = $app->handle($request);
263
264
        $this->assertEquals(404, $response->getStatusCode());
265
    }
266
267
    /**
268
     * This shows that by default it will return 404 when the routes are defined with trailing slashes
269
     *
270
     * @dataProvider requestMethodProvider
271
     *
272
     * @param string $method
273
     */
274 View Code Duplication
    public function testWillRespondWillNotFoundForRouteWithTrailingSlashWhenNotMounted($method)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
275
    {
276
        $app = new Application();
277
278
        $app->match('/foo/', function () {
279
            return 'hunter42';
280
        })->method($method);
281
282
        $app->match('/foo/bar/', function () {
283
            return 'hunter42';
284
        })->method($method);
285
286
        $app->register(new TrailingSlashControllerProvider());
287
288
        $request = Request::create('/foo', $method);
289
        $response = $app->handle($request);
290
291
        $this->assertEquals(404, $response->getStatusCode());
292
293
        $request = Request::create('/foo/bar', $method);
294
        $response = $app->handle($request);
295
296
        $this->assertEquals(404, $response->getStatusCode());
297
    }
298
299
    /**
300
     * This is just to show when defining routes with no trailing slash before
301
     * mounting the controller provider they should respond as expected.
302
     *
303
     * @dataProvider requestMethodProvider
304
     *
305
     * @param string $method
306
     */
307 View Code Duplication
    public function testWillRespondWithOkForRouteWithNoTrailingSlashWhenMountedLast($method)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
308
    {
309
        $app = new Application();
310
311
        $app->match('/foo', function () {
312
            return 'hunter42';
313
        })->method($method);
314
315
        $app->match('/foo/bar', function () {
316
            return 'hunter42';
317
        })->method($method);
318
319
        $app->register(new TrailingSlashControllerProvider());
320
        $app->mount('/', new TrailingSlashControllerProvider());
0 ignored issues
show
Documentation introduced by
new \Graze\Silex\Control...ashControllerProvider() is of type object<Graze\Silex\Contr...lashControllerProvider>, but the function expects a callable.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
321
322
        $request = Request::create('/foo', $method);
323
        $response = $app->handle($request);
324
325
        $this->assertEquals(200, $response->getStatusCode());
326
327
        $request = Request::create('/foo/bar', $method);
328
        $response = $app->handle($request);
329
330
        $this->assertEquals(200, $response->getStatusCode());
331
    }
332
333
    /**
334
     * Test the case in which a request should have both query
335
     * string params and body params
336
     */
337
    public function testWillHandleQueryAndBodySeparately()
338
    {
339
        $app = new Application();
340
341
        $app->match('/foo/', function (Request $request) {
342
            $response = [
343
                'query' => $request->query->all(),
344
                'request' => $request->request->all()
345
            ];
346
            return json_encode($response, true);
347
        })->method('POST');
348
349
        $app->register(new TrailingSlashControllerProvider());
350
        $app->mount('/', new TrailingSlashControllerProvider());
0 ignored issues
show
Documentation introduced by
new \Graze\Silex\Control...ashControllerProvider() is of type object<Graze\Silex\Contr...lashControllerProvider>, but the function expects a callable.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
351
352
        $request = Request::create('/foo?q=1', 'POST', ['r' => 2]);
353
        $response = $app->handle($request);
354
        $this->assertEquals(200, $response->getStatusCode());
355
        $body = json_decode($response->getContent(), true);
356
        $this->assertRequestQuery($body);
357
358
        $request = Request::create('/foo/?q=1', 'POST', ['r' => 2]);
359
        $response = $app->handle($request);
360
        $this->assertEquals(200, $response->getStatusCode());
361
        $body = json_decode($response->getContent(), true);
362
        $this->assertRequestQuery($body);
363
    }
364
365
    /**
366
     * @param array $body
367
     */
368
    private function assertRequestQuery(array $body)
369
    {
370
        $this->assertArrayHasKey('query', $body);
371
        $this->assertArrayHasKey('request', $body);
372
373
        $this->assertArrayHasKey('q', $body['query']);
374
        $this->assertEquals(1, $body['query']['q']);
375
376
        $this->assertArrayHasKey('r', $body['request']);
377
        $this->assertEquals(2, $body['request']['r']);
378
    }
379
380
    public function testLogging()
381
    {
382
        $app = new Application();
383
384
        $logger = Mockery::mock(LoggerInterface::class)->makePartial()->shouldIgnoreMissing();
385
        $app['logger'] = $logger;
386
387
        $app->match('/foo/', function () {
388
            return 'hunter42';
389
        })->method('GET');
390
391
        $logger->shouldReceive('debug')
392
               ->with('Appending a trailing slash for the request to `/foo`.')
393
               ->once();
394
        $logger->shouldReceive('debug')
395
               ->with('Overriding the default Silex url matcher to Symfony\Component\Routing\Matcher\UrlMatcher.')
396
               ->once();
397
398
        $app->register(new TrailingSlashControllerProvider());
399
        $app->mount('/', new TrailingSlashControllerProvider());
0 ignored issues
show
Documentation introduced by
new \Graze\Silex\Control...ashControllerProvider() is of type object<Graze\Silex\Contr...lashControllerProvider>, but the function expects a callable.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
400
401
        $request = Request::create('/foo', 'GET');
402
        $response = $app->handle($request);
403
        $this->assertEquals(200, $response->getStatusCode());
404
    }
405
}
406