From 82ab4eb2ccdfa8b4c6cf5ffe24a9a5cb9082cb19 Mon Sep 17 00:00:00 2001 From: Hugo Heneault Date: Tue, 21 Oct 2025 10:16:49 +0200 Subject: [PATCH 01/10] Allow elements asserting --- README.md | 146 +++++++++++++++++++++++++++--- config/visual-assert.php | 15 ++++ src/ServiceProvider.php | 186 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 334 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index d94291c..7a92837 100644 --- a/README.md +++ b/README.md @@ -18,28 +18,48 @@ Publish the config file to control default settings: php artisan vendor:publish --tag=visual-assert-config ``` - ## Usage The Dusk Browser class now has access to some new methods: ### assertScreenshot() -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). +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). If the images are different, the test will fail and save the image diff so you can inspect the differences. ```php -$browser->assertScreenshot(string $name, float|null $threshold = null, int|null $metric = null) +$browser->assertScreenshot(string $name, float|null $threshold = null, int|null $metric = null, int|null $width = null, int|null $height = null) ``` -Example: +Example: ```php $this->browse(function (Browser $browser) { - $browser->visit('/') - ->assertScreenshot('home'); - }); + $browser->visit('/') + ->assertScreenshot('home'); +}); +``` + +### assertElementScreenshot() + +Take a screenshot of a specific element and compare it to a reference image. Perfect for testing individual components without worrying about the rest of the page. + +```php +$browser->assertElementScreenshot(string $selector, string $name, float|null $threshold = null, int|null $metric = null) +``` + +Example: + +```php +$this->browse(function (Browser $browser) { + $browser->visit('/login') + // Test that the login form hasn't changed + ->assertElementScreenshot('#login-form', 'login-form') + + // Test header with custom threshold + ->assertElementScreenshot('header', 'header', 0.02); +}); ``` ### assertResponsiveScreenshots() @@ -54,9 +74,115 @@ Example: ```php $this->browse(function (Browser $browser) { - $browser->visit('/') - ->assertResponsiveScreenshots('home'); - }); + $browser->visit('/') + ->assertResponsiveScreenshots('home'); +}); +``` + +### assertResponsiveElementScreenshots() + +Test an element at different responsive breakpoints. + +```php +$browser->assertResponsiveElementScreenshots(string $selector, string $name, float|null $threshold = null, int|null $metric = null) +``` + +Example: + +```php +$this->browse(function (Browser $browser) { + $browser->visit('/products') + // Test product grid at different screen sizes + ->assertResponsiveElementScreenshots('.product-grid', 'product-grid'); +}); +``` + +### assertElementsScreenshots() + +Test multiple elements at once by providing an array of selectors and names. + +```php +$browser->assertElementsScreenshots(array $elements, float|null $threshold = null, int|null $metric = null) +``` + +Example: + +```php +$this->browse(function (Browser $browser) { + $browser->visit('/dashboard') + ->assertElementsScreenshots([ + '#sidebar' => 'dashboard-sidebar', + '.user-profile' => 'user-profile-card', + '#main-content' => 'main-content-area', + ]); +}); +``` + +### assertScreenshotWithoutFixed() + +Take a screenshot with fixed elements (like sticky headers, chat widgets, cookie banners) automatically hidden. + +```php +$browser->assertScreenshotWithoutFixed(string $name, array|null $selectorsToHide = null, float|null $threshold = null, int|null $metric = null, int|null $width = null, int|null $height = null) +``` + +Example: + +```php +$this->browse(function (Browser $browser) { + $browser->visit('/') + // Uses default selectors from config + ->assertScreenshotWithoutFixed('homepage-clean') + + // Hide specific elements + ->assertScreenshotWithoutFixed('homepage-custom', [ + '.chat-widget', + '#cookie-banner', + '.sticky-nav' + ]); +}); +``` + +### assertElementScreenshotWithoutFixed() + +Take an element screenshot with fixed elements hidden. + +```php +$browser->assertElementScreenshotWithoutFixed(string $selector, string $name, array|null $selectorsToHide = null, float|null $threshold = null, int|null $metric = null) +``` + +Example: + +```php +$this->browse(function (Browser $browser) { + $browser->visit('/products') + ->assertElementScreenshotWithoutFixed( + '.product-grid', + 'products-no-overlay', + ['.promo-popup', '.flash-sale-banner'] + ); +}); +``` + +### withoutFixedElements() + +Temporarily hide fixed elements for multiple operations. + +```php +$browser->withoutFixedElements(callable $callback, array|null $selectors = null) +``` + +Example: + +```php +$this->browse(function (Browser $browser) { + $browser->visit('/dashboard') + ->withoutFixedElements(function ($browser) { + return $browser + ->assertScreenshot('dashboard-clean') + ->assertElementScreenshot('#charts', 'charts-clean'); + }, ['.fixed']); +}); ``` ## Updating reference images diff --git a/config/visual-assert.php b/config/visual-assert.php index c1810ff..e1266de 100644 --- a/config/visual-assert.php +++ b/config/visual-assert.php @@ -13,4 +13,19 @@ 'default_metric' => \Imagick::METRIC_MEANSQUAREERROR, 'skip_if_different_window_size' => false, + + /** + * Skip assertion if element sizes don't match (for element screenshots) + * If true, the test will pass without comparison when element dimensions differ + * If false, the test will fail when element dimensions differ + */ + 'skip_if_different_element_size' => false, + + /** + * CSS selectors for fixed elements to hide during screenshots + */ + 'fixed_elements_to_hide' => [ + '.fixed', + '.sticky', + ], ]; \ No newline at end of file diff --git a/src/ServiceProvider.php b/src/ServiceProvider.php index ce5e096..db19b85 100644 --- a/src/ServiceProvider.php +++ b/src/ServiceProvider.php @@ -1,5 +1,4 @@ screenshotElement($selector, $name); + + // Move the screenshot to the references folder + $defaultPath = sprintf('%s/%s.png', rtrim(Browser::$storeScreenshotsAt, '/'), $name); + if (file_exists($defaultPath)) { + rename($defaultPath, $filePath); + } + + Assert::assertTrue(true, 'Reference element screenshot stored successfully.'); + return $this; + } + + // Take current element screenshot for comparison + $this->screenshotElement($selector, 'temp/' . $name); + + // Compare images + $originalImage = new Imagick($filePath); + $currentImage = new Imagick($tempFilePath); + + if ( + $originalImage->getImageWidth() !== $currentImage->getImageWidth() + || $originalImage->getImageHeight() !== $currentImage->getImageHeight() + ) { + // Clean up temp file + unlink($tempFilePath); + + if (config('visual-assert.skip_if_different_element_size', false)) { + return $this; + } + + Assert::assertTrue(false, sprintf('Element screenshots are not the same size. The element may have changed dimensions.')); + return $this; + } + + $result = $originalImage->compareImages($currentImage, $metric); + + // If there's a difference above threshold, save the diff + if ($result[1] > $threshold) { + // Move temp file to diff folder + rename($tempFilePath, $diffFilePath); + + // Also create a visual diff image + $visualDiffPath = sprintf('%s/diffs/%s-visual.png', rtrim(Browser::$storeScreenshotsAt, '/'), $name); + $result[0]->setImageFormat("png"); + $result[0]->writeImage($visualDiffPath); + + Assert::assertLessThanOrEqual($threshold, $result[1], sprintf('Element screenshots are not the same. Difference can be viewed at: %s and visual diff at: %s', $diffFilePath, $visualDiffPath)); + } else { + // Clean up temp file + unlink($tempFilePath); + Assert::assertLessThanOrEqual($threshold, $result[1], 'Element screenshots match within threshold.'); + } + + return $this; + }); + Browser::macro('assertResponsiveScreenshots', function (string $name, float|null $threshold = null, int|null $metric = null) { /** @var Browser $this */ $threshold = $threshold ?? config('visual-assert.default_threshold'); @@ -89,6 +174,102 @@ public function boot(): void return $this; }); + + // Responsive element screenshots macro + Browser::macro('assertResponsiveElementScreenshots', function (string $selector, string $name, float|null $threshold = null, int|null $metric = null) { + /** @var Browser $this */ + $threshold = $threshold ?? config('visual-assert.default_threshold'); + $metric = $metric ?? config('visual-assert.default_metric'); + + if (substr($name, -1) !== '/') { + $name .= '-'; + } + + foreach (Browser::$responsiveScreenSizes as $device => $size) { + // Resize window for responsive testing + $this->resize($size['width'], $size['height']); + + // Take element screenshot at this size + $this->assertElementScreenshot($selector, "$name$device", $threshold, $metric); + } + + return $this; + }); + + // Helper macro to assert multiple elements at once + Browser::macro('assertElementsScreenshots', function (array $elements, float|null $threshold = null, int|null $metric = null) { + /** @var Browser $this */ + $threshold = $threshold ?? config('visual-assert.default_threshold'); + $metric = $metric ?? config('visual-assert.default_metric'); + + foreach ($elements as $selector => $name) { + $this->assertElementScreenshot($selector, $name, $threshold, $metric); + } + + return $this; + }); + + // Macro to hide fixed/sticky elements before taking screenshots + Browser::macro('withoutFixedElements', function (callable $callback, array $selectors = null) { + /** @var Browser $this */ + + // Use default selectors if none provided + $selectorsToHide = $selectors ?? config('visual-assert.fixed_elements_to_hide', []); + + // Build CSS to hide fixed elements + $cssRules = []; + + // Add custom selectors + foreach ($selectorsToHide as $selector) { + $cssRules[] = "{$selector} { display: none !important; }"; + } + + // Inject CSS to hide elements + $styleId = 'visual-assert-hide-fixed-' . uniqid(); + $css = implode(' ', $cssRules); + + if (!empty($css)) { + $this->script(" + var style = document.createElement('style'); + style.id = '{$styleId}'; + style.innerHTML = `{$css}`; + document.head.appendChild(style); + "); + } + + try { + // Execute the callback (take screenshots, etc.) + $result = $callback($this); + } finally { + // Always restore by removing the injected CSS + if (!empty($css)) { + $this->script(" + var style = document.getElementById('{$styleId}'); + if (style) { + style.remove(); + } + "); + } + } + + return $result ?? $this; + }); + + // Macro for screenshot without fixed elements + Browser::macro('assertScreenshotWithoutFixed', function (string $name, array $selectorsToHide = null, float|null $threshold = null, int|null $metric = null, int $width = null, int $height = null) { + /** @var Browser $this */ + return $this->withoutFixedElements(function ($browser) use ($name, $threshold, $metric, $width, $height) { + return $browser->assertScreenshot($name, $threshold, $metric, $width, $height); + }, $selectorsToHide); + }); + + // Macro for element screenshot without fixed elements + Browser::macro('assertElementScreenshotWithoutFixed', function (string $selector, string $name, array $selectorsToHide = null, float|null $threshold = null, int|null $metric = null) { + /** @var Browser $this */ + return $this->withoutFixedElements(function ($browser) use ($selector, $name, $threshold, $metric) { + return $browser->assertElementScreenshot($selector, $name, $threshold, $metric); + }, $selectorsToHide); + }); } public function register(): void @@ -97,5 +278,4 @@ public function register(): void __DIR__ . '/../config/visual-assert.php', 'visual-assert' ); } - -} +} \ No newline at end of file From c72602c3f03d157e72f92e91e6941abc9082c414 Mon Sep 17 00:00:00 2001 From: Hugo Heneault Date: Tue, 21 Oct 2025 10:19:02 +0200 Subject: [PATCH 02/10] v1.1.0 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 8e550b4..7d1e32f 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,7 @@ "comparison", "regression" ], - "version": "1.0.6", + "version": "1.1.0", "type": "library", "license": "MIT", "autoload": { From 31a166707f3bc248bdf0d779fc74c36c50e8fa7b Mon Sep 17 00:00:00 2001 From: Hugo Heneault Date: Tue, 21 Oct 2025 10:59:30 +0200 Subject: [PATCH 03/10] Log dimensions change when ref and current screenshot size don't match --- src/ServiceProvider.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/ServiceProvider.php b/src/ServiceProvider.php index db19b85..ee914b2 100644 --- a/src/ServiceProvider.php +++ b/src/ServiceProvider.php @@ -54,7 +54,7 @@ public function boot(): void if (config('visual-assert.skip_if_different_window_size', false)) { return $this; } - Assert::assertTrue(false, sprintf('Screenshots are not the same size, ensure the screenshots are taken using the same Dusk environment.')); + Assert::assertTrue(false, sprintf("Screenshots are not the same size (original: %dx%d, current: %dx%d). The browser window size may have changed between screenshots.")); return $this; } @@ -133,7 +133,12 @@ public function boot(): void return $this; } - Assert::assertTrue(false, sprintf('Element screenshots are not the same size. The element may have changed dimensions.')); + Assert::assertTrue(false, sprintf("Element screenshots are not the same size (original: %dx%d, current: %dx%d). The element may have changed dimensions.", + $originalImage->getImageWidth(), + $originalImage->getImageHeight(), + $currentImage->getImageWidth(), + $currentImage->getImageHeight() + )); return $this; } From ee1d027bd9e77ce55e1692d9e4aed0e0dc7549cf Mon Sep 17 00:00:00 2001 From: Hugo Heneault Date: Tue, 21 Oct 2025 11:00:31 +0200 Subject: [PATCH 04/10] v1.1.1 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 7d1e32f..15c5130 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,7 @@ "comparison", "regression" ], - "version": "1.1.0", + "version": "1.1.1", "type": "library", "license": "MIT", "autoload": { From b9dd4e2c96d9cac22c15a03c88f79f66a6b1eb67 Mon Sep 17 00:00:00 2001 From: Hugo Heneault Date: Tue, 21 Oct 2025 14:08:38 +0200 Subject: [PATCH 05/10] Store diff element screenshot even if dimensions changed --- src/ServiceProvider.php | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/src/ServiceProvider.php b/src/ServiceProvider.php index ee914b2..aaa0b16 100644 --- a/src/ServiceProvider.php +++ b/src/ServiceProvider.php @@ -87,7 +87,6 @@ public function boot(): void $filePath = sprintf('%s/references/%s.png', rtrim(Browser::$storeScreenshotsAt, '/'), $name); $diffName = sprintf('%s-diff', $name); $diffFilePath = sprintf('%s/diffs/%s.png', rtrim(Browser::$storeScreenshotsAt, '/'), $diffName); - $tempFilePath = sprintf('%s/temp/%s.png', rtrim(Browser::$storeScreenshotsAt, '/'), $name); // Create directories if they don't exist $directoryPath = dirname($filePath); @@ -95,11 +94,6 @@ public function boot(): void mkdir($directoryPath, 0777, true); } - $tempDirectoryPath = dirname($tempFilePath); - if (!is_dir($tempDirectoryPath)) { - mkdir($tempDirectoryPath, 0777, true); - } - // If no reference exists, create it if (!file_exists($filePath)) { // Use Dusk's built-in screenshotElement method @@ -115,29 +109,31 @@ public function boot(): void return $this; } + $diffName = sprintf('diffs/%s', $name); + // Take current element screenshot for comparison - $this->screenshotElement($selector, 'temp/' . $name); + $this->screenshotElement($selector, $diffName); + $diffFilePath = sprintf('%s/%s.png', rtrim(Browser::$storeScreenshotsAt, '/'), $diffName); + // Compare images $originalImage = new Imagick($filePath); - $currentImage = new Imagick($tempFilePath); + $currentImage = new Imagick($diffFilePath); if ( $originalImage->getImageWidth() !== $currentImage->getImageWidth() || $originalImage->getImageHeight() !== $currentImage->getImageHeight() ) { - // Clean up temp file - unlink($tempFilePath); - if (config('visual-assert.skip_if_different_element_size', false)) { return $this; } - Assert::assertTrue(false, sprintf("Element screenshots are not the same size (original: %dx%d, current: %dx%d). The element may have changed dimensions.", + Assert::assertTrue(false, sprintf("Element screenshots are not the same size (original: %dx%d, current: %dx%d). The element may have changed dimensions. Difference can be viewed at: %s", $originalImage->getImageWidth(), $originalImage->getImageHeight(), $currentImage->getImageWidth(), - $currentImage->getImageHeight() + $currentImage->getImageHeight(), + $diffFilePath )); return $this; } @@ -146,9 +142,6 @@ public function boot(): void // If there's a difference above threshold, save the diff if ($result[1] > $threshold) { - // Move temp file to diff folder - rename($tempFilePath, $diffFilePath); - // Also create a visual diff image $visualDiffPath = sprintf('%s/diffs/%s-visual.png', rtrim(Browser::$storeScreenshotsAt, '/'), $name); $result[0]->setImageFormat("png"); @@ -157,7 +150,6 @@ public function boot(): void Assert::assertLessThanOrEqual($threshold, $result[1], sprintf('Element screenshots are not the same. Difference can be viewed at: %s and visual diff at: %s', $diffFilePath, $visualDiffPath)); } else { // Clean up temp file - unlink($tempFilePath); Assert::assertLessThanOrEqual($threshold, $result[1], 'Element screenshots match within threshold.'); } From c4f4b1ae0019a786f12f430b8f802a09d349658e Mon Sep 17 00:00:00 2001 From: Hugo Heneault Date: Tue, 21 Oct 2025 14:16:04 +0200 Subject: [PATCH 06/10] v1.1.2 --- composer.json | 2 +- src/ServiceProvider.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 15c5130..028a7a9 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,7 @@ "comparison", "regression" ], - "version": "1.1.1", + "version": "1.1.2", "type": "library", "license": "MIT", "autoload": { diff --git a/src/ServiceProvider.php b/src/ServiceProvider.php index aaa0b16..2f0d275 100644 --- a/src/ServiceProvider.php +++ b/src/ServiceProvider.php @@ -115,7 +115,7 @@ public function boot(): void $this->screenshotElement($selector, $diffName); $diffFilePath = sprintf('%s/%s.png', rtrim(Browser::$storeScreenshotsAt, '/'), $diffName); - + // Compare images $originalImage = new Imagick($filePath); $currentImage = new Imagick($diffFilePath); From b7aaaf5338f7da77e8d586b7622f00d04f3db25f Mon Sep 17 00:00:00 2001 From: Hugo Heneault Date: Tue, 21 Oct 2025 21:28:50 +0200 Subject: [PATCH 07/10] Fix params order --- config/visual-assert.php | 5 ++--- src/ServiceProvider.php | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/config/visual-assert.php b/config/visual-assert.php index e1266de..bfa9ea3 100644 --- a/config/visual-assert.php +++ b/config/visual-assert.php @@ -6,10 +6,9 @@ 'screenshot_width' => 1920, 'screenshot_height' => 1080, - // For more info on how images are compared see // https://www.php.net/manual/en/imagick.compareimages.php - 'default_threshold' => 0.0001, + 'default_threshold' => 0.002, 'default_metric' => \Imagick::METRIC_MEANSQUAREERROR, 'skip_if_different_window_size' => false, @@ -28,4 +27,4 @@ '.fixed', '.sticky', ], -]; \ No newline at end of file +]; diff --git a/src/ServiceProvider.php b/src/ServiceProvider.php index 2f0d275..f8366fc 100644 --- a/src/ServiceProvider.php +++ b/src/ServiceProvider.php @@ -253,7 +253,7 @@ public function boot(): void }); // Macro for screenshot without fixed elements - Browser::macro('assertScreenshotWithoutFixed', function (string $name, array $selectorsToHide = null, float|null $threshold = null, int|null $metric = null, int $width = null, int $height = null) { + Browser::macro('assertScreenshotWithoutFixed', function (string $name, float|null $threshold = null, array $selectorsToHide = null, int|null $metric = null, int $width = null, int $height = null) { /** @var Browser $this */ return $this->withoutFixedElements(function ($browser) use ($name, $threshold, $metric, $width, $height) { return $browser->assertScreenshot($name, $threshold, $metric, $width, $height); @@ -261,7 +261,7 @@ public function boot(): void }); // Macro for element screenshot without fixed elements - Browser::macro('assertElementScreenshotWithoutFixed', function (string $selector, string $name, array $selectorsToHide = null, float|null $threshold = null, int|null $metric = null) { + Browser::macro('assertElementScreenshotWithoutFixed', function (string $selector, string $name, float|null $threshold = null, array $selectorsToHide = null, int|null $metric = null) { /** @var Browser $this */ return $this->withoutFixedElements(function ($browser) use ($selector, $name, $threshold, $metric) { return $browser->assertElementScreenshot($selector, $name, $threshold, $metric); From 882127ac1a317f4e279be6418656a73221a75f10 Mon Sep 17 00:00:00 2001 From: Hugo Heneault Date: Tue, 21 Oct 2025 21:29:04 +0200 Subject: [PATCH 08/10] 1.1.3 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 028a7a9..a87ae16 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,7 @@ "comparison", "regression" ], - "version": "1.1.2", + "version": "1.1.3", "type": "library", "license": "MIT", "autoload": { From 37548cccb06d7bea097d9a89e2626757e78068bc Mon Sep 17 00:00:00 2001 From: Hugo Heneault Date: Wed, 22 Oct 2025 10:47:40 +0200 Subject: [PATCH 09/10] Fix macros signatures --- src/ServiceProvider.php | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/ServiceProvider.php b/src/ServiceProvider.php index f8366fc..ded0590 100644 --- a/src/ServiceProvider.php +++ b/src/ServiceProvider.php @@ -1,4 +1,5 @@ config_path('visual-assert.php'), ], 'visual-assert-config'); - Browser::macro('assertScreenshot', function (string $name, float|null $threshold = null, int|null $metric = null, int $width = null, int $height = null) { + Browser::macro('assertScreenshot', function (string $name, float|null $threshold = null, int|null $metric = null, int $width = null, int $height = null): Browser { /** @var Browser $this */ $threshold = $threshold ?? config('visual-assert.default_threshold'); @@ -74,7 +75,7 @@ public function boot(): void }); // Element screenshot assertion macro - Browser::macro('assertElementScreenshot', function (string $selector, string $name, float|null $threshold = null, int|null $metric = null) { + Browser::macro('assertElementScreenshot', function (string $selector, string $name, float|null $threshold = null, int|null $metric = null): Browser { /** @var Browser $this */ $threshold = $threshold ?? config('visual-assert.default_threshold'); $metric = $metric ?? config('visual-assert.default_metric'); @@ -156,7 +157,7 @@ public function boot(): void return $this; }); - Browser::macro('assertResponsiveScreenshots', function (string $name, float|null $threshold = null, int|null $metric = null) { + Browser::macro('assertResponsiveScreenshots', function (string $name, float|null $threshold = null, int|null $metric = null): Browser { /** @var Browser $this */ $threshold = $threshold ?? config('visual-assert.default_threshold'); $metric = $metric ?? config('visual-assert.default_metric'); @@ -173,7 +174,7 @@ public function boot(): void }); // Responsive element screenshots macro - Browser::macro('assertResponsiveElementScreenshots', function (string $selector, string $name, float|null $threshold = null, int|null $metric = null) { + Browser::macro('assertResponsiveElementScreenshots', function (string $selector, string $name, float|null $threshold = null, int|null $metric = null): Browser { /** @var Browser $this */ $threshold = $threshold ?? config('visual-assert.default_threshold'); $metric = $metric ?? config('visual-assert.default_metric'); @@ -194,7 +195,7 @@ public function boot(): void }); // Helper macro to assert multiple elements at once - Browser::macro('assertElementsScreenshots', function (array $elements, float|null $threshold = null, int|null $metric = null) { + Browser::macro('assertElementsScreenshots', function (array $elements, float|null $threshold = null, int|null $metric = null): Browser { /** @var Browser $this */ $threshold = $threshold ?? config('visual-assert.default_threshold'); $metric = $metric ?? config('visual-assert.default_metric'); @@ -207,7 +208,7 @@ public function boot(): void }); // Macro to hide fixed/sticky elements before taking screenshots - Browser::macro('withoutFixedElements', function (callable $callback, array $selectors = null) { + Browser::macro('withoutFixedElements', function (callable $callback, array $selectors = null): Browser { /** @var Browser $this */ // Use default selectors if none provided @@ -253,7 +254,7 @@ public function boot(): void }); // Macro for screenshot without fixed elements - Browser::macro('assertScreenshotWithoutFixed', function (string $name, float|null $threshold = null, array $selectorsToHide = null, int|null $metric = null, int $width = null, int $height = null) { + Browser::macro('assertScreenshotWithoutFixed', function (string $name, float|null $threshold = null, array $selectorsToHide = null, int|null $metric = null, int $width = null, int $height = null): Browser { /** @var Browser $this */ return $this->withoutFixedElements(function ($browser) use ($name, $threshold, $metric, $width, $height) { return $browser->assertScreenshot($name, $threshold, $metric, $width, $height); @@ -261,7 +262,7 @@ public function boot(): void }); // Macro for element screenshot without fixed elements - Browser::macro('assertElementScreenshotWithoutFixed', function (string $selector, string $name, float|null $threshold = null, array $selectorsToHide = null, int|null $metric = null) { + Browser::macro('assertElementScreenshotWithoutFixed', function (string $selector, string $name, float|null $threshold = null, array $selectorsToHide = null, int|null $metric = null): Browser { /** @var Browser $this */ return $this->withoutFixedElements(function ($browser) use ($selector, $name, $threshold, $metric) { return $browser->assertElementScreenshot($selector, $name, $threshold, $metric); From f81bad327b57a80954cd666e3624747a61167be4 Mon Sep 17 00:00:00 2001 From: Hugo Heneault Date: Wed, 22 Oct 2025 10:47:51 +0200 Subject: [PATCH 10/10] 1.1.4 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index a87ae16..f8dfc17 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,7 @@ "comparison", "regression" ], - "version": "1.1.3", + "version": "1.1.4", "type": "library", "license": "MIT", "autoload": {