Skip to content

Commit 6fed121

Browse files
author
Neubert, Sebastian
committed
add excluding function to screenshot module and some improvements.
1 parent 9b2d58a commit 6fed121

File tree

2 files changed

+106
-35
lines changed

2 files changed

+106
-35
lines changed

module/VisualCeption.php

Lines changed: 96 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,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
*

test/integration/tests/acceptance/TimeComparisonCest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,14 @@ public function dontSeeVisualChanges (WebGuy $I, $scenario)
2626
$I->dontSeeVisualChanges("block", "#theblock");
2727
}
2828

29+
public function dontSeeVisualChangesAndHideElement (WebGuy $I, $scenario)
30+
{
31+
$I->amOnPage("/VisualCeption/seeVisualChanges.php");
32+
$I->dontSeeVisualChanges("body", "body", "#theblock");
33+
34+
// the test has to be called twice for comparison on the travis server
35+
$I->amOnPage("/VisualCeption/seeVisualChanges.php");
36+
$I->dontSeeVisualChanges("body", "body", "#theblock");
37+
}
38+
2939
}

0 commit comments

Comments
 (0)