Completed
Pull Request — master (#7)
by Haralan
11:28 queued 09:45
created

Saveonfailure::save_driver_content()   B

Complexity

Conditions 3
Paths 4

Size

Total Lines 26
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 3.0032

Importance

Changes 0
Metric Value
dl 0
loc 26
ccs 13
cts 14
cp 0.9286
rs 8.8571
c 0
b 0
f 0
cc 3
eloc 14
nc 4
nop 3
crap 3.0032
1
<?php
2
3
namespace Openbuildings\PHPUnitSpiderling;
4
5
6
/**
7
 * Phpunit_Saveonfailure definition
8
 *
9
 * @package    Openbuildings\PHPUnitSpiderling
10
 * @author     Ivan Kerin
11
 * @copyright  (c) 2013 OpenBuildings Ltd.
12
 * @license    http://spdx.org/licenses/BSD-3-Clause
13
 */
14
class Saveonfailure implements \PHPUnit_Framework_TestListener {
15
16
	/**
17
	 * Convert an attribute strigng from a relative to absolute, by providing a base_url
18
	 * @param  string $attribute name of the attribute, e.g. src, href
19
	 * @param  string $content   the string where to do the change
20
	 * @param  string $base_url
21
	 * @return string
22
	 */
23 8
	public static function to_absolute_attribute($attribute, $content, $base_url = NULL)
24
	{
25 8
		return preg_replace('/('.$attribute.'=[\'"])\//', '$1'.rtrim($base_url, '/').'/', $content);
26
	}
27
28
	/**
29
	 * Check if a directory does not exist, create it, otherwise check if it is writable
30
	 * @param  string $directory
31
	 * @throws Exception If directory is not writable
32
	 */
33 2
	public static function autocreate_directory($directory)
34
	{
35 2
		if ( ! file_exists($directory))
36
		{
37 2
			mkdir($directory, 0777, TRUE);
38
		}
39
40 2
		if ( ! is_writable($directory))
41
			throw new \Exception("Directory \"{$directory}\" is not writable");
42 2
	}
43
44
	/**
45
	 * Delete all the files from a directory
46
	 * @param  string $directory
47
	 */
48 2
	public static function clear_directory($directory)
49
	{
50 2
		foreach (scandir($directory) as $file)
51
		{
52 2
			if ($file !== '.' AND $file !== '..')
53
			{
54 1
				unlink($directory.$file);
55
			}
56
		}
57 2
	}
58
59
	/**
60
	 * 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
61
	 * @param  string $filename
62
	 * @param  array  $data
63
	 * @return string
64
	 */
65 1
	public static function render_file($filename, array $data = array())
66
	{
67 1
		extract($data, EXTR_SKIP);
68
69 1
		ob_start();
70 1
		include $filename;
71 1
		return ob_get_clean();
72
	}
73
74
	protected $_directory;
75
	protected $_base_url;
76
77 1
	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...
78
	{
79 1
		if ( ! $directory)
80
			throw new Exception('You must set a directory to output errors to');
81
82 1
		$this->_directory = rtrim($directory, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR;
83 1
		$this->_base_url = $base_url;
84
85 1
		self::autocreate_directory($directory);
86 1
		self::clear_directory($directory);
87 1
	}
88
89
	/**
90
	 * Save the current content of the driver into an html file. Add javascript errors, messages and a title to the html content
91
	 * @param  \Openbuildings\Spiderling\Driver $driver
92
	 * @param  string                           $filename
93
	 * @param  string                           $title
94
	 */
95 1
	public function save_driver_content(\Openbuildings\Spiderling\Driver $driver, $filename, $title)
96
	{
97 1
		$content = $driver->content();
98
99 1
		foreach (array('href', 'action', 'src') as $attribute)
100
		{
101 1
			$content = self::to_absolute_attribute($attribute, $content, $this->_base_url);
102
		}
103
104 1
		$testview = self::render_file(__DIR__.DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.'assets'.DIRECTORY_SEPARATOR.'error-page.php', array(
105 1
			'url' => $driver->current_url(),
106 1
			'title' => $title,
107 1
			'javascript_errors' => $driver->javascript_errors(),
108 1
			'javascript_messages' => $driver->javascript_messages(),
109
		));
110
111 1
		$page_content = str_replace('</body>', $testview.'</body>', $content);
112
113 1
		file_put_contents($this->_directory."/$filename.html", $page_content);
114
115
		try
116
		{
117 1
			$driver->screenshot($this->_directory."/$filename.png");
118
		}
119
		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...
120 1
	}
121
122
	/**
123
	 * Implement PHPUnit_Framework_TestListener, save driver content if there was an error
124
	 * @param \PHPUnit_Framework_Test $test
125
	 * @param \Exception              $exception
126
	 * @param integer                  $time
127
	 */
128 1
	public function addError(\PHPUnit_Framework_Test $test, \Exception $exception, $time)
129
	{
130 1
		if ($test instanceof Testcase_Spiderling AND $test->is_driver_active() AND $test->driver()->is_page_active())
131
		{
132 1
			$this->save_driver_content(
133 1
				$test->driver(),
134 1
				get_class($test).'_'.$test->getName(FALSE),
135 1
				$exception->getMessage()
136
			);
137
		}
138 1
	}
139
140
	/**
141
	 * Implement PHPUnit_Framework_TestListener, save driver content if there was an error
142
	 * @param \PHPUnit_Framework_Test                 $test
143
	 * @param \PHPUnit_Framework_AssertionFailedError $failure
144
	 * @param integer                                 $time
145
	 */
146 1
	public function addFailure(\PHPUnit_Framework_Test $test, \PHPUnit_Framework_AssertionFailedError $failure, $time)
147
	{
148 1
		if ($test instanceof Testcase_Spiderling AND $test->is_driver_active() AND $test->driver()->is_page_active())
149
		{
150
151 1
			$this->save_driver_content(
152 1
				$test->driver(),
153 1
				get_class($test).'_'.$test->getName(FALSE),
154 1
				$failure->getMessage()
155
			);
156
		}
157 1
	}
158
159
160
	/**
161
	 * Risky test.
162
	 *
163
	 * @param PHPUnit_Framework_Test $test
164
	 * @param Exception              $e
165
	 * @param float                  $time
166
	 * @since  Method available since Release 3.8.0
167
	 */
168
	public function addRiskyTest(\PHPUnit_Framework_Test $test, \Exception $e, $time)
169
	{
170
		// Stub out to support PHPUnit 3.8
171
	}
172
173
	// @codeCoverageIgnoreStart
174
	public function addIncompleteTest(\PHPUnit_Framework_Test $test, \Exception $e, $time) {}
175
	public function addSkippedTest(\PHPUnit_Framework_Test $test, \Exception $e, $time) {}
176
	public function startTest(\PHPUnit_Framework_Test $test) {}
177
	public function endTest(\PHPUnit_Framework_Test $test, $time) {}
178
	public function startTestSuite(\PHPUnit_Framework_TestSuite $suite) {}
179
	public function endTestSuite(\PHPUnit_Framework_TestSuite $suite) {}
180
	// @codeCoverageIgnoreEnd
181
}
182