Completed
Push — master ( dfb504...1f28ec )
by David
03:11 queued 11s
created

testClientIsTaggedWithHttplugClientTag()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

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