@@ -20,6 +20,9 @@ class VisualCeption extends \Codeception\Module
2020
2121 private $ maximumDeviation = 0 ;
2222
23+ private $ webDriver = null ;
24+ private $ webDriverModule = null ;
25+
2326 /**
2427 * Create an object from VisualCeption Class
2528 *
@@ -40,38 +43,33 @@ public function __construct ($config)
4043 */
4144 public function _before (\Codeception \TestCase $ test )
4245 {
43- $ this ->test = $ test ;
44- }
45-
46- private function getDeviation ($ identifier , $ elementID )
47- {
48- $ coords = $ this ->getCoordinates ($ elementID );
49- $ this ->createScreenshot ($ identifier , $ coords );
50-
51- $ compareResult = $ this ->compare ($ identifier );
46+ $ this ->webDriverModule = $ this ->getModule ("WebDriver " );
47+ $ this ->webDriver = $ this ->webDriverModule ->webDriver ;
5248
53- unlink ($ this ->getScreenshotPath ($ identifier ));
54-
55- $ deviation = round ($ compareResult [1 ] * 100 , 2 );
56- $ this ->debug ("The deviation between the images is " . $ deviation . " percent " );
57- return array ("deviation " => $ deviation , "deviationImage " => $ compareResult [0 ]);
49+ $ this ->test = $ test ;
5850 }
5951
6052 /**
6153 * Compare the reference image with a current screenshot, identified by their indentifier name
6254 * and their element ID.
6355 *
64- * @param string $identifier identifies your test object
56+ * @param string $identifier Identifies your test object
6557 * @param string $elementID DOM ID of the element, which should be screenshotted
58+ * @param string|array $excludeElements Element name or array of Element names, which should not appear in the screenshot
6659 */
67- public function dontSeeVisualChanges ($ identifier , $ elementID = null )
60+ public function seeVisualChanges ($ identifier , $ elementID = null , $ excludeElements = array () )
6861 {
69- $ deviationResult = $ this ->getDeviation ($ identifier , $ elementID );
62+ if (!is_array ($ excludeElements ) && (string ) $ excludeElements !== '' ) {
63+ $ excludeElements = (array ) $ excludeElements ;
64+ }
65+
66+ $ deviationResult = $ this ->getDeviation ($ identifier , $ elementID , $ excludeElements );
67+
7068 if (! is_null ($ deviationResult ["deviationImage " ])) {
71- if ($ deviationResult ["deviation " ] > $ this ->maximumDeviation ) {
69+ if ($ deviationResult ["deviation " ] <= $ this ->maximumDeviation ) {
7270 $ compareScreenshotPath = $ this ->getDeviationScreenshotPath ($ identifier );
7371 $ deviationResult ["deviationImage " ]->writeImage ($ compareScreenshotPath );
74- $ this ->assertTrue (false , "The deviation of the taken screenshot is too high ( " . $ deviationResult ["deviation " ] . "%). \nSee $ compareScreenshotPath for a deviation screenshot. " );
72+ $ this ->assertTrue (false , "The deviation of the taken screenshot is too low ( " . $ deviationResult ["deviation " ] . "%). \nSee $ compareScreenshotPath for a deviation screenshot. " );
7573 }
7674 }
7775 }
@@ -82,19 +80,47 @@ public function dontSeeVisualChanges ($identifier, $elementID = null)
8280 *
8381 * @param string $identifier identifies your test object
8482 * @param string $elementID DOM ID of the element, which should be screenshotted
83+ * @param string|array $excludeElements string of Element name or array of Element names, which should not appear in the screenshot
8584 */
86- public function seeVisualChanges ($ identifier , $ elementID = null )
85+ public function dontSeeVisualChanges ($ identifier , $ elementID = null , $ excludeElements = array () )
8786 {
88- $ deviationResult = $ this ->getDeviation ($ identifier , $ elementID );
87+ if (!is_array ($ excludeElements ) && (string ) $ excludeElements !== '' ) {
88+ $ excludeElements = (array ) (string )$ excludeElements ;
89+ }
90+
91+ $ deviationResult = $ this ->getDeviation ($ identifier , $ elementID , $ excludeElements );
92+
8993 if (! is_null ($ deviationResult ["deviationImage " ])) {
90- if ($ deviationResult ["deviation " ] <= $ this ->maximumDeviation ) {
94+ if ($ deviationResult ["deviation " ] > $ this ->maximumDeviation ) {
9195 $ compareScreenshotPath = $ this ->getDeviationScreenshotPath ($ identifier );
9296 $ deviationResult ["deviationImage " ]->writeImage ($ compareScreenshotPath );
93- $ this ->assertTrue (false , "The deviation of the taken screenshot is too low ( " . $ deviationResult ["deviation " ] . "%). \nSee $ compareScreenshotPath for a deviation screenshot. " );
97+ $ this ->assertTrue (false , "The deviation of the taken screenshot is too high ( " . $ deviationResult ["deviation " ] . "%). \nSee $ compareScreenshotPath for a deviation screenshot. " );
9498 }
9599 }
96100 }
97101
102+ /**
103+ * Compares the two images and calculate the deviation between expected and actual image
104+ *
105+ * @param $identifier Identifies your test object
106+ * @param $elementID DOM ID of the element, which should be screenshotted
107+ * @param array $excludeElements Element names, which should not appear in the screenshot
108+ * @return array Includes the calculation of deviation in percent and the diff-image
109+ */
110+ private function getDeviation ($ identifier , $ elementID , array $ excludeElements = array ())
111+ {
112+ $ coords = $ this ->getCoordinates ($ elementID );
113+ $ this ->createScreenshot ($ identifier , $ coords , $ excludeElements );
114+
115+ $ compareResult = $ this ->compare ($ identifier );
116+
117+ unlink ($ this ->getScreenshotPath ($ identifier ));
118+
119+ $ deviation = round ($ compareResult [1 ] * 100 , 2 );
120+ $ this ->debug ("The deviation between the images is " . $ deviation . " percent " );
121+ return array ("deviation " => $ deviation , "deviationImage " => $ compareResult [0 ]);
122+ }
123+
98124 /**
99125 * Initialize the module and read the config.
100126 * Throws a runtime exception, if the
@@ -130,20 +156,19 @@ private function init ()
130156 */
131157 private function getCoordinates ($ elementId )
132158 {
133- $ webDriver = $ this ->getModule ("WebDriver " )->webDriver ;
134159 if (is_null ($ elementId )) {
135160 $ elementId = 'body ' ;
136161 }
137162
138163 $ jQueryString = file_get_contents (__DIR__ . "/jquery.js " );
139- $ webDriver ->executeScript ($ jQueryString );
140- $ webDriver ->executeScript ('jQuery.noConflict(); ' );
164+ $ this -> webDriver ->executeScript ($ jQueryString );
165+ $ this -> webDriver ->executeScript ('jQuery.noConflict(); ' );
141166
142167 $ imageCoords = array ();
143- $ imageCoords ['offset_x ' ] = (string ) $ webDriver ->executeScript ('var element = jQuery( " ' . $ elementId . '" );var offset = element.offset();return offset.left; ' );
144- $ imageCoords ['offset_y ' ] = (string ) $ webDriver ->executeScript ('var element = jQuery( " ' . $ elementId . '" );var offset = element.offset();return offset.top; ' );
145- $ imageCoords ['width ' ] = (string ) $ webDriver ->executeScript ('var element = jQuery( " ' . $ elementId . '" );return element.width(); ' );
146- $ imageCoords ['height ' ] = (string ) $ webDriver ->executeScript ('var element = jQuery( " ' . $ elementId . '" );return element.height(); ' );
168+ $ imageCoords ['offset_x ' ] = (string ) $ this -> webDriver ->executeScript ('var element = jQuery( " ' . $ elementId . '" );var offset = element.offset();return offset.left; ' );
169+ $ imageCoords ['offset_y ' ] = (string ) $ this -> webDriver ->executeScript ('var element = jQuery( " ' . $ elementId . '" );var offset = element.offset();return offset.top; ' );
170+ $ imageCoords ['width ' ] = (string ) $ this -> webDriver ->executeScript ('var element = jQuery( " ' . $ elementId . '" );return element.width(); ' );
171+ $ imageCoords ['height ' ] = (string ) $ this -> webDriver ->executeScript ('var element = jQuery( " ' . $ elementId . '" );return element.height(); ' );
147172
148173 return $ imageCoords ;
149174 }
@@ -167,6 +192,7 @@ private function getScreenshotName ($identifier)
167192 *
168193 * @param string $identifier identifies your test object
169194 * @return string Path an name of the image file
195+ * @throws \RuntimeException if debug dir could not create
170196 */
171197 private function getScreenshotPath ($ identifier )
172198 {
@@ -198,17 +224,24 @@ private function getExpectedScreenshotPath ($identifier)
198224 *
199225 * @param string $identifier identifies your test object
200226 * @param array $coords Coordinates where the DOM element is located
227+ * @param array $excludeElements List of elements, which should not appear in the screenshot
201228 * @return string Path of the current screenshot image
202229 */
203- private function createScreenshot ($ identifier , array $ coords )
230+ private function createScreenshot ($ identifier , array $ coords, array $ excludeElements = array () )
204231 {
205- $ webDriverModule = $ this ->getModule ("WebDriver " );
206- $ webDriver = $ webDriverModule ->webDriver ;
207-
208232 $ screenshotPath = \Codeception \Configuration::logDir () . 'debug/ ' . "fullscreenshot.tmp.png " ;
209233 $ elementPath = $ this ->getScreenshotPath ($ identifier );
210234
211- $ webDriver ->takeScreenshot ($ screenshotPath );
235+ // exclude Elements here
236+ if (false !== reset ($ excludeElements )) {
237+ $ this ->hideElementsForScreenshot ($ excludeElements );
238+ }
239+
240+ $ this ->webDriver ->takeScreenshot ($ screenshotPath );
241+
242+ if (false !== reset ($ excludeElements )) {
243+ $ this ->resetHideElementsForScreenshot ($ excludeElements );
244+ }
212245
213246 $ screenShotImage = new \Imagick ();
214247 $ screenShotImage ->readImage ($ screenshotPath );
@@ -220,6 +253,34 @@ private function createScreenshot ($identifier, array $coords)
220253 return $ elementPath ;
221254 }
222255
256+ /**
257+ * Hide the given elements with CSS visibility = hidden. Wait a second after hiding
258+ *
259+ * @param array $excludeElements Array of strings, which should be not visible
260+ */
261+ private function hideElementsForScreenshot (array $ excludeElements )
262+ {
263+ foreach ($ excludeElements as $ element ) {
264+ $ this ->webDriver ->executeScript ('var element = jQuery( " ' .$ element .'" ).css("visibility","hidden"); ' );
265+ $ this ->debug ("set visibility of element ' $ element' to 'hidden' " );
266+ }
267+ $ this ->webDriverModule ->wait (1 );
268+ }
269+
270+ /**
271+ * Reset hiding the given elements with CSS visibility = visible. Wait a second after reset hiding
272+ *
273+ * @param array $excludeElements array of strings, which should be visible again
274+ */
275+ private function resetHideElementsForScreenshot (array $ excludeElements )
276+ {
277+ foreach ($ excludeElements as $ element ) {
278+ $ this ->webDriver ->executeScript ('var element = jQuery( " ' .$ element .'" ).css("visibility","visible"); ' );
279+ $ this ->debug ("set visibility of element ' $ element' to 'visible' " );
280+ }
281+ $ this ->webDriverModule ->wait (1 );
282+ }
283+
223284 /**
224285 * Returns the image path including the filename of a deviation image
225286 *
0 commit comments