Completed
Pull Request — master (#7)
by Yann
05:59
created

DependencyInjectionTest::formatProvider()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
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 PHPUnit\Framework\TestCase;
9
use Prophecy\Prophecy\ProphecySubjectInterface;
10
use Psr\Log\LoggerInterface;
11
use Symfony\Component\Config\FileLocator;
12
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
13
use Symfony\Component\DependencyInjection\ContainerBuilder;
14
use Symfony\Component\DependencyInjection\Definition;
15
use Symfony\Component\DependencyInjection\Loader;
16
use Symfony\Component\HttpFoundation\RequestStack;
17
use Yokai\SecurityTokenBundle\Archive\ArchivistInterface;
18
use Yokai\SecurityTokenBundle\Configuration\TokenConfiguration;
19
use Yokai\SecurityTokenBundle\Factory\TokenFactoryInterface;
20
use Yokai\SecurityTokenBundle\Generator\OpenSslTokenGenerator;
21
use Yokai\SecurityTokenBundle\Generator\TokenGeneratorInterface;
22
use Yokai\SecurityTokenBundle\InformationGuesser\InformationGuesserInterface;
23
use Yokai\SecurityTokenBundle\Manager\TokenManagerInterface;
24
use Yokai\SecurityTokenBundle\Manager\UserManagerInterface;
25
use Yokai\SecurityTokenBundle\Repository\TokenRepositoryInterface;
26
use Yokai\SecurityTokenBundle\YokaiSecurityTokenBundle;
27
28
/**
29
 * @author Yann Eugoné <[email protected]>
30
 */
31
class DependencyInjectionTest extends TestCase
32
{
33
    /**
34
     * @var ContainerBuilder
35
     */
36
    private $container;
37
38
    protected function setUp()
39
    {
40
        $bundle = new YokaiSecurityTokenBundle();
41
        $this->container = new ContainerBuilder();
42
43
        $bundles = [
44
            'FrameworkBundle' => 'Symfony\Bundle\FrameworkBundle\FrameworkBundle',
45
            'DoctrineBundle' => 'Doctrine\Bundle\DoctrineBundle\DoctrineBundle',
46
            'YokaiSecurityTokenBundle' => 'Yokai\SecurityTokenBundle\YokaiSecurityTokenBundle',
47
            'AppBundle' => 'AppBundle\AppBundle',
48
        ];
49
50
        $this->container->setParameter('kernel.debug', true);
51
        $this->container->setParameter('kernel.bundles', $bundles);
52
        $this->container->set('logger', $this->prophesize(LoggerInterface::class)->reveal());
53
        $this->container->setDefinition('doctrine.orm.default_entity_manager', new Definition(EntityManager::class));
54
        $this->container->setDefinition('doctrine.orm.default_metadata_driver', new Definition(MappingDriverChain::class));
55
        $this->container->setDefinition('doctrine.orm.default_configuration', new Definition(Configuration::class));
56
        $this->container->setDefinition('request_stack', new Definition(RequestStack::class));
57
        $this->container->setParameter('doctrine.default_entity_manager', 'default');
58
59
        $mocks = [
60
            'generator_mock' => TokenGeneratorInterface::class,
61
            'information_guesser_mock' => InformationGuesserInterface::class,
62
            'token_factory_mock' => TokenFactoryInterface::class,
63
            'token_repository_mock' => TokenRepositoryInterface::class,
64
            'token_manager_mock' => TokenManagerInterface::class,
65
            'user_manager_mock' => UserManagerInterface::class,
66
            'archivist_mock' => ArchivistInterface::class,
67
        ];
68
        foreach ($mocks as $id => $class) {
69
            $service = $this->prophesize($class)->reveal();
70
            $this->container->setDefinition($id, new Definition(get_class($service)));
71
        }
72
73
        $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...
74
        $bundle->build($this->container);
75
    }
76
77
    /**
78
     * @test
79
     * @dataProvider configurationProvider
80
     */
81
    public function it_parse_configuration_as_expected($resource, array $tokens, array $aliases)
82
    {
83
        // for test purpose, all services are switched to public
84
        $this->container->addCompilerPass(new class implements CompilerPassInterface {
85
            public function process(ContainerBuilder $container)
86
            {
87
                $container->findDefinition('yokai_security_token.configuration_registry')->setPublic(true);
88
                $container->findDefinition('yokai_security_token.default_information_guesser')->setPublic(true);
89
                $container->findDefinition('yokai_security_token.default_token_factory')->setPublic(true);
90
                $container->findDefinition('yokai_security_token.default_token_repository')->setPublic(true);
91
                $container->findDefinition('yokai_security_token.default_token_manager')->setPublic(true);
92
                $container->findDefinition('yokai_security_token.default_user_manager')->setPublic(true);
93
                $container->findDefinition('yokai_security_token.delete_archivist')->setPublic(true);
94
            }
95
        });
96
97
        $this->loadConfiguration($resource);
98
        $this->container->compile();
99
100
        foreach ($tokens as $tokenId => $tokenConfig) {
101
            $token = $this->container->get('yokai_security_token.configuration_registry')->get($tokenId);
102
103
            self::assertInstanceOf(TokenConfiguration::class, $token);
104
            self::assertInstanceOf($tokenConfig['generator'], $token->getGenerator());
105
            self::assertSame($tokenId, $token->getPurpose());
106
            self::assertSame($tokenConfig['duration'], $token->getDuration());
107
        }
108
109
        foreach ($aliases as $alias => $expectedId) {
110
            self::assertTrue(
111
                $this->container->hasAlias($alias),
112
                "An alias named \"$alias\" exists."
113
            );
114
            self::assertSame(
115
                $expectedId, (string) $this->container->getAlias($alias),
116
                "The alias named \"$alias\" refer to \"$expectedId\"."
117
            );
118
        }
119
    }
120
121
    /**
122
     * @param string $resource
123
     */
124
    protected function loadConfiguration($resource)
125
    {
126
        $locator = new FileLocator(__DIR__.'/configuration/');
127
        $path = $locator->locate($resource);
128
129
        switch (pathinfo($path, PATHINFO_EXTENSION)) {
130
            case 'yml':
131
                $loader = new Loader\YamlFileLoader($this->container, $locator);
132
                break;
133
134
            //todo nice to have : support more configuration format
135
136
            default:
137
                throw new \InvalidArgumentException('File ' . $path . ' is not supported.');
138
                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...
139
        }
140
141
        $loader->load($resource);
142
    }
143
144
    public function configurationProvider()
145
    {
146
        $defaultAliases = [
147
            'yokai_security_token.information_guesser' => 'yokai_security_token.default_information_guesser',
148
            'yokai_security_token.token_factory' => 'yokai_security_token.default_token_factory',
149
            'yokai_security_token.token_repository' => 'yokai_security_token.default_token_repository',
150
            'yokai_security_token.token_manager' => 'yokai_security_token.default_token_manager',
151
            'yokai_security_token.user_manager' => 'yokai_security_token.default_user_manager',
152
            'yokai_security_token.archivist' => 'yokai_security_token.delete_archivist',
153
        ];
154
155
        foreach ($this->formatProvider() as $format) {
156
            $format = $format[0];
157
158
            yield $format . ' - none' => [
159
                'none.' . $format,
160
                [],
161
                $defaultAliases,
162
            ];
163
164
            yield $format . ' - names only' => [
165
                'names.' . $format,
166
                [
167
                    'security_password_init' => [
168
                        'generator' => OpenSslTokenGenerator::class,
169
                        'duration' => '+2 days',
170
                    ],
171
                    'security_password_reset' => [
172
                        'generator' => OpenSslTokenGenerator::class,
173
                        'duration' => '+2 days',
174
                    ],
175
                ],
176
                $defaultAliases,
177
            ];
178
179
            yield $format . ' - fully configured' => [
180
                'full.' . $format,
181
                [
182
                    'security_password_init' => [
183
                        'generator' => ProphecySubjectInterface::class,
184
                        'duration' => '+1 month',
185
                    ],
186
                    'security_password_reset' => [
187
                        'generator' => ProphecySubjectInterface::class,
188
                        'duration' => '+2 monthes',
189
                    ],
190
                ],
191
                [
192
                    'yokai_security_token.information_guesser' => 'information_guesser_mock',
193
                    'yokai_security_token.token_factory' => 'token_factory_mock',
194
                    'yokai_security_token.token_repository' => 'token_repository_mock',
195
                    'yokai_security_token.token_manager' => 'token_manager_mock',
196
                    'yokai_security_token.user_manager' => 'user_manager_mock',
197
                    'yokai_security_token.archivist' => 'archivist_mock',
198
                ],
199
            ];
200
        }
201
    }
202
203
    public function formatProvider()
204
    {
205
        yield ['yml'];
206
    }
207
}
208