Repository navigation
Add visual regression assertions - #174
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Empty baselines can pass incorrectly, stale artifacts can persist, and several path, locator, and portability cases remain broken.
Review effort: Balanced
Findings: 1
Open (5)
What changed in this PR
Adds visual regression assertions for pages and locators, backed by Playwright’s screenshot comparator.
Changes:
- Adds PNG/WebP screenshot comparison, update modes, masks, tolerances, and failure artifacts.
- Integrates assertions with PHPUnit tracing, snapshot paths, and browser/platform variants.
- Adds documentation and unit/functional coverage.
| File | Description |
|---|---|
bin/lib/handlers.js |
Bridges screenshot comparisons to Playwright. |
src/Assertions/Internal/AbstractAssertions.php |
Supports non-polled assertions. |
src/Assertions/Internal/ScreenshotExpectation.php |
Manages baselines and artifacts. |
src/Assertions/LocatorAssertions.php |
Adds locator screenshot assertions. |
src/Assertions/LocatorAssertionsInterface.php |
Exposes the locator API. |
src/Assertions/Options/ToHaveScreenshotOptions.php |
Defines and validates options. |
src/Assertions/PageAssertions.php |
Adds page screenshot assertions. |
src/Assertions/PageAssertionsInterface.php |
Exposes the page API. |
src/Locator/Locator.php |
Sends locator comparison commands. |
src/Page/Page.php |
Sends page comparison commands. |
src/Screenshot/ScreenshotComparison.php |
Models comparison results. |
src/Testing/Expect.php |
Resolves snapshot paths and variants. |
src/Testing/ExpectDecorator.php |
Counts screenshot assertions. |
src/Testing/ExpectInterface.php |
Exposes the testing API. |
src/Testing/PlaywrightTestCaseTrait.php |
Configures baseline and output directories. |
tests/Functional/Screenshot/ToHaveScreenshotTest.php |
Exercises browser-level behavior. |
tests/Unit/Assertions/Internal/ScreenshotExpectationTest.php |
Tests baseline lifecycle. |
tests/Unit/Assertions/LocatorAssertionsTest.php |
Tests locator integration. |
tests/Unit/Assertions/Options/ToHaveScreenshotOptionsTest.php |
Tests option validation. |
tests/Unit/Assertions/PageAssertionsTest.php |
Tests page integration. |
tests/Unit/Locator/LocatorTest.php |
Tests locator transport behavior. |
tests/Unit/Page/PageTest.php |
Tests page transport behavior. |
tests/Unit/Screenshot/ScreenshotComparisonTest.php |
Tests response decoding. |
tests/Unit/Testing/ExpectFactoryTest.php |
Tests paths and PHPUnit integration. |
docs/guide/assertions-reference.md |
Lists the new assertions. |
docs/guide/visual-regression.md |
Documents visual regression workflows. |
CHANGELOG.md |
Announces the feature. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
ea7f5c0 to
0722baa
Compare
|
Rebased onto The focused Chromium screenshot tests passed on Playwright 1.62.1 and 1.64.1. |
|
Thak you so much @kbond ! 🙇 |
The bridge gains an expectScreenshot command for pages and locators. It calls page._expectScreenshot(), the private method behind @playwright/test's toHaveScreenshot(): screenshots until two consecutive ones match, masks, then pixelmatch or ssim-cie94. The bridge applies the defaults the JS runner adds on its side (animations disabled, caret hidden, CSS scale). Images travel base64 encoded, masks as selectors rebuilt into locators, frames included. Page::expectScreenshot() and Locator::expectScreenshot() expose it as @internal methods returning a ScreenshotComparison. PageInterface and LocatorInterface are left untouched: downstream test doubles implement them.
toHaveScreenshot() on page and locator assertions, and on expect() in test cases, compares a stable screenshot with a baseline image, as in @playwright/test: - Baselines live next to the test file, <Test>.php-snapshots/, named after the browser of the page under test and the platform: card-chromium-linux.png. PNG by default, lossless WebP with .webp. - PLAYWRIGHT_UPDATE_SNAPSHOTS takes the --update-snapshots values: none, missing (default), changed, all. "all" records without comparing. - A failure writes card-expected, card-actual and card-diff to test-failures/<TestClass>-<testMethod>-<browser>/, removed once the baseline matches or is recorded again. - ToHaveScreenshotOptions carries the @playwright/test defaults and rejects invalid values on construction.
A guide on why and where to compare screenshots (a defensive test on the design system and precious pages), how baselines are named, updated and reviewed, failure images, PNG and WebP, options, headless mode and limits.
- An empty baseline reached Playwright as "no baseline" and matched any screenshot. It now fails with a clear message, and is recorded again in the changed and all modes. The bridge sends any string it receives. - A failure removes the images of the previous one, so a diff from an earlier mismatch never sits next to a later timeout. - Locator::normalize() keeps the page of the locator, so a normalized locator names its baselines after the browser too. - UNC paths (\\server\share\card.png) are absolute snapshot paths. - The unreadable baseline test skips without POSIX permissions. - The useItemsLocator() docblock is back on its helper.
2ec0be9 to
b81aab4
Compare



Add
toHaveScreenshot()for pages and locators, with PNG and lossless WebP baselines, update modes, masks, and configurable tolerances. Save expected, actual, and diff images when a comparison fails.The assertion uses Playwright’s private
_expectScreenshot()API for screenshot stabilization and comparison.