Repository navigation
The headline is elastishot pr. It compares the working tree with a base
commit, both served and captured on the same machine in one run, so there are
no baselines to commit.
This release also:
- fixes the
runandapprovetraps found in field use; - adds capture setup for apps that keep state in the browser;
- adds ignore by locator.
The CLI is stricter. A flag a command does not use, or an unknown capture key
in the config, is now an error (exit 2) where before it was silently ignored.
Comparison results do not move: the UI lab still finds 43 of 43 planted
changes, with 1 noise region.
Fixed
runno longer ignores capture flags.--full-page,--wait-for,
--hideand--no-mapnow apply to every target, over the config.- A flag a command does not use is now a usage error (exit 2) instead of
being parsed and dropped. Examples:run --viewport,run --name, and
--allanywhere butapprove. Scripts that passed such flags got nothing
from them before; now they are told. - A run made with
--single-filecan be approved. Candidate files are
written for every pairapproveaccepts; the pages still inline every
image. - An ad-hoc
compareno longer breaks a pendingapprove.report.jsonnow records the command that made the run and the baseline
folder it used (config.command,config.baselineDir).approvewithout a run folder skips alatestthatcomparemade, uses
the newest run thatrunmade, and says so.- It also notes when the run compared against a different baseline folder.
lateststill points at the newest run of any kind.
approve <name>treats a folder as a run only when it holds a
report.json, so a target named like a folder in the project is no longer
misread.- A delay can carry a unit.
--wait-for 2000msandwaitFor: '2000ms'
are delays; before, they were taken as CSS selectors and timed out.
Added
-
elastishot pr: check a pull request without baselines.- It checks the base commit out into a temporary git worktree, runs the
configuredinstallandbuildsteps, and serves it next to the working
tree, from a folder or with a server command on a port elastishot picked. - It captures every target on both sides in one run with one browser and
compares them: no baselines are committed, and font or browser
differences between machines cannot creep in. - The base is
--base <ref>; in a GitHub pull request job, the base side
of the merge commit; locally, where the branch leftorigin/HEAD,main
ormaster. - A page the base does not have is reported as
newwith the reason. A run
whose base captured nothing exits 2. - The worktree, the servers and the temporary folder are removed afterwards,
on Ctrl-C too.--keepleaves them for inspection. - The report records the base and head commits in
context, andapprove
refuses pr runs. - The new
prconfig block takesinstall,build,serveand
timeoutMs; a static site needs none of it.
- It checks the base commit out into a temporary git worktree, runs the
-
A Markdown summary:
summary.mdin the run folder, with one row per pair
and the pairs that need a look first. In GitHub Actions the same table is
appended to the job summary.pralways writes it;report.markdown: true
turns it on forrunandcompare. -
baseUrland relative target URLs. Targets can be paths relative to
baseUrl, andrun --base-url <url>points them at another server, such as
a local build, for one run. -
New public exports.
elastishot/nodenow exportsstartStaticServer
(the static serverpruses, with an SPA fallback and a base path), the
built-in reporters includingmarkdownReporter, andfindConfigFile.
elastishot/reportexportsrenderMarkdownSummary. -
run --update --forcealso replaces baselines that differ from the new
capture. Those pairs keep their diff and a "baseline replaced" reason, and
the run exits 0. -
compare --no-configignores any config file, so an ad-hoc comparison
inside a project neither takes its thresholds nor runs its reporters. -
--viewportaccepts a configured viewport's name. Asnapshot --viewport 390x844@2that matches a configured viewport also takes its name,
so the baseline lands in the folderrunreads. -
Config discovery: the config file is found in the current folder or the
nearest parent folder, andelastishot.config.cjsis recognised. -
Capture setup before the page loads.
capture.localeandcapture.timezoneId.capture.clock, which pinsDate.now(), or starts a fake clock with
mode: 'install'. Needs Playwright 1.45 or newer.capture.setup(page, context)in a JS config: seed storage, add cookies,
route requests.capture.storageStatealso takes the state object itself. A file path is
now resolved against the config folder rather than the current folder.
Together these remove the need for a custom capture adapter in most apps
that keep state in the browser. -
capture.reducedMotion:'reduce'stays the default;'no-preference'
captures an app's animated state. -
capture.animations: 'finish'fast-forwards running animations and
transitions to their end, soanimationendandtransitionendhandlers run.
The default'freeze'turns them off as before. Some components only reach
their final state in those handlers; React Native for Web'sModalsets
role="dialog"there. -
expectper target (andcapture.expect): a selector the ready page
must show. Without it, the capture fails instead of becoming a baseline of a
sign-in page or an empty app shell. -
A
CAPTURE_REDIRECTEDwarning when a page ends at another path or origin
than the one requested.meta.jsonrecords the final URL, and the colour
scheme, motion setting, locale and time zone of the capture. The pair page
shows them. -
Ignore by locator.
ignore: ['[data-testid=clock]', '#ad'], in the
config and per target, looks each locator up in both element maps. It
leaves that element's boxes out on each side, wherever the element landed.- It works on existing baselines, because their maps are stored with them.
- Locators no map records raise an
IGNORE_UNRESOLVEDwarning. - The pair page lists what was ignored.
Changed
- Capture options in the config are validated like the rest of the config.
An unknown key or a wrong value is now anE_CONFIGerror instead of being
dropped. - Element maps follow the picture more closely.
- When a page scrolls inside a fixed body, elements below the captured
picture are clipped or dropped instead of naming pixels that do not exist. - An
aria-hiddenorinertsubtree that another layer covers, such as an
inactive tab scene mounted under the active one, is left out. - Visible decorative icons stay.
- Maps of ordinary pages are unchanged.
- When a page scrolls inside a fixed body, elements below the captured
- opencv.js 5.0 (
@techstark/opencv-js5.0.0-release.1, up from 4.12). The
UI lab'sreport.jsonis identical on both versions, region for region and
score for score, and stage timings are within run-to-run noise. The install
grows from about 13 MB to about 16 MB, and the browser download from 12 MB
to 13 MB. - The package is now built with TypeScript 7. Apart from quote style on import
paths, the emitted JavaScript and type declarations are the same as
TypeScript 5.9's. - Development and tests use Playwright 1.64.1; the peer range is unchanged.
Documentation
docs/MOBILE.mdis now a general guide to native and React Native
screenshots. The native roadmap and the smaller items found in field use are
indocs/ROADMAP.md.