@@ -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,31 @@ 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 );
52-
53- unlink ($ this ->getScreenshotPath ($ identifier ));
46+ $ this ->webDriverModule = $ this ->getModule ("WebDriver " );
47+ $ this ->webDriver = $ this ->webDriverModule ->webDriver ;
5448
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+ $ excludeElements = (array ) $ excludeElements ;
63+
64+ $ deviationResult = $ this ->getDeviation ($ identifier , $ elementID , $ excludeElements );
65+
7066 if (! is_null ($ deviationResult ["deviationImage " ])) {
71- if ($ deviationResult ["deviation " ] > $ this ->maximumDeviation ) {
67+ if ($ deviationResult ["deviation " ] <= $ this ->maximumDeviation ) {
7268 $ compareScreenshotPath = $ this ->getDeviationScreenshotPath ($ identifier );
7369 $ 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. " );
70+ $ this ->assertTrue (false , "The deviation of the taken screenshot is too low ( " . $ deviationResult ["deviation " ] . "%). \nSee $ compareScreenshotPath for a deviation screenshot. " );
7571 }
7672 }
7773 }
@@ -82,19 +78,75 @@ public function dontSeeVisualChanges ($identifier, $elementID = null)
8278 *
8379 * @param string $identifier identifies your test object
8480 * @param string $elementID DOM ID of the element, which should be screenshotted
81+ * @param string|array $excludeElements string of Element name or array of Element names, which should not appear in the screenshot
8582 */
86- public function seeVisualChanges ($ identifier , $ elementID = null )
83+ public function dontSeeVisualChanges ($ identifier , $ elementID = null , $ excludeElements = array () )
8784 {
88- $ deviationResult = $ this ->getDeviation ($ identifier , $ elementID );
85+ $ excludeElements = (array ) $ excludeElements ;
86+
87+ $ deviationResult = $ this ->getDeviation ($ identifier , $ elementID , $ excludeElements );
88+
8989 if (! is_null ($ deviationResult ["deviationImage " ])) {
90- if ($ deviationResult ["deviation " ] <= $ this ->maximumDeviation ) {
90+ if ($ deviationResult ["deviation " ] > $ this ->maximumDeviation ) {
9191 $ compareScreenshotPath = $ this ->getDeviationScreenshotPath ($ identifier );
9292 $ 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. " );
93+ $ this ->assertTrue (false , "The deviation of the taken screenshot is too high ( " . $ deviationResult ["deviation " ] . "%). \nSee $ compareScreenshotPath for a deviation screenshot. " );
9494 }
9595 }
9696 }
9797
98+ /**
99+ * Hide an element to set the visibility to hidden
100+ *
101+ * @param $elementSelector String of jQuery Element selector, set visibility to hidden
102+ */
103+ public function hideElement ($ elementSelector )
104+ {
105+ $ this ->webDriver ->executeScript ('
106+ if( jQuery(" ' .$ elementSelector .'").length > 0 ) {
107+ jQuery( " ' .$ elementSelector .'" ).css("visibility","hidden");
108+ }
109+ ' );
110+ $ this ->debug ("set visibility of element ' $ elementSelector' to 'hidden' " );
111+ }
112+
113+ /**
114+ * Show an element to set the visibility to visible
115+ *
116+ * @param $elementSelector String of jQuery Element selector, set visibility to visible
117+ */
118+ public function showElement ($ elementSelector )
119+ {
120+ $ this ->webDriver ->executeScript ('
121+ if( jQuery(" ' .$ elementSelector .'").length > 0 ) {
122+ jQuery( " ' .$ elementSelector .'" ).css("visibility","visible");
123+ }
124+ ' );
125+ $ this ->debug ("set visibility of element ' $ elementSelector' to 'visible' " );
126+ }
127+
128+ /**
129+ * Compares the two images and calculate the deviation between expected and actual image
130+ *
131+ * @param $identifier Identifies your test object
132+ * @param $elementID DOM ID of the element, which should be screenshotted
133+ * @param array $excludeElements Element names, which should not appear in the screenshot
134+ * @return array Includes the calculation of deviation in percent and the diff-image
135+ */
136+ private function getDeviation ($ identifier , $ elementID , array $ excludeElements = array ())
137+ {
138+ $ coords = $ this ->getCoordinates ($ elementID );
139+ $ this ->createScreenshot ($ identifier , $ coords , $ excludeElements );
140+
141+ $ compareResult = $ this ->compare ($ identifier );
142+
143+ unlink ($ this ->getScreenshotPath ($ identifier ));
144+
145+ $ deviation = round ($ compareResult [1 ] * 100 , 2 );
146+ $ this ->debug ("The deviation between the images is " . $ deviation . " percent " );
147+ return array ("deviation " => $ deviation , "deviationImage " => $ compareResult [0 ]);
148+ }
149+
98150 /**
99151 * Initialize the module and read the config.
100152 * Throws a runtime exception, if the
@@ -130,20 +182,19 @@ private function init ()
130182 */
131183 private function getCoordinates ($ elementId )
132184 {
133- $ webDriver = $ this ->getModule ("WebDriver " )->webDriver ;
134185 if (is_null ($ elementId )) {
135186 $ elementId = 'body ' ;
136187 }
137188
138189 $ jQueryString = file_get_contents (__DIR__ . "/jquery.js " );
139- $ webDriver ->executeScript ($ jQueryString );
140- $ webDriver ->executeScript ('jQuery.noConflict(); ' );
190+ $ this -> webDriver ->executeScript ($ jQueryString );
191+ $ this -> webDriver ->executeScript ('jQuery.noConflict(); ' );
141192
142193 $ 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(); ' );
194+ $ imageCoords ['offset_x ' ] = (string ) $ this -> webDriver ->executeScript ('return jQuery( " ' . $ elementId . '" ).offset().left; ' );
195+ $ imageCoords ['offset_y ' ] = (string ) $ this -> webDriver ->executeScript ('return jQuery( " ' . $ elementId . '" ).offset().top; ' );
196+ $ imageCoords ['width ' ] = (string ) $ this -> webDriver ->executeScript ('return jQuery( " ' . $ elementId . '" ).width(); ' );
197+ $ imageCoords ['height ' ] = (string ) $ this -> webDriver ->executeScript ('return jQuery( " ' . $ elementId . '" ).height(); ' );
147198
148199 return $ imageCoords ;
149200 }
@@ -172,6 +223,7 @@ private function getScreenshotName ($identifier)
172223 *
173224 * @param string $identifier identifies your test object
174225 * @return string Path an name of the image file
226+ * @throws \RuntimeException if debug dir could not create
175227 */
176228 private function getScreenshotPath ($ identifier )
177229 {
@@ -203,17 +255,17 @@ private function getExpectedScreenshotPath ($identifier)
203255 *
204256 * @param string $identifier identifies your test object
205257 * @param array $coords Coordinates where the DOM element is located
258+ * @param array $excludeElements List of elements, which should not appear in the screenshot
206259 * @return string Path of the current screenshot image
207260 */
208- private function createScreenshot ($ identifier , array $ coords )
261+ private function createScreenshot ($ identifier , array $ coords, array $ excludeElements = array () )
209262 {
210- $ webDriverModule = $ this ->getModule ("WebDriver " );
211- $ webDriver = $ webDriverModule ->webDriver ;
212-
213263 $ screenshotPath = \Codeception \Configuration::logDir () . 'debug/ ' . "fullscreenshot.tmp.png " ;
214264 $ elementPath = $ this ->getScreenshotPath ($ identifier );
215265
216- $ webDriver ->takeScreenshot ($ screenshotPath );
266+ $ this ->hideElementsForScreenshot ($ excludeElements );
267+ $ this ->webDriver ->takeScreenshot ($ screenshotPath );
268+ $ this ->resetHideElementsForScreenshot ($ excludeElements );
217269
218270 $ screenShotImage = new \Imagick ();
219271 $ screenShotImage ->readImage ($ screenshotPath );
@@ -225,6 +277,32 @@ private function createScreenshot ($identifier, array $coords)
225277 return $ elementPath ;
226278 }
227279
280+ /**
281+ * Hide the given elements with CSS visibility = hidden. Wait a second after hiding
282+ *
283+ * @param array $excludeElements Array of strings, which should be not visible
284+ */
285+ private function hideElementsForScreenshot (array $ excludeElements )
286+ {
287+ foreach ($ excludeElements as $ element ) {
288+ $ this ->hideElement ($ element );
289+ }
290+ $ this ->webDriverModule ->wait (1 );
291+ }
292+
293+ /**
294+ * Reset hiding the given elements with CSS visibility = visible. Wait a second after reset hiding
295+ *
296+ * @param array $excludeElements array of strings, which should be visible again
297+ */
298+ private function resetHideElementsForScreenshot (array $ excludeElements )
299+ {
300+ foreach ($ excludeElements as $ element ) {
301+ $ this ->showElement ($ element );
302+ }
303+ $ this ->webDriverModule ->wait (1 );
304+ }
305+
228306 /**
229307 * Returns the image path including the filename of a deviation image
230308 *
0 commit comments