|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
declare(strict_types=1); |
|
4
|
|
|
|
|
5
|
|
|
/* |
|
6
|
|
|
* This file is part of the SymfonyExtension package. |
|
7
|
|
|
* |
|
8
|
|
|
* (c) Kamil Kokot <[email protected]> |
|
9
|
|
|
* |
|
10
|
|
|
* For the full copyright and license information, please view the LICENSE |
|
11
|
|
|
* file that was distributed with this source code. |
|
12
|
|
|
*/ |
|
13
|
|
|
|
|
14
|
|
|
namespace FriendsOfBehat\SymfonyExtension\Context\Environment\Handler; |
|
15
|
|
|
|
|
16
|
|
|
use Behat\Behat\Context\Context; |
|
17
|
|
|
use Behat\Behat\Context\Initializer\ContextInitializer; |
|
18
|
|
|
use Behat\Testwork\Environment\Environment; |
|
19
|
|
|
use Behat\Testwork\Environment\Exception\EnvironmentIsolationException; |
|
20
|
|
|
use Behat\Testwork\Environment\Handler\EnvironmentHandler; |
|
21
|
|
|
use Behat\Testwork\Suite\Exception\SuiteConfigurationException; |
|
22
|
|
|
use Behat\Testwork\Suite\Suite; |
|
23
|
|
|
use FriendsOfBehat\SymfonyExtension\Context\Environment\InitialisedContextServiceEnvironment; |
|
24
|
|
|
use FriendsOfBehat\SymfonyExtension\Context\Environment\UninitialisedContextServiceEnvironment; |
|
25
|
|
|
use Symfony\Component\DependencyInjection\ContainerInterface; |
|
26
|
|
|
use Symfony\Component\HttpKernel\KernelInterface; |
|
27
|
|
|
|
|
28
|
|
|
final class ContextServiceEnvironmentHandler implements EnvironmentHandler |
|
29
|
|
|
{ |
|
30
|
|
|
/** @var KernelInterface */ |
|
31
|
|
|
private $symfonyKernel; |
|
32
|
|
|
|
|
33
|
|
|
/** @var ContextInitializer[] */ |
|
34
|
|
|
private $contextInitializers = []; |
|
35
|
|
|
|
|
36
|
|
|
public function __construct(KernelInterface $symfonyKernel) |
|
37
|
|
|
{ |
|
38
|
|
|
$this->symfonyKernel = $symfonyKernel; |
|
39
|
|
|
} |
|
40
|
|
|
|
|
41
|
|
|
public function supportsSuite(Suite $suite): bool |
|
42
|
|
|
{ |
|
43
|
|
|
return $suite->hasSetting('contexts'); |
|
44
|
|
|
} |
|
45
|
|
|
|
|
46
|
|
|
public function buildEnvironment(Suite $suite): Environment |
|
47
|
|
|
{ |
|
48
|
|
|
$environment = new UninitialisedContextServiceEnvironment($suite); |
|
49
|
|
|
foreach ($this->getSuiteContextsServices($suite) as $contextId) { |
|
50
|
|
|
$environment->registerContextService($contextId, $this->getContextClass($contextId)); |
|
51
|
|
|
} |
|
52
|
|
|
|
|
53
|
|
|
return $environment; |
|
54
|
|
|
} |
|
55
|
|
|
|
|
56
|
|
|
public function supportsEnvironmentAndSubject(Environment $environment, $testSubject = null): bool |
|
57
|
|
|
{ |
|
58
|
|
|
return $environment instanceof UninitialisedContextServiceEnvironment; |
|
59
|
|
|
} |
|
60
|
|
|
|
|
61
|
|
|
/** |
|
62
|
|
|
* @throws EnvironmentIsolationException |
|
63
|
|
|
*/ |
|
64
|
|
|
public function isolateEnvironment(Environment $uninitializedEnvironment, $testSubject = null): Environment |
|
65
|
|
|
{ |
|
66
|
|
|
/** @var UninitialisedContextServiceEnvironment $uninitializedEnvironment */ |
|
67
|
|
|
$this->assertEnvironmentCanBeIsolated($uninitializedEnvironment, $testSubject); |
|
68
|
|
|
|
|
69
|
|
|
$environment = new InitialisedContextServiceEnvironment($uninitializedEnvironment->getSuite()); |
|
70
|
|
|
foreach ($uninitializedEnvironment->getContextServices() as $contextId) { |
|
71
|
|
|
/** @var Context $context */ |
|
72
|
|
|
$context = $this->getContext($contextId); |
|
73
|
|
|
$this->initializeInstance($context); |
|
74
|
|
|
$environment->registerContext($context); |
|
75
|
|
|
} |
|
76
|
|
|
|
|
77
|
|
|
return $environment; |
|
78
|
|
|
} |
|
79
|
|
|
|
|
80
|
|
|
public function registerContextInitializer(ContextInitializer $initializer): void |
|
81
|
|
|
{ |
|
82
|
|
|
$this->contextInitializers[] = $initializer; |
|
83
|
|
|
} |
|
84
|
|
|
|
|
85
|
|
|
/** |
|
86
|
|
|
* @return string[] |
|
87
|
|
|
* |
|
88
|
|
|
* @throws SuiteConfigurationException If "contexts" setting is not an array |
|
89
|
|
|
*/ |
|
90
|
|
|
private function getSuiteContextsServices(Suite $suite): array |
|
91
|
|
|
{ |
|
92
|
|
|
$contextsServices = $suite->getSetting('contexts'); |
|
93
|
|
|
|
|
94
|
|
|
if (!is_array($contextsServices)) { |
|
95
|
|
|
throw new SuiteConfigurationException(sprintf( |
|
96
|
|
|
'"contexts" setting of the "%s" suite is expected to be an array, %s given.', |
|
97
|
|
|
$suite->getName(), |
|
98
|
|
|
gettype($contextsServices) |
|
99
|
|
|
), $suite->getName()); |
|
100
|
|
|
} |
|
101
|
|
|
|
|
102
|
|
|
return $contextsServices; |
|
103
|
|
|
} |
|
104
|
|
|
|
|
105
|
|
|
/** |
|
106
|
|
|
* @throws EnvironmentIsolationException |
|
107
|
|
|
*/ |
|
108
|
|
|
private function assertEnvironmentCanBeIsolated(Environment $uninitializedEnvironment, $testSubject): void |
|
109
|
|
|
{ |
|
110
|
|
|
if (!$this->supportsEnvironmentAndSubject($uninitializedEnvironment, $testSubject)) { |
|
111
|
|
|
throw new EnvironmentIsolationException(sprintf( |
|
112
|
|
|
'"%s" does not support isolation of "%s" environment.', |
|
113
|
|
|
static::class, |
|
114
|
|
|
get_class($uninitializedEnvironment) |
|
115
|
|
|
), $uninitializedEnvironment); |
|
116
|
|
|
} |
|
117
|
|
|
} |
|
118
|
|
|
|
|
119
|
|
|
private function initializeInstance(Context $context): void |
|
120
|
|
|
{ |
|
121
|
|
|
foreach ($this->contextInitializers as $initializer) { |
|
122
|
|
|
$initializer->initializeContext($context); |
|
123
|
|
|
} |
|
124
|
|
|
} |
|
125
|
|
|
|
|
126
|
|
View Code Duplication |
private function getContextClass(string $contextId): string |
|
|
|
|
|
|
127
|
|
|
{ |
|
128
|
|
|
if ($this->getContainer()->has($contextId)) { |
|
129
|
|
|
return get_class($this->getContainer()->get($contextId)); |
|
130
|
|
|
} |
|
131
|
|
|
|
|
132
|
|
|
$class = '\\' . ltrim($contextId, '\\'); |
|
133
|
|
|
|
|
134
|
|
|
if (class_exists($class)) { |
|
135
|
|
|
return $class; |
|
136
|
|
|
} |
|
137
|
|
|
|
|
138
|
|
|
throw new \Exception('wtf?'); |
|
139
|
|
|
} |
|
140
|
|
|
|
|
141
|
|
View Code Duplication |
private function getContext(string $contextId): Context |
|
|
|
|
|
|
142
|
|
|
{ |
|
143
|
|
|
if ($this->getContainer()->has($contextId)) { |
|
144
|
|
|
return $this->getContainer()->get($contextId); |
|
145
|
|
|
} |
|
146
|
|
|
|
|
147
|
|
|
$class = '\\' . ltrim($contextId, '\\'); |
|
148
|
|
|
|
|
149
|
|
|
if (class_exists($class)) { |
|
150
|
|
|
return new $class(); |
|
151
|
|
|
} |
|
152
|
|
|
|
|
153
|
|
|
throw new \Exception('wtf?'); |
|
154
|
|
|
} |
|
155
|
|
|
|
|
156
|
|
|
private function getContainer(): ContainerInterface |
|
157
|
|
|
{ |
|
158
|
|
|
return $this->symfonyKernel->getContainer(); |
|
159
|
|
|
} |
|
160
|
|
|
} |
|
161
|
|
|
|
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.