Skip to content

Commit f0a8c5f

Browse files
committed
Initial commit
0 parents  commit f0a8c5f

File tree

4 files changed

+163
-0
lines changed

4 files changed

+163
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.gitattributes
2+
vendor
3+
.idea

README.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Laravel Dusk Visual Assert
2+
3+
This package adds assertions to compare screenshots taken during [Laravel Dusk](https://laravel.com/docs/10.x/dusk#taking-a-screenshot) tests using the Imagick extension.
4+
5+
## Installation
6+
7+
You can install the package via composer:
8+
9+
```bash
10+
composer require --dev rossjcooper/laravel-dusk-visual-assert
11+
```
12+
13+
## Usage
14+
15+
The Dusk Browser class now has access to some new methods:
16+
17+
### assertScreenshot()
18+
19+
This method will take a screenshot of the current page and compare it to a reference image (generated the first time the test is run).
20+
21+
If the images are different, the test will fail and save the image diff so you can inspect the differences.
22+
23+
```php
24+
$browser->assertScreenshot(string $name, float $threshold = 0.0001, int $metric = Imagick::METRIC_MEANSQUAREERROR)
25+
```
26+
27+
Example:
28+
29+
```php
30+
$this->browse(function (Browser $browser) {
31+
$browser->visit('/')
32+
->assertScreenshot('home');
33+
});
34+
```
35+
36+
### assertResponsiveScreenshots()
37+
38+
This method is similar to the `assertScreenshot` as above but it screenshots the page at different screen sizes.
39+
40+
```php
41+
$browser->assertResponsiveScreenshots(string $name, float $threshold = 0.0001, int $metric = Imagick::METRIC_MEANSQUAREERROR)
42+
```
43+
44+
Example:
45+
46+
```php
47+
$this->browse(function (Browser $browser) {
48+
$browser->visit('/')
49+
->assertResponsiveScreenshots('home');
50+
});
51+
```
52+
53+
## Updating reference images
54+
55+
If you want to update the reference images simply delete them from the `tests/Browser/screenshots` directory and re-run your tests to generate new ones.
56+
57+
I would recommend committing the reference images to your repository so you can track changes to them over time.

composer.json

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
{
2+
"name": "rossjcooper/laravel-dusk-visual-assert",
3+
"description": "Adds assertions to compare screenshots taken during Laravel Dusk tests",
4+
"keywords": [
5+
"laravel",
6+
"dusk",
7+
"visual",
8+
"assert",
9+
"screenshot",
10+
"image",
11+
"comparison",
12+
"regression"
13+
],
14+
"version": "1.0.0",
15+
"type": "library",
16+
"license": "MIT",
17+
"autoload": {
18+
"psr-4": {
19+
"Rossjcooper\\LaravelDuskVisualAssert\\": "src/"
20+
}
21+
},
22+
"authors": [
23+
{
24+
"name": "Ross Cooper",
25+
"email": "[email protected]"
26+
}
27+
],
28+
"require-dev": {
29+
"ext-imagick": "*",
30+
"laravel/dusk": "^7"
31+
},
32+
"extra": {
33+
"laravel": {
34+
"providers": [
35+
"Rossjcooper\\LaravelDuskVisualAssert\\ServiceProvider"
36+
]
37+
}
38+
}
39+
}

src/ServiceProvider.php

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?php
2+
3+
namespace Rossjcooper\LaravelDuskVisualAssert;
4+
5+
use Imagick;
6+
use Laravel\Dusk\Browser;
7+
use PHPUnit\Framework\Assert;
8+
9+
class ServiceProvider extends \Illuminate\Support\ServiceProvider
10+
{
11+
public function boot()
12+
{
13+
Browser::macro('assertScreenshot', function (string $name, float $threshold = 0.0001, int $metric = Imagick::METRIC_MEANSQUAREERROR) {
14+
/** @var Browser $this */
15+
16+
$filePath = sprintf('%s/%s.png', rtrim(Browser::$storeScreenshotsAt, '/'), $name);
17+
18+
$diffName = sprintf('%s-diff', $name);
19+
$diffFilePath = sprintf('%s/diffs/%s.png', rtrim(Browser::$storeScreenshotsAt, '/'), $diffName);
20+
21+
$directoryPath = dirname($filePath);
22+
23+
if (! is_dir($directoryPath)) {
24+
mkdir($directoryPath, 0777, true);
25+
}
26+
27+
if (! file_exists($filePath)) {
28+
$this->driver->takeScreenshot($filePath);
29+
}
30+
31+
$this->driver->takeScreenshot($diffFilePath);
32+
33+
$originalImage = new Imagick($filePath);
34+
$diffImage = new Imagick($diffFilePath);
35+
36+
$result = $originalImage->compareImages($diffImage, $metric);
37+
38+
if ($result[1] > $threshold) {
39+
$result[0]->setImageFormat("png");
40+
$result[0]->writeImage($diffFilePath);
41+
} else {
42+
unlink($diffFilePath);
43+
}
44+
45+
Assert::assertLessThanOrEqual($threshold, $result[1], sprintf('Screenshots are not the same. Difference can be viewed at: %s', $diffFilePath));
46+
47+
return $this;
48+
});
49+
50+
Browser::macro('assertResponsiveScreenshots', function (string $name, float $threshold = 0.0001, int $metric = Imagick::METRIC_MEANSQUAREERROR) {
51+
if (substr($name, -1) !== '/') {
52+
$name .= '-';
53+
}
54+
55+
foreach (Browser::$responsiveScreenSizes as $device => $size) {
56+
$this->resize($size['width'], $size['height'])
57+
->assertScreenshot("$name$device");
58+
}
59+
60+
return $this;
61+
});
62+
}
63+
64+
}

0 commit comments

Comments
 (0)