Completed
Push — master ( 3e963f...fbd0cf )
by Yann
02:04
created

DependencyInjectionTest.php$0 ➔ process()   A

Complexity

Conditions 1

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
cc 1
1
<?php
2
3
namespace Yokai\SecurityTokenBundle\Tests\DependencyInjection;
4
5
use Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain;
6
use Doctrine\ORM\Configuration;
7
use Doctrine\ORM\EntityManager;
8
use Prophecy\Prophecy\ProphecySubjectInterface;
9
use Psr\Log\LoggerInterface;
10
use Symfony\Component\Config\FileLocator;
11
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
12
use Symfony\Component\DependencyInjection\ContainerBuilder;
13
use Symfony\Component\DependencyInjection\Definition;
14
use Symfony\Component\DependencyInjection\Loader;
15
use Symfony\Component\HttpFoundation\RequestStack;
16
use Yokai\SecurityTokenBundle\Archive\ArchivistInterface;
17
use Yokai\SecurityTokenBundle\Configuration\TokenConfiguration;
18
use Yokai\SecurityTokenBundle\Factory\TokenFactoryInterface;
19
use Yokai\SecurityTokenBundle\Generator\OpenSslTokenGenerator;
20
use Yokai\SecurityTokenBundle\Generator\TokenGeneratorInterface;
21
use Yokai\SecurityTokenBundle\InformationGuesser\InformationGuesserInterface;
22
use Yokai\SecurityTokenBundle\Manager\TokenManagerInterface;
23
use Yokai\SecurityTokenBundle\Manager\UserManagerInterface;
24
use Yokai\SecurityTokenBundle\Repository\TokenRepositoryInterface;
25
use Yokai\SecurityTokenBundle\YokaiSecurityTokenBundle;
26
27
/**
28
 * @author Yann Eugoné <[email protected]>
29
 */
