Skip to content

Commit 9546819

Browse files
author
Nils Langner
committed
Merge pull request #27 from sebastianneubert/master
add excluding function to screenshot module and some improvements.
2 parents e1dbcfd + a37715d commit 9546819

File tree

2 files changed

+137
-36
lines changed

2 files changed

+137
-36
lines changed

module/VisualCeption.php

Lines changed: 113 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -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
*

test/integration/tests/acceptance/TimeComparisonCest.php

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,27 @@ public function dontSeeVisualChanges (WebGuy $I, $scenario)
3030
$I->dontSeeVisualChanges("block2", "#theblock");
3131
}
3232

33-
}
33+
public function seeVisualChangesAndHideElement (WebGuy $I, $scenario)
34+
{
35+
$I->amOnPage("/VisualCeption/seeVisualChanges.php");
36+
$I->seeVisualChanges("hideTheIntro", "body", "#intro");
37+
38+
$I->wait(1);
39+
40+
// the test has to be called twice for comparison on the travis server
41+
$I->amOnPage("/VisualCeption/seeVisualChanges.php");
42+
$I->seeVisualChanges("hideTheIntro", "body", array("#intro"));
43+
}
44+
45+
public function dontSeeVisualChangesAndHideElement (WebGuy $I, $scenario)
46+
{
47+
$I->amOnPage("/VisualCeption/seeVisualChanges.php");
48+
$I->dontSeeVisualChanges("hideTheBlock", "body", "#theblock");
49+
50+
$I->wait(1);
51+
52+
// the test has to be called twice for comparison on the travis server
53+
$I->amOnPage("/VisualCeption/seeVisualChanges.php");
54+
$I->dontSeeVisualChanges("hideTheBlock", "body", array("#theblock"));
55+
}
56+
}

0 commit comments

Comments
 (0)