diff --git a/readme.md b/readme.md index 566da41..164b59d 100644 --- a/readme.md +++ b/readme.md @@ -67,6 +67,7 @@ modules: * **report** (default: `false`) When enabled an HTML report with diffs for failing tests is generated. Report is stored in `tests/_output/vcresult.html`. * **module** (default: `'WebDriver'`) module responsible for browser interaction, default: WebDriver. * **fullScreenShot** (default: `false`) fullpage screenshot for Chrome and Firefox +* **downscalePixelRatio** (default: `false`) automatically downscales screenshots to the pixel ratio "1". This can be helpful if you or your team are running the test on devices with different pixel densities. When this feature is enabled, screenshots from devices with higher pixel densities are automatically resized to provide more comparable images. Please note that scaled images will never be absolutely identical to the original, you need to set "maxiumDeviation" carefully if you want to pass your tests. ## Usage diff --git a/src/Codeception/Module/VisualCeption.php b/src/Codeception/Module/VisualCeption.php index e68dc94..78a6995 100755 --- a/src/Codeception/Module/VisualCeption.php +++ b/src/Codeception/Module/VisualCeption.php @@ -36,6 +36,7 @@ class VisualCeption extends CodeceptionModule implements MultiSession 'module' => 'WebDriver', 'fullScreenShot' => false, 'forceFullScreenShot' => false, + 'downscalePixelRatio' => false, ]; /** @@ -471,9 +472,9 @@ private function createScreenshot($identifier, array $coords, array $excludeElem $this->hideElementsForScreenshot($excludeElements); + [$viewportHeight, $devicePixelRatio] = $this->webDriver->executeScript("return [window.innerHeight, window.devicePixelRatio]"); if ($this->config["fullScreenShot"] === true || $this->config["forceFullScreenShot"] === true) { $height = $this->webDriver->executeScript("var ele=document.querySelector('html'); return ele.scrollHeight;"); - list($viewportHeight, $devicePixelRatio) = $this->webDriver->executeScript("return [window.innerHeight, window.devicePixelRatio]"); $itr = $height / $viewportHeight; @@ -495,6 +496,7 @@ private function createScreenshot($identifier, array $coords, array $excludeElem if ($this->config["fullScreenShot"] !== true) { $fullShot->cropImage((int)$coords['width'], (int)$coords['height'], (int)$coords['offset_x'], (int)$coords['offset_y']); } + $this->downscaleImage($fullShot, $devicePixelRatio); $fullShot->writeImage($elementPath); $this->webDriver->executeScript("window.scrollTo(0, 0);"); @@ -503,7 +505,13 @@ private function createScreenshot($identifier, array $coords, array $excludeElem $screenshotBinary = $this->webDriver->takeScreenshot(); $screenShotImage->readimageblob($screenshotBinary); - $screenShotImage->cropImage((int)$coords['width'], (int)$coords['height'], (int)$coords['offset_x'], (int)$coords['offset_y']); + $screenShotImage->cropImage( + (int)$coords['width'] * $devicePixelRatio, + (int)$coords['height'] * $devicePixelRatio, + (int)$coords['offset_x'] * $devicePixelRatio, + (int)$coords['offset_y'] * $devicePixelRatio + ); + $this->downscaleImage($screenShotImage, $devicePixelRatio); $screenShotImage->writeImage($elementPath); } @@ -512,6 +520,22 @@ private function createScreenshot($identifier, array $coords, array $excludeElem return $elementPath; } + /** + * Downscale image + * + * @param \Imagick $image + * @param float|int $downscaleFactor + * @return void + */ + private function downscaleImage(\Imagick $image, $downscaleFactor): void + { + if ($downscaleFactor > 1 && $this->config['downscalePixelRatio']) { + $newWidth = (int)($image->getImageWidth() / $downscaleFactor); + $newHeight = (int)($image->getImageHeight() / $downscaleFactor); + $image->scaleImage($newWidth, $newHeight); + } + } + /** * Hide the given elements with CSS visibility = hidden. Wait a second after hiding *