Completed
Push — master ( 0439b5...1aba6d )
by Kevin
05:34 queued 02:41
created

getInitializationDependencyInjectionContainer()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 5
nc 2
nop 0
1
<?php
2
3
namespace Magium\TestCase;
4
5
use Interop\Container\ContainerInterface;
6
use Magium\AbstractTestCase;
7
use Magium\InvalidConfigurationException;
8
use Magium\TestCaseConfiguration;
9
use Magium\Util\Api\Clairvoyant\Clairvoyant;
10
use Magium\Util\Api\Request;
11
use Magium\Util\Configuration\ClassConfigurationReader;
12
use Magium\Util\Configuration\ConfigurationCollector\DefaultPropertyCollector;
13
use Magium\Util\Configuration\ConfigurationProviderInterface;
14
use Magium\Util\Configuration\ConfigurationReader;
15
use Magium\Util\Configuration\EnvironmentConfigurationReader;
16
use Magium\Util\Configuration\StandardConfigurationProvider;
17
use Magium\Util\Log\Logger;
18
use Magium\Util\TestCase\RegistrationListener;
19
use Magium\WebDriver\LoggingRemoteExecuteMethod;
20
use Magium\WebDriver\WebDriver;
21
use Zend\Di\Config;
22
use Zend\Di\Di;
23
use Zend\I18n\Translator\Translator;
24
use Zend\Log\Writer\Noop;
25
26
class Initializer
27
{
28
29
    protected $testCaseConfiguration = 'Magium\TestCaseConfiguration';
30
    protected $testCaseConfigurationObject;
31
    protected $initialized;
32
    protected $configurationProvider;
33
    protected static $initDi;
34
35
    public function __construct(
36
        $testCaseConfigurationType = null,
37
        TestCaseConfiguration $object = null,
38
        ConfigurationProviderInterface $configurationProvider = null
39
    )
40
    {
41
        if ($testCaseConfigurationType !== null) {
42
            $this->testCaseConfiguration = $testCaseConfigurationType;
43
        }
44
        if ($object instanceof TestCaseConfiguration) {
45
            $this->testCaseConfigurationObject = $object;
46
        }
47
48
        $this->configurationProvider = $configurationProvider;
49
        if (!$this->configurationProvider instanceof ConfigurationProviderInterface) {
50
            $preference = self::getInitializationDependencyInjectionContainer()->instanceManager()->getTypePreferences(ConfigurationProviderInterface::class);
51
            if (is_array($preference) && count($preference)) {
52
                $preference = array_shift($preference);
53
            } else {
54
                $preference = StandardConfigurationProvider::class;
55
            }
56
            $this->configurationProvider = self::getInitializationDependencyInjectionContainer()->get($preference);
57
        }
58
    }
59
60
    public static function setInitializationDependencyInjectionContainer(ContainerInterface $container)
61
    {
62
        self::$initDi = $container;
63
    }
64
65
    /**
66
     * This method returns a DI container that will ONLY be used to initialize this class
67
     *
68
     * @return Di
69
     */
70
71
    public static function getInitializationDependencyInjectionContainer()
72
    {
73
        if (!self::$initDi instanceof Di) {
74
            self::$initDi = new Di();
75
            self::$initDi->instanceManager()->addTypePreference(ConfigurationProviderInterface::class, StandardConfigurationProvider::class);
76
        }
77
        return self::$initDi;
78
    }
79
80
    protected function injectTestCaseHierarchy(AbstractTestCase $testCase)
81
    {
82
        $rc = new \ReflectionClass($testCase);
83
        while ($rc->getParentClass()) {
84
            $class = $rc->getParentClass()->getName();
85
            $testCase->getDi()->instanceManager()->addSharedInstance($testCase, $class);
86
            $rc = new \ReflectionClass($class);
87
        }
88
    }
89
90
    protected function configureWebDriver(AbstractTestCase $testCase)
91
    {
92
        $webDriver = $testCase->getDi()->get('Magium\WebDriver\WebDriver');
93
        if ($webDriver instanceof WebDriver) {
94
            $testCase->setWebdriver($webDriver);
95
            $testCase->setTypePreference(
96
                'Facebook\WebDriver\WebDriver',
97
                'Magium\WebDriver\WebDriver'
98
            );
99
            $testCase->setTypePreference(
100
                'Facebook\WebDriver\RemoteWebDriver',
101
                'Magium\WebDriver\WebDriver'
102
            );
103
        } else {
104
            throw new InvalidConfigurationException('DIC has misconfigured WebDriver object');
105
        }
106
    }
107
108
    protected function initLoggingExecutor(AbstractTestCase $testCase)
109
    {
110
        $remote = $testCase->getDi()->get('Magium\WebDriver\LoggingRemoteExecuteMethod');
111
        if ($remote instanceof LoggingRemoteExecuteMethod) {
112
            $testCase->getWebdriver()->setRemoteExecuteMethod($remote);
113
        } else {
114
            throw new InvalidConfigurationException('DIC has invalid logger configured');
115
        }
116
    }
117
118
    protected function configureClairvoyant(AbstractTestCase $testCase)
119
    {
120
        // This is going to be refactored in a completely backwards compatible way.  Currently, because the DiC is
121
        // rebuilt for each request it doesn't maintain state between tests.  This is a good thing... except when
122
        // something that understands it (the MasterListener) does retain state.
123
124
        $clairvoyant = $this->initClairvoyant($testCase);
125
126
        /* @var $clairvoyant \Magium\Util\Api\Clairvoyant\Clairvoyant */
127
        $request = $testCase->get('Magium\Util\Api\Request');
128
        if ($request instanceof Request) {
129
            $clairvoyant->setApiRequest($request);
130
        }
131
        $clairvoyant->reset();
132
        $clairvoyant->setSessionId($testCase->getWebdriver()->getSessionID());
133
        $clairvoyant->setCapability($this->testCaseConfigurationObject->getCapabilities());
134
        $testCase->getLogger()->addWriter($clairvoyant);
135
    }
136
137
    protected function executeCallbacks(AbstractTestCase $testCase)
138
    {
139
        RegistrationListener::executeCallbacks($testCase);
140
    }
141
142
    protected function setCharacteristics(AbstractTestCase $testCase)
143
    {
144
        $testCase->getLogger()->addCharacteristic(Logger::CHARACTERISTIC_BROWSER, $testCase->getWebdriver()->getBrowser());
145
        $testCase->getLogger()->addCharacteristic(Logger::CHARACTERISTIC_OPERATING_SYSTEM, $testCase->getWebdriver()->getPlatform());
146
    }
147
148
    protected function attachMasterListener(AbstractTestCase $testCase)
149
    {
150
        $testCase->getDi()->instanceManager()->addSharedInstance(AbstractTestCase::getMasterListener(), 'Magium\Util\Phpunit\MasterListener');
151
    }
152
153
    public function initialize(AbstractTestCase $testCase, $force = false)
154
    {
155
        if ($this->initialized === $testCase && !$force) {
156
            return;
157
        }
158
        $this->configureDi($testCase);
159
        $this->attachMasterListener($testCase);
160
        $this->injectTestCaseHierarchy($testCase);
161
        $this->configureWebDriver($testCase);
162
        $this->initLoggingExecutor($testCase);
163
        $this->configureClairvoyant($testCase);
164
        $this->setCharacteristics($testCase);
165
        $this->executeCallbacks($testCase);
166
        $this->initialized = $testCase;
167
    }
168
169
170
    protected function initClairvoyant(AbstractTestCase $testCase)
171
    {
172
        $clairvoyant = AbstractTestCase::getMasterListener()->getListener('Magium\Util\Api\Clairvoyant\Clairvoyant');
173
        if ($clairvoyant instanceof Clairvoyant) {
174
            $testCase->getDi()->instanceManager()->addSharedInstance($clairvoyant, get_class($clairvoyant));
175
        } else {
176
            $clairvoyant = $testCase->get('Magium\Util\Api\Clairvoyant\Clairvoyant');
177
            if ($clairvoyant instanceof Clairvoyant) {
178
                AbstractTestCase::getMasterListener()->addListener($clairvoyant);
179
            } else {
180
                throw new InvalidConfigurationException('Invalid Clairvoyant preference');
181
            }
182
        }
183
        return $clairvoyant;
184
    }
185
186
    protected function getDefaultConfiguration()
187
    {
188
        return [
189
            'definition' => [
190
                'class' => [
191
                    'Magium\WebDriver\WebDriver' => [
192
                        'instantiator' => 'Magium\WebDriver\WebDriverFactory::create'
193
                    ],
194
195
                    'Magium\WebDriver\WebDriverFactory' => [
196
                        'create'       => $this->testCaseConfigurationObject->getWebDriverConfiguration()
197
                    ]
198
                ]
199
            ],
200
            'instance'  => [
201
                'preference' => [
202
                    Translator::class => [\Magium\Util\Translator\Translator::class]
203
                ],
204
                'Magium\Util\Translator\Translator' => [
205
                    'parameters'    => [
206
                        'locale'    => 'en_US'
207
                    ]
208
                ],
209
                'Magium\Util\Log\Logger'   => [
210
                    'parameters'    => [
211
                        'options'   => [
212
                            'writers' => [
213
                                [
214
                                    'name' => Noop::class,
215
                                    'options' => []
216
                                ]
217
                            ]
218
                        ]
219
                    ]
220
                ]
221
            ]
222
        ];
223
    }
224
225
    public function configureDi(AbstractTestCase $testCase)
226
    {
227
228
        if (!$this->testCaseConfigurationObject instanceof TestCaseConfiguration) {
229
            if ($testCase->getDi() instanceof Di) {
230
231
                $testCaseConfiguration = $testCase->get($this->testCaseConfiguration);
232
                if ($testCaseConfiguration instanceof TestCaseConfiguration) {
233
                    $this->testCaseConfigurationObject = $testCaseConfiguration;
234
                }
235
            } else {
236
                $this->testCaseConfigurationObject = new $this->testCaseConfiguration(
237
                    $this->configurationProvider
238
                    , new DefaultPropertyCollector()
239
                );
240
            }
241
        }
242
        if ($testCase->getDi() instanceof Di) {
243
            return;
244
        }
245
        /* @var $configuration TestCaseConfiguration */
246
        $configArray = $this->getDefaultConfiguration();
247
248
        $count = 0;
249
250
        $path = realpath(__DIR__ . '/../');
251
252
        while ($count++ < 5) {
253
            $dir = "{$path}/configuration/";
254
            if (is_dir($dir)) {
255
                foreach (glob($dir . '*.php') as $file) {
256
                    $configArray = array_merge_recursive($configArray, include $file);
257
                }
258
                break;
259
            }
260
            $path .= '/../';
261
        }
262
263
264
        $configArray = $this->testCaseConfigurationObject->reprocessConfiguration($configArray);
265
        $configuration = new Config($configArray);
266
267
        $di = new Di();
268
        $configuration->configure($di);
269
        $testCase->setDi($di);
270
        $di->instanceManager()->addSharedInstance($di, Di::class);
271
272
        $this->setConfigurationProvider($testCase);
273
    }
274
275
    public function setConfigurationProvider(AbstractTestCase $testCase)
276
    {
277
        $configuredProvider = self::getInitializationDependencyInjectionContainer()->instanceManager()->getTypePreferences(ConfigurationProviderInterface::class);
278
        if (is_array($configuredProvider) && count($configuredProvider)) {
279
            $configuredProvider = array_shift($configuredProvider);
280
        } else {
281
            $configuredProvider = StandardConfigurationProvider::class;
282
        }
283
        $testCase->setTypePreference(
284
            ConfigurationProviderInterface::class,
285
            $configuredProvider
286
        );
287
        $this->configurationProvider->configureDi($testCase->getDi());
288
289
    }
290
291
}
292