Completed
Pull Request — master (#178)
by ignace nyamagana
03:19
created

UriTemplateTest::templateExpansionProvider()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 122

Duplication

Lines 9
Ratio 7.38 %

Importance

Changes 0
Metric Value
dl 9
loc 122
rs 8
c 0
b 0
f 0
cc 3
nc 3
nop 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * League.Uri (https://uri.thephpleague.com)
5
 *
6
 * (c) Ignace Nyamagana Butera <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace LeagueTest\Uri;
15
16
use League\Uri\Exceptions\SyntaxError;
17
use League\Uri\Exceptions\TemplateCanNotBeExpanded;
18
use League\Uri\UriTemplate;
19
use PHPUnit\Framework\TestCase;
20
21
/**
22
 * @coversDefaultClass \League\Uri\UriTemplate
23
 */
24
final class UriTemplateTest extends TestCase
25
{
26
    /**
27
     * @covers ::__construct
28
     * @covers ::getTemplate
29
     */
30
    public function testGetTemplate(): void
31
    {
32
        $template = 'http://example.com{+path}{/segments}{?query,more*,foo[]*}';
33
        $variables = [
34
            'path'     => '/foo/bar',
35
            'segments' => ['one', 'two'],
36
            'query'    => 'test',
37
            'more'     => ['fun', 'ice cream'],
38
            'foo[]' => ['fizz', 'buzz'],
39
        ];
40
41
        $uriTemplate = new UriTemplate($template, $variables);
42
43
        self::assertSame($template, $uriTemplate->getTemplate());
44
    }
45
46
    /**
47
     * @covers ::__construct
48
     * @covers ::filterVariables
49
     * @covers ::getDefaultVariables
50
     */
51
    public function testGetDefaultVariables(): void
52
    {
53
        $template = 'http://example.com{+path}{/segments}{?query,more*,foo[]*}';
54
        $variables = [
55
            'path'     => '/foo/bar',
56
            'segments' => ['one', 'two', 3, true, 'false', false, null],
57
            'query'    => 'test',
58
            'more'     => ['fun', 'ice cream'],
59
            'foo[]' => ['fizz', 'buzz'],
60
            'nonexistent' => ['random'],
61
        ];
62
63
        $expectedVariables = [
64
            'path'     => '/foo/bar',
65
            'segments' => ['one', 'two', '3', '1', 'false', '0', ''],
66
            'query'    => 'test',
67
            'more'     => ['fun', 'ice cream'],
68
            'foo[]' => ['fizz', 'buzz'],
69
        ];
70
71
        $uriTemplate = new UriTemplate($template, $variables);
72
        self::assertSame($expectedVariables, $uriTemplate->getDefaultVariables());
73
74
        $uriTemplateEmpty = new UriTemplate($template, []);
75
        self::assertSame([], $uriTemplateEmpty->getDefaultVariables());
76
    }
77
78
    /**
79
     * @covers ::filterVariables
80
     * @covers ::withDefaultVariables
81
     */
82
    public function testWithDefaultVariables(): void
83
    {
84
        $template = '{foo}{bar}';
85
        $variables = ['foo' => 'foo', 'bar' => 'bar'];
86
        $newVariables = ['foo' => 'bar', 'bar' => 'foo'];
87
        $newAltVariables = ['foo' => 'foo', 'bar' => 'bar', 'filteredVariable' => 'random'];
88
89
        $uriTemplate = new UriTemplate($template, $variables);
90
        $newTemplate = $uriTemplate->withDefaultVariables($newVariables);
91
        $altTemplate = $uriTemplate->withDefaultVariables($variables);
92
        $newAltTemplate = $uriTemplate->withDefaultVariables($newAltVariables);
93
94
        self::assertSame($altTemplate->getDefaultVariables(), $uriTemplate->getDefaultVariables());
95
        self::assertSame($newAltTemplate->getDefaultVariables(), $uriTemplate->getDefaultVariables());
96
        self::assertNotSame($newTemplate->getDefaultVariables(), $uriTemplate->getDefaultVariables());
97
    }
98
99
    /**
100
     * @covers ::__set_state
101
     */
102
    public function testSetState(): void
103
    {
104
        $template = '{foo}{bar}';
105
        $variables = ['foo' => 'foo', 'bar' => 'bar'];
106
107
        $uriTemplate = new UriTemplate($template, $variables);
108
109
        self::assertEquals($uriTemplate, eval('return '.var_export($uriTemplate, true).';'));
110
    }
111
112
    /**
113
     * @covers ::getVariableNames
114
     *
115
     * @dataProvider expectedVariableNames
116
     */
117
    public function testGetVariableNames(string $template, array $expected): void
118
    {
119
        self::assertSame($expected, (new UriTemplate($template))->getVariableNames());
120
    }
121
122 View Code Duplication
    public function expectedVariableNames(): iterable
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...
123
    {
124
        return [
125
            [
126
                'template' => '',
127
                'expected' => [],
128
            ],
129
            [
130
                'template' => '{foo}{bar}',
131
                'expected' => ['foo', 'bar'],
132
            ],
133
            [
134
                'template' => '{foo}{foo:2}{+foo}',
135
                'expected' => ['foo'],
136
            ],
137
            [
138
                'template' => '{bar}{foo}',
139
                'expected' => ['bar', 'foo'],
140
            ],
141
        ];
142
    }
143
144
    /**
145
     * @covers ::expand
146
     *
147
     * @dataProvider templateExpansionProvider
148
     */
149
    public function testExpandsUriTemplates(string $template, string $expectedUriString, array $variables): void
150
    {
151
        self::assertSame($expectedUriString, (new UriTemplate($template))->expand($variables)->__toString());
152
    }
153
154
    public function templateExpansionProvider(): iterable
155
    {
156
        $variables = [
157
            'var'   => 'value',
158
            'hello' => 'Hello World!',
159
            'empty' => '',
160
            'path'  => '/foo/bar',
161
            'x'     => '1024',
162
            'y'     => '768',
163
            'null'  => null,
164
            'list'  => ['red', 'green', 'blue'],
165
            'keys'  => [
166
                'semi'  => ';',
167
                'dot'   => '.',
168
                'comma' => ',',
169
            ],
170
            'empty_keys' => [],
171
            'bool' => true,
172
        ];
173
174
        $templateAndExpansionData = [
175
            'level 1' => [
176
                ['foo',                 'foo'],
177
                ['{var}',               'value'],
178
                ['{hello}',             'Hello%20World%21'],
179
                ['{bool}',              '1'],
180
            ],
181
            'level 2' => [
182
                ['{+var}',              'value'],
183
                ['{+hello}',            'Hello%20World!'],
184
                ['{+path}/here',        '/foo/bar/here'],
185
                ['here?ref={+path}',    'here?ref=/foo/bar'],
186
            ],
187
            'level 3' => [
188
                ['X{#var}',             'X#value'],
189
                ['X{#hello}',           'X#Hello%20World!'],
190
                ['map?{x,y}',           'map?1024,768'],
191
                ['{x,hello,y}',         '1024,Hello%20World%21,768'],
192
                ['{+x,hello,y}',        '1024,Hello%20World!,768'],
193
                ['{+path,x}/here',      '/foo/bar,1024/here'],
194
                ['{#x,hello,y}',        '#1024,Hello%20World!,768'],
195
                ['{#path,x}/here',      '#/foo/bar,1024/here'],
196
                ['X{.var}',             'X.value'],
197
                ['X{.x,y}',             'X.1024.768'],
198
                ['{/var}',              '/value'],
199
                ['{/var,x}/here',       '/value/1024/here'],
200
                ['{;x,y}',              ';x=1024;y=768'],
201
                ['{;x,y,empty}',        ';x=1024;y=768;empty'],
202
                ['{?x,y}',              '?x=1024&y=768'],
203
                ['{?x,y,empty}',        '?x=1024&y=768&empty='],
204
                ['{?x,y,undef}',        '?x=1024&y=768'],
205
                ['?fixed=yes{&x}',      '?fixed=yes&x=1024'],
206
                ['{&x,y,empty}',        '&x=1024&y=768&empty='],
207
            ],
208
            'level 4' => [
209
                ['{var:3}',             'val'],
210
                ['{var:30}',            'value'],
211
                ['{list}',              'red,green,blue'],
212
                ['{list*}',             'red,green,blue'],
213
                ['{keys}',              'semi,%3B,dot,.,comma,%2C'],
214
                ['{keys*}',             'semi=%3B,dot=.,comma=%2C'],
215
                ['{+path:6}/here',      '/foo/b/here'],
216
                ['{+list}',             'red,green,blue'],
217
                ['{+list*}',            'red,green,blue'],
218
                ['{+keys}',             'semi,;,dot,.,comma,,'],
219
                ['{+keys*}',            'semi=;,dot=.,comma=,'],
220
                ['{#path:6}/here',      '#/foo/b/here'],
221
                ['{#list}',             '#red,green,blue'],
222
                ['{#list*}',            '#red,green,blue'],
223
                ['{#keys}',             '#semi,;,dot,.,comma,,'],
224
                ['{#keys*}',            '#semi=;,dot=.,comma=,'],
225
                ['X{.var:3}',           'X.val'],
226
                ['X{.list}',            'X.red,green,blue'],
227
                ['X{.list*}',           'X.red.green.blue'],
228
                ['X{.keys}',            'X.semi,%3B,dot,.,comma,%2C'],
229
                ['X{.keys*}',           'X.semi=%3B.dot=..comma=%2C'],
230
                ['{/var:1,var}',        '/v/value'],
231
                ['{/list}',             '/red,green,blue'],
232
                ['{/list*}',            '/red/green/blue'],
233
                ['{/list*,path:4}',     '/red/green/blue/%2Ffoo'],
234
                ['{/keys}',             '/semi,%3B,dot,.,comma,%2C'],
235
                ['{/keys*}',            '/semi=%3B/dot=./comma=%2C'],
236
                ['{;hello:5}',          ';hello=Hello'],
237
                ['{;list}',             ';list=red,green,blue'],
238
                ['{;list*}',            ';list=red;list=green;list=blue'],
239
                ['{;keys}',             ';keys=semi,%3B,dot,.,comma,%2C'],
240
                ['{;keys*}',            ';semi=%3B;dot=.;comma=%2C'],
241
                ['{?var:3}',            '?var=val'],
242
                ['{?list}',             '?list=red,green,blue'],
243
                ['{?list*}',            '?list=red&list=green&list=blue'],
244
                ['{?keys}',             '?keys=semi,%3B,dot,.,comma,%2C'],
245
                ['{?keys*}',            '?semi=%3B&dot=.&comma=%2C'],
246
                ['{&var:3}',            '&var=val'],
247
                ['{&list}',             '&list=red,green,blue'],
248
                ['{&list*}',            '&list=red&list=green&list=blue'],
249
                ['{&keys}',             '&keys=semi,%3B,dot,.,comma,%2C'],
250
                ['{&keys*}',            '&semi=%3B&dot=.&comma=%2C'],
251
                ['{.null}',            ''],
252
                ['{.null,var}',        '.value'],
253
                ['X{.empty_keys*}',     'X'],
254
                ['X{.empty_keys}',      'X'],
255
            ],
256
            'extra' => [
257
                // Test that missing expansions are skipped
258
                ['test{&missing*}',     'test'],
259
                // Test that multiple expansions can be set
260
                ['http://{var}/{var:2}{?keys*}', 'http://value/va?semi=%3B&dot=.&comma=%2C'],
261
                // Test more complex query string stuff
262
                ['http://www.test.com{+path}{?var,keys*}', 'http://www.test.com/foo/bar?var=value&semi=%3B&dot=.&comma=%2C'],
263
            ],
264
        ];
265
266 View Code Duplication
        foreach ($templateAndExpansionData as $specification => $tests) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
267
            foreach ($tests as $offset => $test) {
268
                yield $specification.' test '.$offset => [
269
                    'template' => $test[0],
270
                    'expectedUriString' => $test[1],
271
                    'variables' => $variables,
272
                ];
273
            }
274
        }
275
    }
276
277
    public function testAllowsQueryValuePairsArrayExpansion(): void
278
    {
279
        $template = 'http://example.com{+path}{/segments}{?query,more*,foo[]*}';
280
        $variables = [
281
            'path'     => '/foo/bar',
282
            'segments' => ['one', 'two'],
283
            'query'    => 'test',
284
            'more'     => ['fun', 'ice cream'],
285
            'foo[]' => ['fizz', 'buzz'],
286
        ];
287
288
        self::assertSame(
289
            'http://example.com/foo/bar/one,two?query=test&more=fun&more=ice%20cream&foo%5B%5D=fizz&foo%5B%5D=buzz',
290
            (new UriTemplate($template))->expand($variables)->__toString()
291
        );
292
    }
293
294
    /**
295
     * @covers \League\Uri\Exceptions\TemplateCanNotBeExpanded
296
     * @covers \League\Uri\UriTemplate\Template
297
     */
298
    public function testDisallowNestedArrayExpansion(): void
299
    {
300
        $template = 'http://example.com{?query,data*,foo*}';
301
        $variables = [
302
            'query'    => 'test',
303
            'data'     => [
304
                'more' => ['fun', 'ice cream'],
305
            ],
306
            'foo' => [
307
                'baz' => [
308
                    'bar'  => 'fizz',
309
                    'test' => 'buzz',
310
                ],
311
                'bam' => 'boo',
312
            ],
313
        ];
314
315
        self::expectException(TemplateCanNotBeExpanded::class);
316
317
        (new UriTemplate($template))->expand($variables);
318
    }
319
320
    /**
321
     * @covers ::expand
322
     * @covers ::filterVariables
323
     * @covers \League\Uri\UriTemplate\Template
324
     */
325 View Code Duplication
    public function testExpandWithDefaultVariables(): void
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...
326
    {
327
        $template = 'http://example.com{+path}{/segments}{?query,more*,foo[]*}';
328
329
        $defaultVariables = [
330
            'path' => '/foo/bar',
331
            'segments' => ['one', 'two'],
332
        ];
333
334
        $variables = [
335
            'query' => 'test',
336
            'more' => ['fun', 'ice cream'],
337
            'foo[]' => ['fizz', 'buzz'],
338
        ];
339
340
        self::assertSame(
341
            'http://example.com/foo/bar/one,two?query=test&more=fun&more=ice%20cream&foo%5B%5D=fizz&foo%5B%5D=buzz',
342
            (new UriTemplate($template, $defaultVariables))->expand($variables)->__toString()
343
        );
344
    }
345
346
    /**
347
     * @covers ::expand
348
     * @covers ::filterVariables
349
     * @covers \League\Uri\UriTemplate\Template
350
     */
351 View Code Duplication
    public function testExpandWithDefaultVariablesWithOverride(): void
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...
352
    {
353
        $template = 'http://example.com{+path}{/segments}{?query,more*,foo[]*}';
354
355
        $defaultVariables = [
356
            'path'     => '/foo/bar',
357
            'segments' => ['one', 'two'],
358
        ];
359
360
        $variables = [
361
            'path' => '/bar/baz',
362
            'query'    => 'test',
363
            'more'     => ['fun', 'ice cream'],
364
            'foo[]' => ['fizz', 'buzz'],
365
        ];
366
367
        self::assertSame(
368
            'http://example.com/bar/baz/one,two?query=test&more=fun&more=ice%20cream&foo%5B%5D=fizz&foo%5B%5D=buzz',
369
            (new UriTemplate($template, $defaultVariables))->expand($variables)->__toString()
370
        );
371
    }
372
373
    /**
374
     * @covers \League\Uri\UriTemplate\Template
375
     *
376
     * @dataProvider provideInvalidTemplate
377
     */
378
    public function testInvalidUriTemplate(string $template): void
379
    {
380
        self::expectException(SyntaxError::class);
381
382
        new UriTemplate($template);
383
    }
384
385
    /**
386
     * @see https://github.com/uri-templates/uritemplate-test/blob/master/negative-tests.json
387
     */
388
    public function provideInvalidTemplate(): iterable
389
    {
390
        return [
391
            'mismatch in at least one expression (1)' => ['http://example.com/}/{+foo}'],
392
            'mismatch in at least one expression (2)' => ['http://example.com/{/{+foo}'],
393
        ];
394
    }
395
396
    /**
397
     * @covers \League\Uri\UriTemplate\Template
398
     */
399
    public function testExpansionWithMultipleSameExpression(): void
400
    {
401
        $template = '{foo}/{foo}';
402
        $data = ['foo' => 'foo'];
403
404
        self::assertSame('foo/foo', (new UriTemplate($template, $data))->expand()->__toString());
405
    }
406
}
407