Failed Conditions
Pull Request — master (#75)
by Malte
03:57
created

BrowserTestCase::runTest()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 7
Bugs 0 Features 1
Metric Value
c 7
b 0
f 1
dl 0
loc 12
ccs 0
cts 8
cp 0
rs 9.4285
cc 2
eloc 7
nc 2
nop 0
crap 6
1
<?php
2
/**
3
 * This file is part of the phpunit-mink library.
4
 * For the full copyright and license information, please view
5
 * the LICENSE file that was distributed with this source code.
6
 *
7
 * @copyright Alexander Obuhovich <[email protected]>
8
 * @link      https://github.com/aik099/phpunit-mink
9
 */
10
11
namespace aik099\PHPUnit;
12
13
14
use aik099\PHPUnit\BrowserConfiguration\BrowserConfiguration;
15
use aik099\PHPUnit\BrowserConfiguration\IBrowserConfigurationFactory;
16
use aik099\PHPUnit\RemoteCoverage\RemoteCoverageHelper;
17
use aik099\PHPUnit\RemoteCoverage\RemoteCoverageTool;
18
use aik099\PHPUnit\Event\TestEndedEvent;
19
use aik099\PHPUnit\Event\TestEvent;
20
use aik099\PHPUnit\Event\TestFailedEvent;
21
use aik099\PHPUnit\Session\ISessionStrategy;
22
use aik099\PHPUnit\Session\SessionStrategyManager;
23
use aik099\PHPUnit\TestSuite\RegularTestSuite;
24
use Behat\Mink\Exception\DriverException;
25
use Behat\Mink\Session;
26
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
27
28
/**
29
 * Test Case class for writing browser-based tests.
30
 *
31
 * @method \Mockery\Expectation shouldReceive(string $name)
32
 */
33
abstract class BrowserTestCase extends \PHPUnit_Framework_TestCase implements IEventDispatcherAware
34
{
35
36
	const TEST_ENDED_EVENT = 'test.ended';
37
38
	const TEST_SUITE_ENDED_EVENT = 'test_suite.ended';
39
40
	const TEST_FAILED_EVENT = 'test.failed';
41
42
	const TEST_SETUP_EVENT = 'test.setup';
43
44
	/**
45
	 * Browser list to be used in tests.
46
	 *
47
	 * @var array
48
	 */
49
	public static $browsers = array();
50
51
	/**
52
	 * Event dispatcher.
53
	 *
54
	 * @var EventDispatcherInterface
55
	 */
56
	private $_eventDispatcher;
57
58
	/**
59
	 * Browser configuration factory.
60
	 *
61
	 * @var IBrowserConfigurationFactory
62
	 */
63
	private $_browserConfigurationFactory;
64
65
	/**
66
	 * Remote coverage collection url.
67
	 *
68
	 * @var string Override to provide code coverage data from the server
69
	 */
70
	private $_remoteCoverageScriptUrl;
71
72
	/**
73
	 * Current browser configuration.
74
	 *
75
	 * @var BrowserConfiguration
76
	 */
77
	private $_browser;
78
79
	/**
80
	 * Reference to Mink session.
81
	 *
82
	 * @var Session
83
	 */
84
	private $_session;
85
86
	/**
87
	 * Session strategy manager.
88
	 *
89
	 * @var SessionStrategyManager
90
	 */
91
	protected $sessionStrategyManager;
92
93
	/**
94
	 * Remote coverage helper.
95
	 *
96
	 * @var RemoteCoverageHelper
97
	 */
98
	protected $remoteCoverageHelper;
99
100
	/**
101
	 * Session strategy, used currently.
102
	 *
103
	 * @var ISessionStrategy
104
	 */
105
	protected $sessionStrategy;
106
107
	/**
108
	 * Test ID.
109
	 *
110
	 * @var string
111
	 */
112
	private $_testId;
113
114
	/**
115
	 * Sets application.
116
	 *
117
	 * @param IBrowserConfigurationFactory $browser_configuration_factory Browser configuration factory.
118
	 *
119
	 * @return void
120
	 */
121 9
	public function setBrowserConfigurationFactory(IBrowserConfigurationFactory $browser_configuration_factory)
122
	{
123 9
		$this->_browserConfigurationFactory = $browser_configuration_factory;
124 9
	}
125
126
	/**
127
	 * Sets event dispatcher.
128
	 *
129
	 * @param EventDispatcherInterface $event_dispatcher Event dispatcher.
130
	 *
131
	 * @return void
132
	 */
133 10
	public function setEventDispatcher(EventDispatcherInterface $event_dispatcher)
134
	{
135 10
		$this->_eventDispatcher = $event_dispatcher;
136 10
	}
137
138
	/**
139
	 * Sets session strategy manager.
140
	 *
141
	 * @param SessionStrategyManager $session_strategy_manager Session strategy manager.
142
	 *
143
	 * @return self
144
	 */
145 11
	public function setSessionStrategyManager(SessionStrategyManager $session_strategy_manager)
146
	{
147 11
		$this->sessionStrategyManager = $session_strategy_manager;
148
149 11
		return $this;
150
	}
151
152
	/**
153
	 * Sets remote coverage helper.
154
	 *
155
	 * @param RemoteCoverageHelper $remote_coverage_helper Remote coverage helper.
156
	 *
157
	 * @return void
158
	 */
159 2
	public function setRemoteCoverageHelper(RemoteCoverageHelper $remote_coverage_helper)
160
	{
161 2
		$this->remoteCoverageHelper = $remote_coverage_helper;
162 2
	}
163
164
	/**
165
	 * Sets base url for remote coverage information collection.
166
	 *
167
	 * @param string $url URL.
168
	 *
169
	 * @return void
170
	 */
171
	public function setRemoteCoverageScriptUrl($url)
172
	{
173
		$this->_remoteCoverageScriptUrl = $url;
174
	}
175
176
	/**
177
	 * Set session meta-info for "Sauce Labs".
178
	 *
179
	 * @return void
180
	 */
181
	protected function setUp()
182
	{
183
		parent::setUp();
184
185
		$this->_eventDispatcher->dispatch(
186
			self::TEST_SETUP_EVENT,
187
			new TestEvent($this)
188
		);
189
	}
190
191
	/**
192
	 * Sets browser configuration.
193
	 *
194
	 * @param BrowserConfiguration $browser Browser configuration.
195
	 *
196
	 * @return self
197
	 */
198 5
	public function setBrowser(BrowserConfiguration $browser)
199
	{
200 5
		$this->_browser = $browser->attachToTestCase($this);
201
202
		// Configure session strategy.
203 5
		return $this->setSessionStrategy($this->sessionStrategyManager->getSessionStrategy($browser));
204
	}
205
206
	/**
207
	 * Returns browser configuration.
208
	 *
209
	 * @return BrowserConfiguration
210
	 * @throws \RuntimeException When browser configuration isn't defined.
211
	 */
212 5
	public function getBrowser()
213
	{
214 5
		if ( !is_object($this->_browser) ) {
215 1
			throw new \RuntimeException('Browser configuration not defined');
216
		}
217
218 4
		return $this->_browser;
219
	}
220
221
	/**
222
	 * Initializes a browser with given configuration.
223
	 *
224
	 * @param array $browser_config Browser configuration.
225
	 *
226
	 * @return self
227
	 */
228 2
	public function setBrowserFromConfiguration(array $browser_config)
229
	{
230 2
		return $this->setBrowser($this->createBrowserConfiguration($browser_config));
231
	}
232
233
	/**
234
	 * Returns browser configuration instance.
235
	 *
236
	 * @param array $browser_config Browser.
237
	 *
238
	 * @return BrowserConfiguration
239
	 */
240 2
	protected function createBrowserConfiguration(array $browser_config)
241
	{
242 2
		return $this->_browserConfigurationFactory->createBrowserConfiguration($browser_config, $this);
243
	}
244
245
	/**
246
	 * Sets session strategy.
247
	 *
248
	 * @param ISessionStrategy $session_strategy Session strategy.
249
	 *
250
	 * @return self
251
	 */
252 8
	public function setSessionStrategy(ISessionStrategy $session_strategy = null)
253
	{
254 8
		$this->sessionStrategy = $session_strategy;
255
256 8
		return $this;
257
	}
258
259
	/**
260
	 * Returns session strategy used currently.
261
	 *
262
	 * @return ISessionStrategy
263
	 * @see    setSessionStrategy()
264
	 */
265 5
	public function getSessionStrategy()
266
	{
267 5
		if ( $this->sessionStrategy ) {
268 4
			return $this->sessionStrategy;
269
		}
270
271
		// Default session strategy (not session itself) shared across all test cases.
272 1
		return $this->sessionStrategyManager->getDefaultSessionStrategy();
273
	}
274
275
	/**
276
	 * Creates Mink session using current session strategy and returns it.
277
	 *
278
	 * @return Session
279
	 */
280 2
	public function getSession()
281
	{
282 2
		if ( $this->_session ) {
283 1
			return $this->_session;
284
		}
285
286 2
		$browser = $this->getBrowser();
287
288
		try {
289 2
			$this->_session = $this->getSessionStrategy()->session($browser);
290
291 1
			if ( $this->getCollectCodeCoverageInformation() ) {
292
				$this->_session->visit($browser->getBaseUrl());
293
			}
294
		}
295 2
		catch ( DriverException $e ) {
296 1
			$message = 'The Selenium Server is not active on host %s at port %s';
297 1
			$this->markTestSkipped(sprintf($message, $browser->getHost(), $browser->getPort()));
298
		}
299
300 1
		return $this->_session;
301
	}
302
303
	/**
304
	 * Runs the test case and collects the results in a TestResult object.
305
	 *
306
	 * If no TestResult object is passed a new one will be created.
307
	 *
308
	 * @param \PHPUnit_Framework_TestResult $result Test result.
309
	 *
310
	 * @return \PHPUnit_Framework_TestResult
311
	 * @throws \PHPUnit_Framework_Exception When exception was thrown during a test.
312
	 */
313
	public function run(\PHPUnit_Framework_TestResult $result = null)
314
	{
315
		if ( $result === null ) {
316
			$result = $this->createResult();
317
		}
318
319
		parent::run($result);
320
321
		if ( $result->getCollectCodeCoverageInformation() ) {
322
			$result->getCodeCoverage()->append($this->getRemoteCodeCoverageInformation(), $this);
323
		}
324
325
		/*$this->setTestResultObject($result);*/
326
327
		// Do not call this before to give the time to the Listeners to run.
328
		$this->_eventDispatcher->dispatch(
329
			self::TEST_ENDED_EVENT,
330
			new TestEndedEvent($this, $result, $this->_session)
331
		);
332
333
		/*$this->setTestResultObject(null);*/
334
335
		return $result;
1 ignored issue
show
introduced by
Expected 1 blank line before return statement; 3 found
Loading history...
336
	}
337
338
	/**
339
	 * Whatever or not code coverage information should be gathered.
340
	 *
341
	 * @return boolean
342
	 * @throws \RuntimeException When used before test is started.
343
	 */
344 2
	public function getCollectCodeCoverageInformation()
345
	{
346 2
		$result = $this->getTestResultObject();
347
348 2
		if ( !is_object($result) ) {
349
			throw new \RuntimeException('Test must be started before attempting to collect coverage information');
350
		}
351
352 2
		return $result->getCollectCodeCoverageInformation();
353
	}
354
355
	/**
356
	 * Override to tell remote website, that code coverage information needs to be collected.
357
	 *
358
	 * @return mixed
359
	 * @throws \Exception When exception was thrown inside the test.
360
	 */
361
	protected function runTest()
362
	{
363
		if ( $this->getCollectCodeCoverageInformation() ) {
364
			$this->_testId = get_class($this) . '__' . $this->getName();
365
366
			$session = $this->getSession();
367
			$session->setCookie(RemoteCoverageTool::TEST_ID_VARIABLE, null);
368
			$session->setCookie(RemoteCoverageTool::TEST_ID_VARIABLE, $this->_testId);
369
		}
370
371
		return parent::runTest();
372
	}
373
374
	/**
375
	 * Called, when last test in a test case has ended.
376
	 *
377
	 * @return self
378
	 */
379 1
	public function onTestSuiteEnded()
380
	{
381 1
		$this->_eventDispatcher->dispatch(
382 1
			self::TEST_SUITE_ENDED_EVENT,
383 1
			new TestEvent($this, $this->_session)
384 1
		);
385
386 1
		return $this;
387
	}
388
389
	/**
390
	 * Returns remote code coverage information, when enabled.
391
	 *
392
	 * @return array
393
	 */
394
	public function getRemoteCodeCoverageInformation()
395
	{
396
		if ( $this->_remoteCoverageScriptUrl ) {
397
			return $this->remoteCoverageHelper->get($this->_remoteCoverageScriptUrl, $this->_testId);
398
		}
399
400
		return array();
401
	}
402
403
	/**
404
	 * Creates test suite for usage with Mink.
405
	 *
406
	 * @param string $class_name Test case class name.
407
	 *
408
	 * @return RegularTestSuite
409
	 */
410 2
	public static function suite($class_name)
411
	{
412 2
		$application = Application::getInstance();
413
414 2
		return $application->getTestSuiteFactory()->createSuiteFromTestCase($class_name);
415
	}
416
417
	/**
418
	 * This method is called when a test method did not execute successfully.
419
	 *
420
	 * @param \Exception $e Exception.
421
	 *
422
	 * @return void
423
	 */
424 1
	protected function onNotSuccessfulTest(\Exception $e)
425
	{
426 1
		$this->_eventDispatcher->dispatch(
427 1
			self::TEST_FAILED_EVENT,
428 1
			new TestFailedEvent($e, $this, $this->_session)
429 1
		);
430
431 1
		parent::onNotSuccessfulTest($e);
432
	}
433
434
	/**
435
	 * Get test id (generated internally).
436
	 *
437
	 * @return string
438
	 */
439
	public function getTestId()
440
	{
441
		return $this->_testId;
442
	}
443
444
	/**
445
	 * Gets browser configuration aliases.
446
	 *
447
	 * Allows to decouple actual test server connection details from test cases.
448
	 *
449
	 * @return array
450
	 */
451 2
	public function getBrowserAliases()
452
	{
453 2
		return array();
454
	}
455
456
}
457