30
class DependencyInjectionTest extends \PHPUnit_Framework_TestCase
31
{
32
    /**
33
     * @var ContainerBuilder
34
     */
35
    private $container;
36
37
    protected function setUp()
38
    {
39
        $bundle = new YokaiSecurityTokenBundle();
40
        $this->container = new ContainerBuilder();
41
42
        $bundles = [
43
            'FrameworkBundle' => 'Symfony\Bundle\FrameworkBundle\FrameworkBundle',
44
            'DoctrineBundle' => 'Doctrine\Bundle\DoctrineBundle\DoctrineBundle',
45
            'YokaiSecurityTokenBundle' => 'Yokai\SecurityTokenBundle\YokaiSecurityTokenBundle',
46
            'AppBundle' => 'AppBundle\AppBundle',
47
        ];
48
49
        $this->container->setParameter('kernel.debug', true);
50
        $this->container->setParameter('kernel.bundles', $bundles);
51
        $this->container->set('logger', $this->prophesize(LoggerInterface::class)->reveal());
52
        $this->container->setDefinition('doctrine.orm.default_entity_manager', new Definition(EntityManager::class));
53
        $this->container->setDefinition('doctrine.orm.default_metadata_driver', new Definition(MappingDriverChain::class));
54
        $this->container->setDefinition('doctrine.orm.default_configuration', new Definition(Configuration::class));
55
        $this->container->setDefinition('request_stack', new Definition(RequestStack::class));
56
        $this->container->setParameter('doctrine.default_entity_manager', 'default');
57
58
        $mocks = [
59
            'generator_mock' => TokenGeneratorInterface::class,
60
            'information_guesser_mock' => InformationGuesserInterface::class,
61
            'token_factory_mock' => TokenFactoryInterface::class,
62
            'token_repository_mock' => TokenRepositoryInterface::class,
63
            'token_manager_mock' => TokenManagerInterface::class,
64
            'user_manager_mock' => UserManagerInterface::class,
65
            'archivist_mock' => ArchivistInterface::class,
66
        ];
67
        foreach ($mocks as $id => $class) {
68
            $service = $this->prophesize($class)->reveal();
69
            $this->container->setDefinition($id, new Definition(get_class($service)));
70
        }
71
72
        $this->container->registerExtension($bundle->getContainerExtension());
0 ignored issues
show
Bug introduced by
It seems like $bundle->getContainerExtension() can be null; however, registerExtension() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
73
        $bundle->build($this->container);
74
    }
75
76
    /**
77
     * @test
78
     * @dataProvider configurationProvider
79
     */
80
    public function it_parse_configuration_as_expected($resource, array $tokens, array $aliases)
81
    {
82
        // for test purpose, all services are switched to public
83
        $this->container->addCompilerPass(new class implements CompilerPassInterface {
84
            public function process(ContainerBuilder $container)
85
            {
86
                $container->findDefinition('yokai_security_token.configuration_registry')->setPublic(true);
87
                $container->findDefinition('yokai_security_token.default_information_guesser')->setPublic(true);
88
                $container->findDefinition('yokai_security_token.default_token_factory')->setPublic(true);
89
                $container->findDefinition('yokai_security_token.default_token_repository')->setPublic(true);
90
                $container->findDefinition('yokai_security_token.default_token_manager')->setPublic(true);
91
                $container->findDefinition('yokai_security_token.default_user_manager')->setPublic(true);
92
                $container->findDefinition('yokai_security_token.delete_archivist')->setPublic(true);
93
            }
94
        });
95
96
        $this->loadConfiguration($resource);
97
        $this->container->compile();
98
99
        foreach ($tokens as $tokenId => $tokenConfig) {
100
            $token = $this->container->get('yokai_security_token.configuration_registry')->get($tokenId);
101
102
            self::assertInstanceOf(TokenConfiguration::class, $token);
103
            self::assertInstanceOf($tokenConfig['generator'], $token->getGenerator());
104
            self::assertSame($tokenId, $token->getPurpose());
105
            self::assertSame($tokenConfig['duration'], $token->getDuration());
106
        }
107
108
        foreach ($aliases as $alias => $expectedId) {
109
            self::assertTrue(
110
                $this->container->hasAlias($alias),
111
                "An alias named \"$alias\" exists."
112
            );
113
            self::assertSame(
114
                $expectedId, (string) $this->container->getAlias($alias),
115
                "The alias named \"$alias\" refer to \"$expectedId\"."
116
            );
117
        }
118
    }
119
120
    /**
121
     * @param string $resource
122
     */
123
    protected function loadConfiguration($resource)
124
    {
125
        $locator = new FileLocator(__DIR__.'/configuration/');
126
        $path = $locator->locate($resource);
127
128
        switch (pathinfo($path, PATHINFO_EXTENSION)) {
129
            case 'yml':
130
                $loader = new Loader\YamlFileLoader($this->container, $locator);
131
                break;
132
133
            //todo nice to have : support more configuration format
134
135
            default:
136
                throw new \InvalidArgumentException('File ' . $path . ' is not supported.');
137
                break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
138
        }
139
140
        $loader->load($resource);
141
    }
142
143
    public function configurationProvider()
144
    {
145
        $defaultAliases = [
146
            'yokai_security_token.information_guesser' => 'yokai_security_token.default_information_guesser',
147
            'yokai_security_token.token_factory' => 'yokai_security_token.default_token_factory',
148
            'yokai_security_token.token_repository' => 'yokai_security_token.default_token_repository',
149
            'yokai_security_token.token_manager' => 'yokai_security_token.default_token_manager',
150
            'yokai_security_token.user_manager' => 'yokai_security_token.default_user_manager',
151
            'yokai_security_token.archivist' => 'yokai_security_token.delete_archivist',
152
        ];
153
154
        foreach ($this->formatProvider() as $format) {
155
            $format = $format[0];
156
157
            yield $format . ' - none' => [
158
                'none.' . $format,
159
                [],
160
                $defaultAliases,
161
            ];
162
163
            yield $format . ' - names only' => [
164
                'names.' . $format,
165
                [
166
                    'security_password_init' => [
167
                        'generator' => OpenSslTokenGenerator::class,
168
                        'duration' => '+2 days',
169
                    ],
170
                    'security_password_reset' => [
171
                        'generator' => OpenSslTokenGenerator::class,
172
                        'duration' => '+2 days',
173
                    ],
174
                ],
175
                $defaultAliases,
176
            ];
177
178
            yield $format . ' - fully configured' => [
179
                'full.' . $format,
180
                [
181
                    'security_password_init' => [
182
                        'generator' => ProphecySubjectInterface::class,
183
                        'duration' => '+1 month',
184
                    ],
185
                    'security_password_reset' => [
186
                        'generator' => ProphecySubjectInterface::class,
187
                        'duration' => '+2 monthes',
188
                    ],
189
                ],
190
                [
191
                    'yokai_security_token.information_guesser' => 'information_guesser_mock',
192
                    'yokai_security_token.token_factory' => 'token_factory_mock',
193
                    'yokai_security_token.token_repository' => 'token_repository_mock',
194
                    'yokai_security_token.token_manager' => 'token_manager_mock',
195
                    'yokai_security_token.user_manager' => 'user_manager_mock',
196
                    'yokai_security_token.archivist' => 'archivist_mock',
197
                ],
198
            ];
199
        }
200
    }
201
202
    public function formatProvider()
203
    {
204
        yield ['yml'];
205
    }
206
}
207