Completed
Pull Request — master (#7)
by Haralan
09:53 queued 08:07
created

SaveOnFailure::autocreate_directory()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3.0416

Importance

Changes 0
Metric Value
dl 0
loc 10
ccs 5
cts 6
cp 0.8333
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 5
nc 4
nop 1
crap 3.0416
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 8
	public static function to_absolute_attribute($attribute, $content, $base_url = NULL)
15
	{
16 8
		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 2
	public static function autocreate_directory($directory)
25
	{
26 2
		if ( ! file_exists($directory))
27
		{
28 2
			mkdir($directory, 0777, TRUE);
29
		}
30
31 2
		if ( ! is_writable($directory))
32
			throw new \Exception("Directory \"{$directory}\" is not writable");
33 2
	}
34
35
	/**
36
	 * Delete all the files from a directory
37
	 * @param  string $directory
38
	 */
39 2
	public static function clear_directory($directory)
40
	{
41 2
		foreach (scandir($directory) as $file)
42
		{
43 2
			if ($file !== '.' AND $file !== '..')
44
			{
45 1
				unlink($directory.$file);
46
			}
47
		}
48 2
	}
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 1
	public static function render_file($filename, array $data = array())
57
	{
58 1
		extract($data, EXTR_SKIP);
59
60 1
		ob_start();
61 1
		include $filename;
62 1
		return ob_get_clean();
63
	}
64
65
	protected $_directory;
66
	protected $_base_url;
67
68 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...
69
	{
70 1
		if ( ! $directory) {
71
			throw new \Exception('You must set a directory to output errors to');
72
		}
73
74 1
		$this->_directory = rtrim($directory, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR;
75 1
		$this->_base_url = $base_url;
76
77 1
		self::autocreate_directory($directory);
78 1
		self::clear_directory($directory);
79 1
	}
80
81
	/**
82
	 * Save the current content of the driver into an html file. Add javascript errors, messages and a title to the html content
83
	 * @param  \Openbuildings\Spiderling\Driver $driver
84
	 * @param  string                           $filename
85
	 * @param  string                           $title
86
	 */
87 1
	public function save_driver_content(\Openbuildings\Spiderling\Driver $driver, $filename, $title)
88
	{
89 1
		$content = $driver->content();
90
91 1
		foreach (array('href', 'action', 'src') as $attribute)
92
		{
93 1
			$content = self::to_absolute_attribute($attribute, $content, $this->_base_url);
94
		}
95
96 1
		$testview = self::render_file(__DIR__.'/../assets/error-page.php', array(
97 1
			'url' => $driver->current_url(),
98 1
			'title' => $title,
99 1
			'javascript_errors' => $driver->javascript_errors(),
100 1
			'javascript_messages' => $driver->javascript_messages(),
101
		));
102
103 1
		$page_content = str_replace('</body>', $testview.'</body>', $content);
104
105 1
		file_put_contents($this->_directory."/$filename.html", $page_content);
106
107
		try
108
		{
109 1
			$driver->screenshot($this->_directory."/$filename.png");
110
		}
111
		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...
112 1
	}
113
114
	/**
115
	 * Implement PHPUnit\Framework\TestListener, save driver content if there was an error
116
	 * @param \PHPUnit\Framework\Test $test
117
	 * @param \Exception              $exception
118
	 * @param integer                  $time
119
	 */
120 1
	public function addError(\PHPUnit\Framework\Test $test, \Exception $exception, $time)
121
	{
122 1
		if ($test instanceof TestCase AND $test->is_driver_active() AND $test->driver()->is_page_active())
123
		{
124 1
			$this->save_driver_content(
125 1
				$test->driver(),
126 1
				get_class($test).'_'.$test->getName(FALSE),
127 1
				$exception->getMessage()
128
			);
129
		}
130 1
	}
131
132
	/**
133
	 * Implement PHPUnit\Framework\TestListener, save driver content if there was an error
134
	 * @param \PHPUnit\Framework\Test                 $test
135
	 * @param \PHPUnit\Framework\AssertionFailedError $failure
136
	 * @param integer                                 $time
137
	 */
138 1
	public function addFailure(\PHPUnit\Framework\Test $test, \PHPUnit\Framework\AssertionFailedError $failure, $time)
139
	{
140 1
		if ($test instanceof TestCase AND $test->is_driver_active() AND $test->driver()->is_page_active())
141
		{
142
143 1
			$this->save_driver_content(
144 1
				$test->driver(),
145 1
				get_class($test).'_'.$test->getName(FALSE),
146 1
				$failure->getMessage()
147
			);
148
		}
149 1
	}
150
151
	// @codeCoverageIgnoreStart
152
	public function addWarning(\PHPUnit\Framework\Test $test, \PHPUnit\Framework\Warning $e, $time) {}
153
	public function addRiskyTest(\PHPUnit\Framework\Test $test, \Exception $e, $time) {}
154
	public function addIncompleteTest(\PHPUnit\Framework\Test $test, \Exception $e, $time) {}
155
	public function addSkippedTest(\PHPUnit\Framework\Test $test, \Exception $e, $time) {}
156
	public function startTest(\PHPUnit\Framework\Test $test) {}
157
	public function endTest(\PHPUnit\Framework\Test $test, $time) {}
158
	public function startTestSuite(\PHPUnit\Framework\TestSuite $suite) {}
159
	public function endTestSuite(\PHPUnit\Framework\TestSuite $suite) {}
160
	// @codeCoverageIgnoreEnd
161
}
162