Completed
Push — master ( 78a0a4...eabb68 )
by David
02:07 queued 18s
created

testCachePluginConfigCacheListenersDefinition()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 22

Duplication

Lines 22
Ratio 100 %

Importance

Changes 0
Metric Value
dl 22
loc 22
rs 9.568
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Http\HttplugBundle\Tests\Unit\DependencyInjection;
6
7
use Http\Adapter\Guzzle6\Client;
8
use Http\Client\HttpClient;
9
use Http\Client\Plugin\Vcr\Recorder\InMemoryRecorder;
10
use Http\HttplugBundle\Collector\PluginClientFactoryListener;
11
use Http\HttplugBundle\DependencyInjection\HttplugExtension;
12
use Matthias\SymfonyDependencyInjectionTest\PhpUnit\AbstractExtensionTestCase;
13
use Symfony\Component\DependencyInjection\Reference;
14
use Symfony\Component\HttpKernel\Kernel;
15
16
/**
17
 * @author David Buchmann <[email protected]>
18
 * @author Tobias Nyholm <[email protected]>
19
 */
20
class HttplugExtensionTest extends AbstractExtensionTestCase
21
{
22
    protected function setUp(): void
23
    {
24
        parent::setUp();
25
26
        $this->setParameter('kernel.debug', true);
27
    }
28
29
    protected function getContainerExtensions(): array
30
    {
31
        return [
32
            new HttplugExtension(),
33
        ];
34
    }
35
36
    public function testConstants(): void
37
    {
38
        self::assertSame('httplug.client', HttplugExtension::HTTPLUG_CLIENT_TAG);
39
    }
40
41
    public function testConfigLoadDefault(): void
42
    {
43
        $this->load();
44
45 View Code Duplication
        foreach (['client', 'message_factory', 'uri_factory', 'stream_factory'] as $type) {
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...
46
            $this->assertContainerBuilderHasAlias("httplug.$type", "httplug.$type.default");
47
        }
48
    }
49
50
    public function testConfigLoadClass(): void
51
    {
52
        $this->load([
53
            'classes' => [
54
                'client' => Client::class,
55
            ],
56
        ]);
57
58
        $this->assertContainerBuilderHasService('httplug.client.default', Client::class);
59
    }
60
61
    public function testConfigLoadService(): void
62
    {
63
        $this->load([
64
            'main_alias' => [
65
                'client' => 'my_client_service',
66
                'message_factory' => 'my_message_factory_service',
67
                'uri_factory' => 'my_uri_factory_service',
68
                'stream_factory' => 'my_stream_factory_service',
69
            ],
70
        ]);
71
72 View Code Duplication
        foreach (['client', 'message_factory', 'uri_factory', 'stream_factory'] as $type) {
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...
73
            $this->assertContainerBuilderHasAlias("httplug.$type", "my_{$type}_service");
74
        }
75
    }
76
77
    public function testClientPlugins(): void
78
    {
79
        $this->load([
80
            'clients' => [
81
                'acme' => [
82
                    'factory' => 'httplug.factory.curl',
83
                    'plugins' => [
84
                        [
85
                            'decoder' => [
86
                                'use_content_encoding' => false,
87
                            ],
88
                        ],
89
                        'httplug.plugin.redirect',
90
                        [
91
                            'add_host' => [
92
                                'host' => 'http://localhost:8000',
93
                            ],
94
                        ],
95
                        [
96
                            'content_type' => [
97
                                'skip_detection' => true,
98
                            ],
99
                        ],
100
                        [
101
                            'header_append' => [
102
                                'headers' => ['X-FOO' => 'bar'],
103
                            ],
104
                        ],
105
                        [
106
                            'header_defaults' => [
107
                                'headers' => ['X-FOO' => 'bar'],
108
                            ],
109
                        ],
110
                        [
111
                            'header_set' => [
112
                                'headers' => ['X-FOO' => 'bar'],
113
                            ],
114
                        ],
115
                        [
116
                            'header_remove' => [
117
                                'headers' => ['X-FOO'],
118
                            ],
119
                        ],
120
                        [
121
                            'query_defaults' => [
122
                                'parameters' => ['locale' => 'en'],
123
                            ],
124
                        ],
125
                        [
126
                            'authentication' => [
127
                                'my_basic' => [
128
                                    'type' => 'basic',
129
                                    'username' => 'foo',
130
                                    'password' => 'bar',
131
                                ],
132
                            ],
133
                        ],
134
                        [
135
                            'cache' => [
136
                                'cache_pool' => 'my_cache_pool',
137
                            ],
138
                        ],
139
                    ],
140
                ],
141
            ],
142
        ]);
143
144
        $plugins = [
145
            'httplug.client.acme.plugin.decoder',
146
            'httplug.plugin.redirect',
147
            'httplug.client.acme.plugin.add_host',
148
            'httplug.client.acme.plugin.content_type',
149
            'httplug.client.acme.plugin.header_append',
150
            'httplug.client.acme.plugin.header_defaults',
151
            'httplug.client.acme.plugin.header_set',
152
            'httplug.client.acme.plugin.header_remove',
153
            'httplug.client.acme.plugin.query_defaults',
154
            'httplug.client.acme.authentication.my_basic',
155
            'httplug.client.acme.plugin.cache',
156
        ];
157
        $pluginReferences = array_map(function ($id) {
158
            return new Reference($id);
159
        }, $plugins);
160
161
        $this->assertContainerBuilderHasService('httplug.client.acme');
162
        foreach ($plugins as $id) {
163
            $this->assertContainerBuilderHasService($id);
164
        }
165
        $this->assertContainerBuilderHasServiceDefinitionWithArgument('httplug.client.acme', 1, $pluginReferences);
166
        $this->assertContainerBuilderHasService('httplug.client.mock');
167
    }
168
169
    /**
170
     * @group legacy
171
     */
172 View Code Duplication
    public function testNoProfilingWhenToolbarIsDisabled(): 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...
173
    {
174
        $this->load(
175
            [
176
                'toolbar' => [
177
                    'enabled' => false,
178
                ],
179
                'clients' => [
180
                    'acme' => [
181
                        'factory' => 'httplug.factory.curl',
182
                        'plugins' => ['foo'],
183
                    ],
184
                ],
185
            ]
186
        );
187
188
        $this->verifyProfilingDisabled();
189
    }
190
191 View Code Duplication
    public function testNoProfilingWhenNotInDebugMode(): 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...
192
    {
193
        $this->setParameter('kernel.debug', false);
194
        $this->load(
195
            [
196
                'clients' => [
197
                    'acme' => [
198
                        'factory' => 'httplug.factory.curl',
199
                        'plugins' => ['foo'],
200
                    ],
201
                ],
202
            ]
203
        );
204
205
        $this->verifyProfilingDisabled();
206
    }
207
208
    /**
209
     * @group legacy
210
     */
211 View Code Duplication
    public function testProfilingWhenToolbarIsSpecificallyOn(): 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...
212
    {
213
        $this->setParameter('kernel.debug', false);
214
        $this->load(
215
            [
216
                'toolbar' => [
217
                    'enabled' => true,
218
                ],
219
                'clients' => [
220
                    'acme' => [
221
                        'factory' => 'httplug.factory.curl',
222
                        'plugins' => ['foo'],
223
                    ],
224
                ],
225
            ]
226
        );
227
228
        $this->assertContainerBuilderHasService(PluginClientFactoryListener::class);
229
    }
230
231
    public function testOverrideProfilingFormatter(): void
232
    {
233
        $this->load(
234
            [
235
                'profiling' => [
236
                    'formatter' => 'acme.formatter',
237
                ],
238
            ]
239
        );
240
241
        $def = $this->container->findDefinition('httplug.collector.formatter');
242
        $this->assertEquals('acme.formatter', (string) $def->getArgument(0));
243
    }
244
245 View Code Duplication
    public function testCachePluginConfigCacheKeyGeneratorReference(): 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...
246
    {
247
        $this->load([
248
            'plugins' => [
249
                'cache' => [
250
                    'cache_pool' => 'my_cache_pool',
251
                    'config' => [
252
                        'cache_key_generator' => 'header_cache_key_generator',
253
                    ],
254
                ],
255
            ],
256
        ]);
257
258
        $cachePlugin = $this->container->findDefinition('httplug.plugin.cache');
259
260
        $config = $cachePlugin->getArgument(2);
261
        $this->assertArrayHasKey('cache_key_generator', $config);
262
        $this->assertInstanceOf(Reference::class, $config['cache_key_generator']);
263
        $this->assertSame('header_cache_key_generator', (string) $config['cache_key_generator']);
264
    }
265
266 View Code Duplication
    public function testCachePluginConfigCacheListenersDefinition(): 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...
267
    {
268
        $this->load([
269
            'plugins' => [
270
                'cache' => [
271
                    'cache_pool' => 'my_cache_pool',
272
                    'config' => [
273
                        'cache_listeners' => [
274
                            'httplug.plugin.cache.listeners.add_header',
275
                        ],
276
                    ],
277
                ],
278
            ],
279
        ]);
280
281
        $cachePlugin = $this->container->findDefinition('httplug.plugin.cache');
282
283
        $config = $cachePlugin->getArgument(2);
284
        $this->assertArrayHasKey('cache_listeners', $config);
285
        $this->assertContainsOnlyInstancesOf(Reference::class, $config['cache_listeners']);
286
        $this->assertSame('httplug.plugin.cache.listeners.add_header', (string) $config['cache_listeners'][0]);
287
    }
288
289
    public function testContentTypePluginAllowedOptions(): void
290
    {
291
        $this->load([
292
            'clients' => [
293
                'acme' => [
294
                    'plugins' => [
295
                        [
296
                            'content_type' => [
297
                                'skip_detection' => true,
298
                                'size_limit' => 200000,
299
                            ],
300
                        ],
301
                    ],
302
                ],
303
            ],
304
        ]);
305
306
        $cachePlugin = $this->container->findDefinition('httplug.client.acme.plugin.content_type');
307
308
        $config = $cachePlugin->getArgument(0);
309
        $this->assertEquals([
310
            'skip_detection' => true,
311
            'size_limit' => 200000,
312
        ], $config);
313
    }
314
315
    public function testUsingServiceKeyForClients(): void
316
    {
317
        $this->load([
318
            'clients' => [
319
                'acme' => [
320
                    'service' => 'my_custom_client',
321
                ],
322
            ],
323
        ]);
324
325
        $client = $this->container->getAlias('httplug.client.acme.client');
326
        $this->assertEquals('my_custom_client', (string) $client);
327
        $this->assertFalse($client->isPublic());
328
    }
329
330
    private function verifyProfilingDisabled(): void
331
    {
332
        $def = $this->container->findDefinition('httplug.client');
333
        $this->assertTrue(is_subclass_of($def->getClass(), HttpClient::class));
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of might return inconsistent results on some PHP versions if \Http\Client\HttpClient::class can be an interface. If so, you could instead use ReflectionClass::implementsInterface.
Loading history...
334
        $arguments = $def->getArguments();
335
336
        if (isset($arguments[3])) {
337
            $this->assertEmpty(
338
                $arguments[3],
339
                'Parameter 3 to the PluginClient must not contain any debug_plugin information when profiling is disabled'
340
            );
341
        }
342
    }
343
344
    public function testClientShouldHaveDefaultVisibility(): void
345
    {
346
        $this->load([
347
            'clients' => [
348
                'acme' => [],
349
            ],
350
        ]);
351
352
        $this->assertContainerBuilderHasService('httplug.client.acme');
353
354
        if (version_compare(Kernel::VERSION, '3.4', '>=')) {
355
            // Symfony made services private by default starting from 3.4
356
            $this->assertTrue($this->container->getDefinition('httplug.client.acme')->isPublic());
357
            $this->assertTrue($this->container->getDefinition('httplug.client.acme')->isPrivate());
358
        } else {
359
            // Legacy Symfony
360
            $this->assertTrue($this->container->getDefinition('httplug.client.acme')->isPublic());
361
        }
362
    }
363
364 View Code Duplication
    public function testFlexibleClientShouldBePrivateByDefault(): 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...
365
    {
366
        $this->load([
367
            'clients' => [
368
                'acme' => [
369
                    'flexible_client' => true,
370
                ],
371
            ],
372
        ]);
373
374
        $this->assertContainerBuilderHasService('httplug.client.acme');
375
        $this->assertFalse($this->container->getDefinition('httplug.client.acme.flexible')->isPublic());
376
    }
377
378 View Code Duplication
    public function testHttpMethodsClientShouldBePrivateByDefault(): 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...
379
    {
380
        $this->load([
381
            'clients' => [
382
                'acme' => [
383
                    'http_methods_client' => true,
384
                ],
385
            ],
386
        ]);
387
388
        $this->assertContainerBuilderHasService('httplug.client.acme');
389
        $this->assertFalse($this->container->getDefinition('httplug.client.acme.http_methods')->isPublic());
390
    }
391
392 View Code Duplication
    public function testBatchClientShouldBePrivateByDefault(): 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...
393
    {
394
        $this->load([
395
            'clients' => [
396
                'acme' => [
397
                    'batch_client' => true,
398
                ],
399
            ],
400
        ]);
401
402
        $this->assertContainerBuilderHasService('httplug.client.acme');
403
        $this->assertFalse($this->container->getDefinition('httplug.client.acme.batch_client')->isPublic());
404
    }
405
406 View Code Duplication
    public function testClientCanBePublic(): 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...
407
    {
408
        $this->load([
409
            'clients' => [
410
                'acme' => [
411
                    'public' => true,
412
                ],
413
            ],
414
        ]);
415
416
        $this->assertContainerBuilderHasService('httplug.client.acme');
417
        $this->assertTrue($this->container->getDefinition('httplug.client.acme')->isPublic());
418
419
        if (version_compare(Kernel::VERSION, '3.4', '>=')) {
420
            // Symfony made services private by default starting from 3.4
421
            $this->assertFalse($this->container->getDefinition('httplug.client.acme')->isPrivate());
422
        }
423
    }
424
425 View Code Duplication
    public function testFlexibleClientCanBePublic(): 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...
426
    {
427
        $this->load([
428
            'clients' => [
429
                'acme' => [
430
                    'public' => true,
431
                    'flexible_client' => true,
432
                ],
433
            ],
434
        ]);
435
436
        $this->assertContainerBuilderHasService('httplug.client.acme');
437
        $this->assertTrue($this->container->getDefinition('httplug.client.acme.flexible')->isPublic());
438
439
        if (version_compare(Kernel::VERSION, '3.4', '>=')) {
440
            // Symfony made services private by default starting from 3.4
441
            $this->assertFalse($this->container->getDefinition('httplug.client.acme.flexible')->isPrivate());
442
        }
443
    }
444
445 View Code Duplication
    public function testHttpMethodsClientCanBePublic(): 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...
446
    {
447
        $this->load([
448
            'clients' => [
449
                'acme' => [
450
                    'public' => true,
451
                    'http_methods_client' => true,
452
                ],
453
            ],
454
        ]);
455
456
        $this->assertContainerBuilderHasService('httplug.client.acme');
457
        $this->assertTrue($this->container->getDefinition('httplug.client.acme.http_methods')->isPublic());
458
459
        if (version_compare(Kernel::VERSION, '3.4', '>=')) {
460
            // Symfony made services private by default starting from 3.4
461
            $this->assertFalse($this->container->getDefinition('httplug.client.acme.http_methods')->isPrivate());
462
        }
463
    }
464
465 View Code Duplication
    public function testBatchClientCanBePublic(): 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...
466
    {
467
        $this->load([
468
            'clients' => [
469
                'acme' => [
470
                    'public' => true,
471
                    'batch_client' => true,
472
                ],
473
            ],
474
        ]);
475
476
        $this->assertContainerBuilderHasService('httplug.client.acme');
477
        $this->assertTrue($this->container->getDefinition('httplug.client.acme.batch_client')->isPublic());
478
479
        if (version_compare(Kernel::VERSION, '3.4', '>=')) {
480
            // Symfony made services private by default starting from 3.4
481
            $this->assertFalse($this->container->getDefinition('httplug.client.acme.batch_client')->isPrivate());
482
        }
483
    }
484
485
    public function testClientIsTaggedWithHttplugClientTag(): void
486
    {
487
        $this->load([
488
            'clients' => [
489
                'acme' => null,
490
            ],
491
        ]);
492
493
        $serviceId = 'httplug.client.acme';
494
495
        $this->assertContainerBuilderHasService($serviceId);
496
497
        $this->assertTrue($this->container->getDefinition($serviceId)->hasTag(HttplugExtension::HTTPLUG_CLIENT_TAG), sprintf(
498
            'Failed asserting that client with service identifier "%s" has been tagged with "%s".',
499
            $serviceId,
500
            HttplugExtension::HTTPLUG_CLIENT_TAG
501
        ));
502
    }
503
504
    /**
505
     * @dataProvider provideVcrPluginConfig
506
     * @group vcr-plugin
507
     */
508
    public function testVcrPluginConfiguration(array $config, array $services, array $arguments = []): void
509
    {
510
        if (!class_exists(InMemoryRecorder::class)) {
511
            $this->markTestSkipped('VCR plugin is not installed.');
512
        }
513
514
        $prefix = 'httplug.client.acme.vcr';
515
        $this->load(['clients' => ['acme' => ['plugins' => [['vcr' => $config]]]]]);
516
        $this->assertContainerBuilderHasService('httplug.plugin.vcr.recorder.in_memory', InMemoryRecorder::class);
517
518
        foreach ($services as $service) {
519
            $this->assertContainerBuilderHasService($prefix.'.'.$service);
520
        }
521
522
        foreach ($arguments as $id => $args) {
523
            foreach ($args as $index => $value) {
524
                $this->assertContainerBuilderHasServiceDefinitionWithArgument($prefix.'.'.$id, $index, $value);
525
            }
526
        }
527
    }
528
529
    /**
530
     * @group vcr-plugin
531
     */
532
    public function testIsNotLoadedUnlessNeeded(): void
533
    {
534
        if (!class_exists(InMemoryRecorder::class)) {
535
            $this->markTestSkipped('VCR plugin is not installed.');
536
        }
537
538
        $this->load(['clients' => ['acme' => ['plugins' => []]]]);
539
        $this->assertContainerBuilderNotHasService('httplug.plugin.vcr.recorder.in_memory');
540
    }
541
542
    public function provideVcrPluginConfig()
543
    {
544
        $config = [
545
            'mode' => 'record',
546
            'recorder' => 'in_memory',
547
            'naming_strategy' => 'app.naming_strategy',
548
        ];
549
        yield [$config, ['record']];
550
551
        $config['mode'] = 'replay';
552
        yield [$config, ['replay']];
553
554
        $config['mode'] = 'replay_or_record';
555
        yield [$config, ['replay', 'record']];
556
557
        $config['recorder'] = 'filesystem';
558
        $config['fixtures_directory'] = __DIR__;
559
        unset($config['naming_strategy']);
560
561
        yield [$config, ['replay', 'record', 'recorder', 'naming_strategy'], ['replay' => [2 => false]]];
562
563
        $config['naming_strategy_options'] = [
564
            'hash_headers' => ['X-FOO'],
565
            'hash_body_methods' => ['PATCH'],
566
        ];
567
568
        yield [
569
            $config,
570
            ['replay', 'record', 'recorder', 'naming_strategy'],
571
            ['naming_strategy' => [$config['naming_strategy_options']]],
572
        ];
573
    }
574
}
575