1 | <?php |
||
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) |
|
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()) |
|
73 | |||
74 | protected $_directory; |
||
75 | protected $_base_url; |
||
76 | |||
77 | 1 | function __construct($directory, $base_url) |
|
|
|||
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){} |
||
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) |
||
172 | |||
173 | // @codeCoverageIgnoreStart |
||
174 | public function addIncompleteTest(\PHPUnit_Framework_Test $test, \Exception $e, $time) {} |
||
180 | // @codeCoverageIgnoreEnd |
||
181 | } |
||
182 |
Adding explicit visibility (
private
,protected
, orpublic
) is generally recommend to communicate to other developers how, and from where this method is intended to be used.