Completed
Push — update ( 3c072c...67888e )
by Haralan
06:13
created

SaveOnFailure::save_driver_content()   B

Complexity

Conditions 3
Paths 4

Size

Total Lines 26
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 26
rs 8.8571
c 0
b 0
f 0
cc 3
eloc 14
nc 4
nop 3
1
<?php
2
3
namespace Openbuildings\PHPUnitSpiderling;
4
5
class SaveOnFailure implements \PHPUnit\Framework\TestListener {
6
7
	/**
8
	 * Convert an attribute strigng from a relative to absolute, by providing a base_url
9
	 * @param  string $attribute name of the attribute, e.g. src, href
10
	 * @param  string $content   the string where to do the change
11
	 * @param  string $base_url
12
	 * @return string
13
	 */
14
	public static function to_absolute_attribute($attribute, $content, $base_url = NULL)
15
	{
16
		return preg_replace('/('.$attribute.'=[\'"])\//', '$1'.rtrim($base_url, '/').'/', $content);
17
	}
18
19
	/**
20
	 * Check if a directory does not exist, create it, otherwise check if it is writable
21
	 * @param  string $directory
22
	 * @throws Exception If directory is not writable
23
	 */
24
	public static function autocreate_directory($directory)
25
	{
26
		if ( ! file_exists($directory))
27
		{
28
			mkdir($directory, 0777, TRUE);
29
		}
30
31
		if ( ! is_writable($directory))
32
			throw new \Exception("Directory \"{$directory}\" is not writable");
33
	}
34
35
	/**
36
	 * Delete all the files from a directory
37
	 * @param  string $directory
38
	 */
39
	public static function clear_directory($directory)
40
	{
41
		foreach (scandir($directory) as $file)
42
		{
43
			if ($file !== '.' AND $file !== '..')
44
			{
45
				unlink($directory.$file);
46
			}
47
		}
48
	}
49
50
	/**
51
	 * Execute a php script and get the output of that script as a string, optionally pass variables as an associative array to be converted to local variables inside of the file
52
	 * @param  string $filename
53
	 * @param  array  $data
54
	 * @return string
55
	 */
56
	public static function render_file($filename, array $data = array())
57
	{
58
		extract($data, EXTR_SKIP);
59
60
		ob_start();
61
		include $filename;
62
		return ob_get_clean();
63
	}
64
65
	protected $_directory;
66
	protected $_base_url;
67
68
	function __construct($directory, $base_url)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
69
	{
70
		if ( ! $directory)
71
			throw new Exception('You must set a directory to output errors to');
72
73
		$this->_directory = rtrim($directory, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR;
74
		$this->_base_url = $base_url;
75
76
		self::autocreate_directory($directory);
77
		self::clear_directory($directory);
78
	}
79
80
	/**
81
	 * Save the current content of the driver into an html file. Add javascript errors, messages and a title to the html content
82
	 * @param  \Openbuildings\Spiderling\Driver $driver
83
	 * @param  string                           $filename
84
	 * @param  string                           $title
85
	 */
86
	public function save_driver_content(\Openbuildings\Spiderling\Driver $driver, $filename, $title)
87
	{
88
		$content = $driver->content();
89
90
		foreach (array('href', 'action', 'src') as $attribute)
91
		{
92
			$content = self::to_absolute_attribute($attribute, $content, $this->_base_url);
93
		}
94
95
		$testview = self::render_file(__DIR__.'/../assets/error-page.php', array(
96
			'url' => $driver->current_url(),
97
			'title' => $title,
98
			'javascript_errors' => $driver->javascript_errors(),
99
			'javascript_messages' => $driver->javascript_messages(),
100
		));
101
102
		$page_content = str_replace('</body>', $testview.'</body>', $content);
103
104
		file_put_contents($this->_directory."/$filename.html", $page_content);
105
106
		try
107
		{
108
			$driver->screenshot($this->_directory."/$filename.png");
109
		}
110
		catch (\Openbuildings\Spiderling\Exception_Notimplemented $e){}
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
111
	}
112
113
	/**
114
	 * Implement PHPUnit\Framework\TestListener, save driver content if there was an error
115
	 * @param \PHPUnit\Framework\Test $test
116
	 * @param \Exception              $exception
117
	 * @param integer                  $time
118
	 */
119
	public function addError(\PHPUnit\Framework\Test $test, \Exception $exception, $time)
120
	{
121
		if ($test instanceof TestCase AND $test->is_driver_active() AND $test->driver()->is_page_active())
122
		{
123
			$this->save_driver_content(
124
				$test->driver(),
125
				get_class($test).'_'.$test->getName(FALSE),
126
				$exception->getMessage()
127
			);
128
		}
129
	}
130
131
	/**
132
	 * Implement PHPUnit\Framework\TestListener, save driver content if there was an error
133
	 * @param \PHPUnit\Framework\Test                 $test
134
	 * @param \PHPUnit\Framework\AssertionFailedError $failure
135
	 * @param integer                                 $time
136
	 */
137
	public function addFailure(\PHPUnit\Framework\Test $test, \PHPUnit\Framework\AssertionFailedError $failure, $time)
138
	{
139
		if ($test instanceof TestCase AND $test->is_driver_active() AND $test->driver()->is_page_active())
140
		{
141
142
			$this->save_driver_content(
143
				$test->driver(),
144
				get_class($test).'_'.$test->getName(FALSE),
145
				$failure->getMessage()
146
			);
147
		}
148
	}
149
150
	// @codeCoverageIgnoreStart
151
	public function addWarning(\PHPUnit\Framework\Test $test, \PHPUnit\Framework\Warning $e, $time) {}
152
	public function addRiskyTest(\PHPUnit\Framework\Test $test, \Exception $e, $time) {}
153
	public function addIncompleteTest(\PHPUnit\Framework\Test $test, \Exception $e, $time) {}
154
	public function addSkippedTest(\PHPUnit\Framework\Test $test, \Exception $e, $time) {}
155
	public function startTest(\PHPUnit\Framework\Test $test) {}
156
	public function endTest(\PHPUnit\Framework\Test $test, $time) {}
157
	public function startTestSuite(\PHPUnit\Framework\TestSuite $suite) {}
158
	public function endTestSuite(\PHPUnit\Framework\TestSuite $suite) {}
159
	// @codeCoverageIgnoreEnd
160
}
161