Skip to content

Releases: testivai/testivai-oss

@testivai/witness@2.6.0

Choose a tag to compare

@github-actions github-actions released this 02 Nov 03:25
d83763b

Minor Changes

  • 1ac04ef: Capture health: an unhealthy capture is never "render noise". A web font that failed and fell back to a system font, or a stylesheet that answered 404, leaves the DOM identical and the computed styles matching (the style digest hashes the declared font-family, not the font that rendered), so its small, scattered diff read "likely render noise" and noiseAutoPass passed it. The Playwright JS/TS adapter and testivai witness <url> now record, after each screenshot, what failed to load as health in the capture's metadata.json: document.fonts.status and every font face that errored, <link rel=stylesheet> elements that did not load, broken <img>s, and requests that answered 400 or more (Resource Timing, Chromium 109+), each URL as host and path only, never the query string. The crawler also merges the failed requests it saw on the network (CDP), cross-origin ones included. Approving freezes the capture's health into the baseline's metadata.json. results.json schema 2.7.0 (additive) adds snapshots[].captureHealth (both blocks, unhealthy: "candidate" / "baseline" / "both" / null, and reasons and warnings in plain words), present when either side recorded health, new snapshots included. Web fonts still loading, a font face that failed, a failed stylesheet, or a failed stylesheet request make a capture unhealthy (a failed font request only with a font face that failed, since a face can load from its next src; a fetch()/XHR request or a <link> that no <link rel=stylesheet> names and that does not end in .css is never a stylesheet): dom.noiseHint is then false and no pass criterion (noiseAutoPass, maxDiffPercent / maxDiffPixels, shiftTolerance) applies while pixels differ; a zero-pixel diff still passes. The HTML report, @testivai/mcp (get_visual_results verdicts, explain_snapshot's new layers.health and guidance, the triage-visual-diff rubric and the review prompt; unhealthy captures are never grouped) and the GitHub Action comment read Unhealthy capture with what failed, before any other reading (rendering drift too, when both are true), and call out an unhealthy baseline on every compare against it ("re-baseline from a healthy run"). Broken images, failed scripts and other requests are warnings only. testivai approve warns when the capture it promotes is unhealthy. @testivai/witness exports HEALTH_PROBE_EXPRESSION, parseHealth, mergeResourceFailures and the types, and @testivai/witness/report the readings (assessHealth, snapshotCaptureHealth, captureHealthReading, isUnhealthyCapture, approveHealthWarning). The WebdriverIO, Selenium, Python, Ruby and Java adapters do not record health yet: their captures read "not checked" and compare exactly as before.

  • 117bac5: New opt-in config elementIdAttributes (for example ["data-testid"]) anchors element-map paths on attributes your tests already set. An element's path starts at its nearest ancestor-or-self carrying one of them with a non-empty value no other element in the page shares: div[data-testid="board"] > div.css-146c3p1 instead of a body > div > div.css-g5y9jx > div.css-g5y9jx:nth-of-type(2) > … chain. Content inserted above an anchored element no longer renumbers its path, so an element that only moved reads as a shift (with the page shift detected) instead of a change, and the style check pairs the same elements. The list order is the precedence; a duplicated value is skipped and the path continues upward, so paths stay unique; values are escaped as CSS strings (> included), so each anchored path is a working selector. Unset, nothing changes: the attributes are never read and elements.json, the style digests, results.json and the report are byte-identical. The Playwright, Selenium and WebdriverIO adapters read it from .testivai/config.json and record it in the capture's metadata.json (only when set); approving freezes it into the baseline, and styles are compared only when both sides used the same setting (dom.styleCheck: "unavailable" until baselines are re-approved after a change), so paths built two ways never produce a style verdict on part of the page. @testivai/witness exports normalizeElementIdAttributes; buildElementMapExpression takes the list as a third argument.

  • f3e3fc7: Native app screens (experimental): @testivai/witness-webdriverio captures native Android and iOS app screens in an Appium session. In a session on Android or iOS that names no browser and is in the NATIVE_APP context (or, when the context cannot be read, was started with app, appPackage or bundleId), witness() runs no page script: a native screen has no page, Appium rejects them there and WebdriverIO resends each failed one three times (~1.5 s each, ~8 s per capture on an Android 14 emulator). The capture is the whole screen, pixel diff only. The status bar is masked per capture (masks: [{ "top": <px> }] in the capture's metadata.json): on Android to the bottom of the bar's frame in the window manager at capture time (mobile: getSystemBars), so a rotation is followed; UiAutomator2's own reading (mobile: viewportRect, the session capabilities) is taken once at the session start and came back 63 px for a 136 px bar in one emulator run, so it is only the fallback. On iOS it comes from mobile: viewportRect. The environment block comes from the capabilities, with browser.name: "native-app", capture method screen:appium and a new device section (platform, OS version, model, the requested device name, the Appium driver, screen size, density). The snapshot is keyed <name>__<platform>-<device>-<osMajor> (login__android-pixel_7-15) unless the call gives a variant. New options native (true forces native mode, false keeps the web path) and maskStatusBar (default true); WitnessBrowser gains the optional getContext(). A hybrid app in a web view, and every browser session, keep the web path, and a browser session makes no extra call. Verified on an Android 14 emulator in CI; iOS is not verified.

    @testivai/witness: results.json schema 2.9.0 (additive) adds the device section of a snapshot's environment blocks and capture method screen:appium. The device's platform, OS version, model, screen and density can change rendering; the device name and the Appium driver are context, and so is os (the machine running the tests) when both sides are native app captures. The report words device changes ("device sdk_gphone64_x86_64 → Pixel 7, device OS 14 → 15") and the capture method ("full screen (Appium)"). New exports: appiumEnvironment, isNativeAppCapabilities, mobilePlatform, namesBrowser, nativeAppDevice, nativeAppVariant, statusBarFromCapabilities, statusBarFromSystemBars, statusBarFromViewportRect, CAPTURE_METHODS.APPIUM_SCREEN and the DeviceEnvironment type. Guide: docs/guides/native-mobile.md.

  • 9eaa9f4: A failing test no longer leaves a pull request without a visual report. testivai merge-captures now writes testivai-merge.json beside the captures it merges in .testivai/temp/ (the shard total, the shards seen and the shards missing; exported as MERGE_RECORD and the MergeRecord type), so a later step can tell a merge that lacks a shard from the whole suite. The testivai/testivai-oss@v1 action uses it: when a run wrote no results.json, the action compares the captures in .testivai/temp/ itself, but never one shard's slice or an incomplete merge. In capture-only mode, the Playwright reporter's hint now says to run the compare step with if: ${{ !cancelled() }} (and on a job that needs the shards, too), since a CI step runs only on success by default.

  • a3278e1: The report writes images/<name>/thumb.png for each changed snapshot: the changed area of the baseline, the current capture and the diff side by side, 2 px apart, at most 800×400 px (area-average downscale, never upscaled), small enough to show inline where a full-page diff is not, such as a pull request comment. The area is the union of the up to three largest diff regions padded 24 px, or without regions a 400 px band from the first differing row; on a size change it is on the padded canvas. results.json schema 2.6.0 (additive) records it as snapshots[].thumbPath. Never written for passed (auto-passed included) or new snapshots; the HTML report does not show it. parseReportData accepts thumbPath as text and, like the other image paths, never copies it from the file.

  • 62964eb: Four fixes found running React Native screens through react-native-web.

    • A claimed shift is checked against the pixels. Element maps pair elements by path, and content inserted above an element renumbers its :nth-of-type path, which can pair it with a look-alike neighbour (same size and styles, different content). That read as a shift by a wrong distance (−16 px while the content moved +64 px) with a wrong pageShift. A pair now counts as a shift, in regions and in pageShift, only when the element's pixels match at its new position: at most 1% differ, at the diff's colour threshold, masks excluded, best of ±1 px. In real Chrome true shifts differed on 0.00% of their pixels (fractional moves included), look-alike neighbours on 4.8–6.7%. Shifts that were right before are unchanged; wrong ones now read as change, which also keeps shiftTolerance from passing them.
    • <script> attribute values are not a DOM change. A script never renders, but a bundle renamed by content hash (Expo's index-<hash>.js), its integrity and a per-request nonce counted as attribute changes, so a stylesheet-only change did not read style-only. Their presence still counts, and so does a script added or removed. A snapshot whose only DOM difference was a script attribute now has dom.changed: false, so its noise hint follows the style check.
    • **The Playwright adapter restores the device emulation its full-page capture ...
Read more

@testivai/witness-webdriverio@0.5.0

Choose a tag to compare

@github-actions github-actions released this 02 Nov 03:25
d83763b

Minor Changes

  • 117bac5: New opt-in config elementIdAttributes (for example ["data-testid"]) anchors element-map paths on attributes your tests already set. An element's path starts at its nearest ancestor-or-self carrying one of them with a non-empty value no other element in the page shares: div[data-testid="board"] > div.css-146c3p1 instead of a body > div > div.css-g5y9jx > div.css-g5y9jx:nth-of-type(2) > … chain. Content inserted above an anchored element no longer renumbers its path, so an element that only moved reads as a shift (with the page shift detected) instead of a change, and the style check pairs the same elements. The list order is the precedence; a duplicated value is skipped and the path continues upward, so paths stay unique; values are escaped as CSS strings (> included), so each anchored path is a working selector. Unset, nothing changes: the attributes are never read and elements.json, the style digests, results.json and the report are byte-identical. The Playwright, Selenium and WebdriverIO adapters read it from .testivai/config.json and record it in the capture's metadata.json (only when set); approving freezes it into the baseline, and styles are compared only when both sides used the same setting (dom.styleCheck: "unavailable" until baselines are re-approved after a change), so paths built two ways never produce a style verdict on part of the page. @testivai/witness exports normalizeElementIdAttributes; buildElementMapExpression takes the list as a third argument.

  • f3e3fc7: Native app screens (experimental): @testivai/witness-webdriverio captures native Android and iOS app screens in an Appium session. In a session on Android or iOS that names no browser and is in the NATIVE_APP context (or, when the context cannot be read, was started with app, appPackage or bundleId), witness() runs no page script: a native screen has no page, Appium rejects them there and WebdriverIO resends each failed one three times (~1.5 s each, ~8 s per capture on an Android 14 emulator). The capture is the whole screen, pixel diff only. The status bar is masked per capture (masks: [{ "top": <px> }] in the capture's metadata.json): on Android to the bottom of the bar's frame in the window manager at capture time (mobile: getSystemBars), so a rotation is followed; UiAutomator2's own reading (mobile: viewportRect, the session capabilities) is taken once at the session start and came back 63 px for a 136 px bar in one emulator run, so it is only the fallback. On iOS it comes from mobile: viewportRect. The environment block comes from the capabilities, with browser.name: "native-app", capture method screen:appium and a new device section (platform, OS version, model, the requested device name, the Appium driver, screen size, density). The snapshot is keyed <name>__<platform>-<device>-<osMajor> (login__android-pixel_7-15) unless the call gives a variant. New options native (true forces native mode, false keeps the web path) and maskStatusBar (default true); WitnessBrowser gains the optional getContext(). A hybrid app in a web view, and every browser session, keep the web path, and a browser session makes no extra call. Verified on an Android 14 emulator in CI; iOS is not verified.

    @testivai/witness: results.json schema 2.9.0 (additive) adds the device section of a snapshot's environment blocks and capture method screen:appium. The device's platform, OS version, model, screen and density can change rendering; the device name and the Appium driver are context, and so is os (the machine running the tests) when both sides are native app captures. The report words device changes ("device sdk_gphone64_x86_64 → Pixel 7, device OS 14 → 15") and the capture method ("full screen (Appium)"). New exports: appiumEnvironment, isNativeAppCapabilities, mobilePlatform, namesBrowser, nativeAppDevice, nativeAppVariant, statusBarFromCapabilities, statusBarFromSystemBars, statusBarFromViewportRect, CAPTURE_METHODS.APPIUM_SCREEN and the DeviceEnvironment type. Guide: docs/guides/native-mobile.md.

  • 8462b36: Hybrid app web views (experimental): new witness() option context captures in another Appium context for one call and switches back afterwards, also when the capture fails. context: 'webview' is the app's web view (the WEBVIEW_<appPackage> context on Android, else the first WEBVIEW_… context, as iOS numbers them); any other value is an exact context name ('WEBVIEW_com.example.app', 'NATIVE_APP'). A hybrid app driven in the native context gets its web view captured as a page, with every layer (DOM diff, style check, attribution, shift detection), instead of a native capture; context: 'NATIVE_APP' from a web view is a native capture. A session with no web view, or without the name asked for, fails with the contexts it has and what the app's build needs (WebView debugging enabled). WitnessBrowser gains the optional getContexts() and switchContext().

Patch Changes

@testivai/witness-selenium@0.4.0

Choose a tag to compare

@github-actions github-actions released this 02 Nov 03:25
d83763b

Minor Changes

  • 117bac5: New opt-in config elementIdAttributes (for example ["data-testid"]) anchors element-map paths on attributes your tests already set. An element's path starts at its nearest ancestor-or-self carrying one of them with a non-empty value no other element in the page shares: div[data-testid="board"] > div.css-146c3p1 instead of a body > div > div.css-g5y9jx > div.css-g5y9jx:nth-of-type(2) > … chain. Content inserted above an anchored element no longer renumbers its path, so an element that only moved reads as a shift (with the page shift detected) instead of a change, and the style check pairs the same elements. The list order is the precedence; a duplicated value is skipped and the path continues upward, so paths stay unique; values are escaped as CSS strings (> included), so each anchored path is a working selector. Unset, nothing changes: the attributes are never read and elements.json, the style digests, results.json and the report are byte-identical. The Playwright, Selenium and WebdriverIO adapters read it from .testivai/config.json and record it in the capture's metadata.json (only when set); approving freezes it into the baseline, and styles are compared only when both sides used the same setting (dom.styleCheck: "unavailable" until baselines are re-approved after a change), so paths built two ways never produce a style verdict on part of the page. @testivai/witness exports normalizeElementIdAttributes; buildElementMapExpression takes the list as a third argument.

Patch Changes

@testivai/witness-playwright@2.1.0

Choose a tag to compare

@github-actions github-actions released this 02 Nov 03:25
d83763b

Minor Changes

  • 117bac5: New opt-in config elementIdAttributes (for example ["data-testid"]) anchors element-map paths on attributes your tests already set. An element's path starts at its nearest ancestor-or-self carrying one of them with a non-empty value no other element in the page shares: div[data-testid="board"] > div.css-146c3p1 instead of a body > div > div.css-g5y9jx > div.css-g5y9jx:nth-of-type(2) > … chain. Content inserted above an anchored element no longer renumbers its path, so an element that only moved reads as a shift (with the page shift detected) instead of a change, and the style check pairs the same elements. The list order is the precedence; a duplicated value is skipped and the path continues upward, so paths stay unique; values are escaped as CSS strings (> included), so each anchored path is a working selector. Unset, nothing changes: the attributes are never read and elements.json, the style digests, results.json and the report are byte-identical. The Playwright, Selenium and WebdriverIO adapters read it from .testivai/config.json and record it in the capture's metadata.json (only when set); approving freezes it into the baseline, and styles are compared only when both sides used the same setting (dom.styleCheck: "unavailable" until baselines are re-approved after a change), so paths built two ways never produce a style verdict on part of the page. @testivai/witness exports normalizeElementIdAttributes; buildElementMapExpression takes the list as a third argument.

  • 62964eb: Four fixes found running React Native screens through react-native-web.

    • A claimed shift is checked against the pixels. Element maps pair elements by path, and content inserted above an element renumbers its :nth-of-type path, which can pair it with a look-alike neighbour (same size and styles, different content). That read as a shift by a wrong distance (−16 px while the content moved +64 px) with a wrong pageShift. A pair now counts as a shift, in regions and in pageShift, only when the element's pixels match at its new position: at most 1% differ, at the diff's colour threshold, masks excluded, best of ±1 px. In real Chrome true shifts differed on 0.00% of their pixels (fractional moves included), look-alike neighbours on 4.8–6.7%. Shifts that were right before are unchanged; wrong ones now read as change, which also keeps shiftTolerance from passing them.
    • <script> attribute values are not a DOM change. A script never renders, but a bundle renamed by content hash (Expo's index-<hash>.js), its integrity and a per-request nonce counted as attribute changes, so a stylesheet-only change did not read style-only. Their presence still counts, and so does a script added or removed. A snapshot whose only DOM difference was a script attribute now has dom.changed: false, so its noise hint follows the style check.
    • The Playwright adapter restores the device emulation its full-page capture drops. The default capture's beyond-viewport screenshot, over the adapter's own CDP session, left the page without its emulation for the rest of the test (Pixel 7: devicePixelRatio 2.625 → 1, touch off). witness() now puts back the pixel ratio and touch emulation after everything it measures, and metadata.json records the pixel ratio the image was rendered at: 1 for a Chromium CDP capture, which used to record the profile's value. A baseline approved before this, on a Chromium profile with a deviceScaleFactor other than 1, reads as an environment change in render.deviceScaleFactor until it is re-approved: wording only by default, a status change with environmentPolicy: "strict". The captured images do not change.
    • No "Browser screenshot failed" on WebKit and Firefox. They are captured with Playwright's full-page screenshot directly; a CDP failure on Chromium is still reported.

Patch Changes

  • 1ac04ef: Capture health: an unhealthy capture is never "render noise". A web font that failed and fell back to a system font, or a stylesheet that answered 404, leaves the DOM identical and the computed styles matching (the style digest hashes the declared font-family, not the font that rendered), so its small, scattered diff read "likely render noise" and noiseAutoPass passed it. The Playwright JS/TS adapter and testivai witness <url> now record, after each screenshot, what failed to load as health in the capture's metadata.json: document.fonts.status and every font face that errored, <link rel=stylesheet> elements that did not load, broken <img>s, and requests that answered 400 or more (Resource Timing, Chromium 109+), each URL as host and path only, never the query string. The crawler also merges the failed requests it saw on the network (CDP), cross-origin ones included. Approving freezes the capture's health into the baseline's metadata.json. results.json schema 2.7.0 (additive) adds snapshots[].captureHealth (both blocks, unhealthy: "candidate" / "baseline" / "both" / null, and reasons and warnings in plain words), present when either side recorded health, new snapshots included. Web fonts still loading, a font face that failed, a failed stylesheet, or a failed stylesheet request make a capture unhealthy (a failed font request only with a font face that failed, since a face can load from its next src; a fetch()/XHR request or a <link> that no <link rel=stylesheet> names and that does not end in .css is never a stylesheet): dom.noiseHint is then false and no pass criterion (noiseAutoPass, maxDiffPercent / maxDiffPixels, shiftTolerance) applies while pixels differ; a zero-pixel diff still passes. The HTML report, @testivai/mcp (get_visual_results verdicts, explain_snapshot's new layers.health and guidance, the triage-visual-diff rubric and the review prompt; unhealthy captures are never grouped) and the GitHub Action comment read Unhealthy capture with what failed, before any other reading (rendering drift too, when both are true), and call out an unhealthy baseline on every compare against it ("re-baseline from a healthy run"). Broken images, failed scripts and other requests are warnings only. testivai approve warns when the capture it promotes is unhealthy. @testivai/witness exports HEALTH_PROBE_EXPRESSION, parseHealth, mergeResourceFailures and the types, and @testivai/witness/report the readings (assessHealth, snapshotCaptureHealth, captureHealthReading, isUnhealthyCapture, approveHealthWarning). The WebdriverIO, Selenium, Python, Ruby and Java adapters do not record health yet: their captures read "not checked" and compare exactly as before.
  • 9eaa9f4: A failing test no longer leaves a pull request without a visual report. testivai merge-captures now writes testivai-merge.json beside the captures it merges in .testivai/temp/ (the shard total, the shards seen and the shards missing; exported as MERGE_RECORD and the MergeRecord type), so a later step can tell a merge that lacks a shard from the whole suite. The testivai/testivai-oss@v1 action uses it: when a run wrote no results.json, the action compares the captures in .testivai/temp/ itself, but never one shard's slice or an incomplete merge. In capture-only mode, the Playwright reporter's hint now says to run the compare step with if: ${{ !cancelled() }} (and on a job that needs the shards, too), since a CI step runs only on success by default.
  • Updated dependencies [1ac04ef]
  • Updated dependencies [117bac5]
  • Updated dependencies [f3e3fc7]
  • Updated dependencies [9eaa9f4]
  • Updated dependencies [a3278e1]
  • Updated dependencies [62964eb]
  • Updated dependencies [c53604c]
    • @testivai/witness@2.6.0

@testivai/mcp@0.9.1

Choose a tag to compare

@github-actions github-actions released this 02 Nov 03:25
d83763b

Patch Changes

  • 1ac04ef: Capture health: an unhealthy capture is never "render noise". A web font that failed and fell back to a system font, or a stylesheet that answered 404, leaves the DOM identical and the computed styles matching (the style digest hashes the declared font-family, not the font that rendered), so its small, scattered diff read "likely render noise" and noiseAutoPass passed it. The Playwright JS/TS adapter and testivai witness <url> now record, after each screenshot, what failed to load as health in the capture's metadata.json: document.fonts.status and every font face that errored, <link rel=stylesheet> elements that did not load, broken <img>s, and requests that answered 400 or more (Resource Timing, Chromium 109+), each URL as host and path only, never the query string. The crawler also merges the failed requests it saw on the network (CDP), cross-origin ones included. Approving freezes the capture's health into the baseline's metadata.json. results.json schema 2.7.0 (additive) adds snapshots[].captureHealth (both blocks, unhealthy: "candidate" / "baseline" / "both" / null, and reasons and warnings in plain words), present when either side recorded health, new snapshots included. Web fonts still loading, a font face that failed, a failed stylesheet, or a failed stylesheet request make a capture unhealthy (a failed font request only with a font face that failed, since a face can load from its next src; a fetch()/XHR request or a <link> that no <link rel=stylesheet> names and that does not end in .css is never a stylesheet): dom.noiseHint is then false and no pass criterion (noiseAutoPass, maxDiffPercent / maxDiffPixels, shiftTolerance) applies while pixels differ; a zero-pixel diff still passes. The HTML report, @testivai/mcp (get_visual_results verdicts, explain_snapshot's new layers.health and guidance, the triage-visual-diff rubric and the review prompt; unhealthy captures are never grouped) and the GitHub Action comment read Unhealthy capture with what failed, before any other reading (rendering drift too, when both are true), and call out an unhealthy baseline on every compare against it ("re-baseline from a healthy run"). Broken images, failed scripts and other requests are warnings only. testivai approve warns when the capture it promotes is unhealthy. @testivai/witness exports HEALTH_PROBE_EXPRESSION, parseHealth, mergeResourceFailures and the types, and @testivai/witness/report the readings (assessHealth, snapshotCaptureHealth, captureHealthReading, isUnhealthyCapture, approveHealthWarning). The WebdriverIO, Selenium, Python, Ruby and Java adapters do not record health yet: their captures read "not checked" and compare exactly as before.
  • e5f2b7f: zod 4.6.6 or later (was 3.25): every 3.x release is affected by GHSA-mrhx-c7xc-m3w5 (memory exhaustion while validating oversized constrained collections), so npm audit --audit-level=high failed in any project that installs @testivai/mcp. The tools, their arguments and their validation are unchanged. Two cosmetic differences in the advertised input schemas: integer arguments (region, y, height) now carry an explicit maximum, and tool input objects no longer advertise additionalProperties: false (unknown keys are still dropped, as before).
  • c53604c: A permanently broken asset no longer turns off every pass tolerance. Since capture health (schema 2.7.0), no pass criterion passed an unhealthy capture whose pixels differed, so a site whose web font or stylesheet fails on every CI run lost maxDiffPercent, maxDiffPixels and shiftTolerance on every affected snapshot, and a small anti-aliasing diff failed even with the baseline unhealthy in the same way. Now, when both sides are unhealthy with exactly the same failures (the same font faces by family, weight and style, the same failed stylesheets, and the same failed stylesheet and font requests by host, path and status), results.json schema 2.8.0 (additive) sets snapshots[].captureHealth.sameOnBothSides: true and those three tolerances apply again (autoPassed "threshold" or "shift"). noiseAutoPass never passes an unhealthy capture, dom.noiseHint stays false, and the reading is still Unhealthy capture, never render noise: the HTML report, the @testivai/mcp verdicts, explain_snapshot guidance and triage rubric, and the GitHub Action comment add "the baseline was captured with the same failures", that the tolerances still apply but noise auto-pass does not, and which criterion passed it. It is never "the same" while web fonts were still loading on either side, when one side could see what the other could not (Font Loading API, request statuses), or when a list may have been cut at 10 entries; broken images and failed scripts are not compared (they are warnings). One side unhealthy, or different failures, behave as before. @testivai/witness/report exports sameHealthFailures, healthAllowsTolerances and SAME_FAILURES_NEXT; parseReportData keeps sameOnBothSides only as true with unhealthy: "both".
  • Updated dependencies [1ac04ef]
  • Updated dependencies [117bac5]
  • Updated dependencies [f3e3fc7]
  • Updated dependencies [9eaa9f4]
  • Updated dependencies [a3278e1]
  • Updated dependencies [62964eb]
  • Updated dependencies [c53604c]
    • @testivai/witness@2.6.0

@testivai/witness@2.5.0

Choose a tag to compare

@github-actions github-actions released this 19 Oct 14:14
e90e959

Minor Changes

  • cd9ffe7: Capture provenance: every capture now records where it came from, and the report says when a diff is the machine changing rather than the page. The Playwright, WebdriverIO and Selenium (JS) adapters and testivai witness <url> write an environment block into the capture's metadata.json: the OS (and the Linux distro), the browser and its version (and the WebDriver binary), the test framework, the adapter and how it took the screenshot (full-page:cdp, full-page:playwright, full-page:stitched, viewport:webdriver), what the page was rendered with (viewport, device scale, color scheme, reduced motion, locale, time zone, measured in the page), the CI provider and runner image, a container, and TESTIVAI_ENV_LABEL. Approving a capture freezes its block into the baseline's metadata.json (and drops a stale one). The compare reads both blocks: results.json schema 2.5.0 (additive) adds snapshots[].environment (delta, renderingDelta, both blocks when they differ) and a run-level environment (the fields every capture of the run agrees on). Framework, adapter and driver versions, the CI runner image, the project and the Linux kernel are context; the rest can change rendering. A diff whose DOM is identical, whose computed styles match and whose rendering environment changed is now rendering drift in the HTML report, @testivai/mcp (get_visual_results verdicts, its grouping and a new opening line when several snapshots share one change; explain_snapshot's new layers.environment; the triage-visual-diff rubric) and the GitHub Action comment, never "likely render noise"; a size change from another capture method says so instead of "page grew". New config environmentPolicy: "warn" (default) never changes a status; "separate" keys snapshots <name>__<browser>__<platform> (never by version) and reports missing only the baselines of an environment the run captured; "strict" makes a rendering change of environment changed whatever its pixels say. New testivai env prints this machine's part of the block (--fonts adds a fingerprint of the installed fonts, --json for machines). @testivai/witness exports the collectors (collectHostEnvironment, RENDER_PROBE_EXPRESSION, browserFromCapabilities, webDriverEnvironment, applyEnvironmentPolicyToName, …) and @testivai/witness/report the readings (diffEnvironments, isRenderingDrift, environmentChangeGroups, environmentChangeLine, …). BaselineStore gains writeTempMetadata and readTempMetadata. The WebdriverIO and Selenium WitnessBrowser / WitnessDriver types gain the optional capabilities / getCapabilities() they read the browser from. The Python, Ruby and Java adapters do not record the block yet; their captures compare exactly as before.

  • c05d870: The HTML report now escapes every value it shows, and each snapshot has its own link target.

    • Escaping. The report wrote six values from results.json into the page without escaping them: the baseline, current and diff image paths, the diff path on each changed region's zoom link, the auto-pass criterion and where a mask came from. A results.json with markup in one of those fields (one you did not produce, such as from a fork's CI run) could add elements or script to the page. They are escaped now, like every other value.
    • Link targets. Each snapshot card has an id, so index.html#snap-home opens the report at that snapshot, outlined. On phones the card stays below the top bar. Clicking a snapshot's name puts its link in the address bar. snapshotAnchorId(name) is exported, so other tools (the PR comment) build the same link: plain names stay readable (snap-home), and any other name gets a hash suffix so that home page and home/page never share an id.
    • Reading a results.json you did not produce. parseReportData(json) checks every field the report reads (each must have its type, within size limits, or the file is rejected with the field's path), drops fields it does not know, and never takes image paths from the file. It reads the 2.x formats, capture provenance (2.5.0) included; a newer major is refused with "open the report ZIP". The GitHub Pages publisher renders reports from other people's CI runs, forks included, only through it.
    • Options for a published report. renderHtml(data, { notices, noindex, csp }): notices are lines at the top of the report (which pull request, commit and CI run it is, and a warning for a fork's results), each with links to https pages only; noindex asks search engines not to index the page; csp adds a Content-Security-Policy that lets the page use only its own inline styles and scripts and its own images, so nothing is loaded from or sent to another site even if markup ever got through the escaping (project sites on <owner>.github.io share one origin). Without options the report is unchanged.

@testivai/witness-webdriverio@0.4.6

Choose a tag to compare

@github-actions github-actions released this 19 Oct 14:14
e90e959

Patch Changes

  • cd9ffe7: Capture provenance: every capture now records where it came from, and the report says when a diff is the machine changing rather than the page. The Playwright, WebdriverIO and Selenium (JS) adapters and testivai witness <url> write an environment block into the capture's metadata.json: the OS (and the Linux distro), the browser and its version (and the WebDriver binary), the test framework, the adapter and how it took the screenshot (full-page:cdp, full-page:playwright, full-page:stitched, viewport:webdriver), what the page was rendered with (viewport, device scale, color scheme, reduced motion, locale, time zone, measured in the page), the CI provider and runner image, a container, and TESTIVAI_ENV_LABEL. Approving a capture freezes its block into the baseline's metadata.json (and drops a stale one). The compare reads both blocks: results.json schema 2.5.0 (additive) adds snapshots[].environment (delta, renderingDelta, both blocks when they differ) and a run-level environment (the fields every capture of the run agrees on). Framework, adapter and driver versions, the CI runner image, the project and the Linux kernel are context; the rest can change rendering. A diff whose DOM is identical, whose computed styles match and whose rendering environment changed is now rendering drift in the HTML report, @testivai/mcp (get_visual_results verdicts, its grouping and a new opening line when several snapshots share one change; explain_snapshot's new layers.environment; the triage-visual-diff rubric) and the GitHub Action comment, never "likely render noise"; a size change from another capture method says so instead of "page grew". New config environmentPolicy: "warn" (default) never changes a status; "separate" keys snapshots <name>__<browser>__<platform> (never by version) and reports missing only the baselines of an environment the run captured; "strict" makes a rendering change of environment changed whatever its pixels say. New testivai env prints this machine's part of the block (--fonts adds a fingerprint of the installed fonts, --json for machines). @testivai/witness exports the collectors (collectHostEnvironment, RENDER_PROBE_EXPRESSION, browserFromCapabilities, webDriverEnvironment, applyEnvironmentPolicyToName, …) and @testivai/witness/report the readings (diffEnvironments, isRenderingDrift, environmentChangeGroups, environmentChangeLine, …). BaselineStore gains writeTempMetadata and readTempMetadata. The WebdriverIO and Selenium WitnessBrowser / WitnessDriver types gain the optional capabilities / getCapabilities() they read the browser from. The Python, Ruby and Java adapters do not record the block yet; their captures compare exactly as before.
  • Updated dependencies [cd9ffe7]
  • Updated dependencies [c05d870]
    • @testivai/witness@2.5.0

@testivai/witness-selenium@0.3.12

Choose a tag to compare

@github-actions github-actions released this 19 Oct 14:14
e90e959

Patch Changes

  • cd9ffe7: Capture provenance: every capture now records where it came from, and the report says when a diff is the machine changing rather than the page. The Playwright, WebdriverIO and Selenium (JS) adapters and testivai witness <url> write an environment block into the capture's metadata.json: the OS (and the Linux distro), the browser and its version (and the WebDriver binary), the test framework, the adapter and how it took the screenshot (full-page:cdp, full-page:playwright, full-page:stitched, viewport:webdriver), what the page was rendered with (viewport, device scale, color scheme, reduced motion, locale, time zone, measured in the page), the CI provider and runner image, a container, and TESTIVAI_ENV_LABEL. Approving a capture freezes its block into the baseline's metadata.json (and drops a stale one). The compare reads both blocks: results.json schema 2.5.0 (additive) adds snapshots[].environment (delta, renderingDelta, both blocks when they differ) and a run-level environment (the fields every capture of the run agrees on). Framework, adapter and driver versions, the CI runner image, the project and the Linux kernel are context; the rest can change rendering. A diff whose DOM is identical, whose computed styles match and whose rendering environment changed is now rendering drift in the HTML report, @testivai/mcp (get_visual_results verdicts, its grouping and a new opening line when several snapshots share one change; explain_snapshot's new layers.environment; the triage-visual-diff rubric) and the GitHub Action comment, never "likely render noise"; a size change from another capture method says so instead of "page grew". New config environmentPolicy: "warn" (default) never changes a status; "separate" keys snapshots <name>__<browser>__<platform> (never by version) and reports missing only the baselines of an environment the run captured; "strict" makes a rendering change of environment changed whatever its pixels say. New testivai env prints this machine's part of the block (--fonts adds a fingerprint of the installed fonts, --json for machines). @testivai/witness exports the collectors (collectHostEnvironment, RENDER_PROBE_EXPRESSION, browserFromCapabilities, webDriverEnvironment, applyEnvironmentPolicyToName, …) and @testivai/witness/report the readings (diffEnvironments, isRenderingDrift, environmentChangeGroups, environmentChangeLine, …). BaselineStore gains writeTempMetadata and readTempMetadata. The WebdriverIO and Selenium WitnessBrowser / WitnessDriver types gain the optional capabilities / getCapabilities() they read the browser from. The Python, Ruby and Java adapters do not record the block yet; their captures compare exactly as before.
  • Updated dependencies [cd9ffe7]
  • Updated dependencies [c05d870]
    • @testivai/witness@2.5.0

@testivai/witness-playwright@2.0.10

Choose a tag to compare

@github-actions github-actions released this 19 Oct 14:14
e90e959

Patch Changes

  • cd9ffe7: Capture provenance: every capture now records where it came from, and the report says when a diff is the machine changing rather than the page. The Playwright, WebdriverIO and Selenium (JS) adapters and testivai witness <url> write an environment block into the capture's metadata.json: the OS (and the Linux distro), the browser and its version (and the WebDriver binary), the test framework, the adapter and how it took the screenshot (full-page:cdp, full-page:playwright, full-page:stitched, viewport:webdriver), what the page was rendered with (viewport, device scale, color scheme, reduced motion, locale, time zone, measured in the page), the CI provider and runner image, a container, and TESTIVAI_ENV_LABEL. Approving a capture freezes its block into the baseline's metadata.json (and drops a stale one). The compare reads both blocks: results.json schema 2.5.0 (additive) adds snapshots[].environment (delta, renderingDelta, both blocks when they differ) and a run-level environment (the fields every capture of the run agrees on). Framework, adapter and driver versions, the CI runner image, the project and the Linux kernel are context; the rest can change rendering. A diff whose DOM is identical, whose computed styles match and whose rendering environment changed is now rendering drift in the HTML report, @testivai/mcp (get_visual_results verdicts, its grouping and a new opening line when several snapshots share one change; explain_snapshot's new layers.environment; the triage-visual-diff rubric) and the GitHub Action comment, never "likely render noise"; a size change from another capture method says so instead of "page grew". New config environmentPolicy: "warn" (default) never changes a status; "separate" keys snapshots <name>__<browser>__<platform> (never by version) and reports missing only the baselines of an environment the run captured; "strict" makes a rendering change of environment changed whatever its pixels say. New testivai env prints this machine's part of the block (--fonts adds a fingerprint of the installed fonts, --json for machines). @testivai/witness exports the collectors (collectHostEnvironment, RENDER_PROBE_EXPRESSION, browserFromCapabilities, webDriverEnvironment, applyEnvironmentPolicyToName, …) and @testivai/witness/report the readings (diffEnvironments, isRenderingDrift, environmentChangeGroups, environmentChangeLine, …). BaselineStore gains writeTempMetadata and readTempMetadata. The WebdriverIO and Selenium WitnessBrowser / WitnessDriver types gain the optional capabilities / getCapabilities() they read the browser from. The Python, Ruby and Java adapters do not record the block yet; their captures compare exactly as before.
  • Updated dependencies [cd9ffe7]
  • Updated dependencies [c05d870]
    • @testivai/witness@2.5.0

@testivai/mcp@0.9.0

Choose a tag to compare

@github-actions github-actions released this 19 Oct 14:14
e90e959

Minor Changes

  • d8bd6b1: get_diff (and its alias get_snapshot_diff) now makes tall full-page captures readable. It still sends the baseline, current and diff images downscaled to fit (a 390×11844 mobile page becomes about 33×987 px, which shows where the changes are but not what they say), and then, when an image had to be downscaled, lists the snapshot's regions and crops them at native scale, one image pixel per page pixel, so a reviewer can check text, wrapping and clipping (a page that fits within 1024 px is already sent at native scale and gets no crops, as before). Each crop is a region plus 32 px on every side, made as wide as the page (up to 1280 px) so whole lines show, and labelled with its box and the region's selector; regions whose padded areas meet share a crop while it fits 1280×1024 px, a region inside a box another crop shows joins it, and changes come before shifts. The response stays bounded: up to 3 crops per call, each at most 1280×1024 px and 2,000,000 px in all; an area wider than 1280 px is sampled at 1/2 scale or smaller, and a taller one shows its top rows and gives the y to continue from. After a size change each capture is cut to its own bounds, and a crop of the padded band says the shorter capture has no pixels there. New optional inputs fetch one area on demand, without the full-page images: region (an index the response lists) or y and height (a full-width band, which works on a new snapshot too). An image that is not a PNG is now said instead of failing the call. The triage-visual-diff rubric, shared with the review action, tells the model to judge text, wrapping and clipping from the crops. Found when the review action triaged testivai/testivai-site#20 and could only judge one page, at thumbnail scale.

Patch Changes

  • cd9ffe7: Capture provenance: every capture now records where it came from, and the report says when a diff is the machine changing rather than the page. The Playwright, WebdriverIO and Selenium (JS) adapters and testivai witness <url> write an environment block into the capture's metadata.json: the OS (and the Linux distro), the browser and its version (and the WebDriver binary), the test framework, the adapter and how it took the screenshot (full-page:cdp, full-page:playwright, full-page:stitched, viewport:webdriver), what the page was rendered with (viewport, device scale, color scheme, reduced motion, locale, time zone, measured in the page), the CI provider and runner image, a container, and TESTIVAI_ENV_LABEL. Approving a capture freezes its block into the baseline's metadata.json (and drops a stale one). The compare reads both blocks: results.json schema 2.5.0 (additive) adds snapshots[].environment (delta, renderingDelta, both blocks when they differ) and a run-level environment (the fields every capture of the run agrees on). Framework, adapter and driver versions, the CI runner image, the project and the Linux kernel are context; the rest can change rendering. A diff whose DOM is identical, whose computed styles match and whose rendering environment changed is now rendering drift in the HTML report, @testivai/mcp (get_visual_results verdicts, its grouping and a new opening line when several snapshots share one change; explain_snapshot's new layers.environment; the triage-visual-diff rubric) and the GitHub Action comment, never "likely render noise"; a size change from another capture method says so instead of "page grew". New config environmentPolicy: "warn" (default) never changes a status; "separate" keys snapshots <name>__<browser>__<platform> (never by version) and reports missing only the baselines of an environment the run captured; "strict" makes a rendering change of environment changed whatever its pixels say. New testivai env prints this machine's part of the block (--fonts adds a fingerprint of the installed fonts, --json for machines). @testivai/witness exports the collectors (collectHostEnvironment, RENDER_PROBE_EXPRESSION, browserFromCapabilities, webDriverEnvironment, applyEnvironmentPolicyToName, …) and @testivai/witness/report the readings (diffEnvironments, isRenderingDrift, environmentChangeGroups, environmentChangeLine, …). BaselineStore gains writeTempMetadata and readTempMetadata. The WebdriverIO and Selenium WitnessBrowser / WitnessDriver types gain the optional capabilities / getCapabilities() they read the browser from. The Python, Ruby and Java adapters do not record the block yet; their captures compare exactly as before.
  • c439e08: The triage rubric (the triage-visual-diff prompt, shared with the review action) now says what an unchanged DOM rules out. No element, attribute or text differs between the baseline and the current capture, and the baseline is the last approved capture, which can already contain the change under test. So a text or markup edit in the change never explains an identical-DOM diff, even where its regions sit on text the change edited. Only something the DOM does not record can: a stylesheet change the style check does not cover, an image, a font or another asset, or the capture. When the change touched none of those, the verdict is a glitch or a possible bug, not an intended change. Found when the CI review of testivai-site#20 called a re-capture of already-approved copy an intended change because the pull request edited that text.
  • Updated dependencies [cd9ffe7]
  • Updated dependencies [c05d870]
    • @testivai/witness@2.5.0