Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE] Improve support for pixel ratio > 1 #80

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
28 changes: 26 additions & 2 deletions src/Codeception/Module/VisualCeption.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class VisualCeption extends CodeceptionModule implements MultiSession
'module' => 'WebDriver',
'fullScreenShot' => false,
'forceFullScreenShot' => false,
'downscalePixelRatio' => false,
];

/**
Expand Down Expand Up @@ -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;

Expand All @@ -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);");
Expand All @@ -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);
}

Expand All @@ -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
*
Expand Down