Completed
Push — master ( 337ea5...293404 )
by Harry
03:06
created

TrailingSlashControllerProviderTest::testLogging()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 25
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 25
rs 8.8571
cc 1
eloc 18
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 Psr\Log\LoggerInterface;
8
use Silex\Application;
9
use Silex\ControllerProviderInterface;
10
use Silex\ServiceProviderInterface;
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['url_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())
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());
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());
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());
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());
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());
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 is just to show when defining routes with no trailing slash before
269
     * mounting the controller provider they should respond as expected.
270
     *
271
     * @dataProvider requestMethodProvider
272
     *
273
     * @param string $method
274
     */
275 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...
276
    {
277
        $app = new Application();
278
279
        $app->match('/foo', function () {
280
            return 'hunter42';
281
        })->method($method);
282
283
        $app->match('/foo/bar', function () {
284
            return 'hunter42';
285
        })->method($method);
286
287
        $app->register(new TrailingSlashControllerProvider());
288
        $app->mount('/', new TrailingSlashControllerProvider());
289
290
        $request = Request::create('/foo', $method);
291
        $response = $app->handle($request);
292
293
        $this->assertEquals(200, $response->getStatusCode());
294
295
        $request = Request::create('/foo/bar', $method);
296
        $response = $app->handle($request);
297
298
        $this->assertEquals(200, $response->getStatusCode());
299
    }
300
301
    /**
302
     * Test the case in which a request should have both query
303
     * string params and body params
304
     */
305
    public function testWillHandleQueryAndBodySeparately()
306
    {
307
        $app = new Application();
308
309
        $app->match('/foo/', function (Request $request) {
310
            $response = [
311
                'query' => $request->query->all(),
312
                'request' => $request->request->all()
313
            ];
314
            return json_encode($response, true);
315
        })->method('POST');
316
317
        $app->register(new TrailingSlashControllerProvider());
318
        $app->mount('/', new TrailingSlashControllerProvider());
319
320
        $request = Request::create('/foo?q=1', 'POST', ['r' => 2]);
321
        $response = $app->handle($request);
322
        $this->assertEquals(200, $response->getStatusCode());
323
        $body = json_decode($response->getContent(), true);
324
        $this->assertRequestQuery($body);
325
326
        $request = Request::create('/foo/?q=1', 'POST', ['r' => 2]);
327
        $response = $app->handle($request);
328
        $this->assertEquals(200, $response->getStatusCode());
329
        $body = json_decode($response->getContent(), true);
330
        $this->assertRequestQuery($body);
331
    }
332
333
    /**
334
     * @param array $body
335
     */
336
    private function assertRequestQuery(array $body)
337
    {
338
        $this->assertArrayHasKey('query', $body);
339
        $this->assertArrayHasKey('request', $body);
340
341
        $this->assertArrayHasKey('q', $body['query']);
342
        $this->assertEquals(1, $body['query']['q']);
343
344
        $this->assertArrayHasKey('r', $body['request']);
345
        $this->assertEquals(2, $body['request']['r']);
346
    }
347
348
    public function testLogging()
349
    {
350
        $app = new Application();
351
352
        $logger = Mockery::mock(LoggerInterface::class)->makePartial()->shouldIgnoreMissing();
353
        $app['logger'] = $logger;
354
355
        $app->match('/foo/', function () {
356
            return 'hunter42';
357
        })->method('GET');
358
359
        $logger->shouldReceive('debug')
360
               ->with('Appending a trailing slash for the request to `/foo`.')
361
               ->once();
362
        $logger->shouldReceive('debug')
363
               ->with('Overriding the default Silex url matcher to Symfony\Component\Routing\Matcher\UrlMatcher.')
364
               ->once();
365
366
        $app->register(new TrailingSlashControllerProvider());
367
        $app->mount('/', new TrailingSlashControllerProvider());
368
369
        $request = Request::create('/foo', 'GET');
370
        $response = $app->handle($request);
371
        $this->assertEquals(200, $response->getStatusCode());
372
    }
373
}
374