snapdrift 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,17 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.5.1 - 2026-07-14
6
+
7
+ ### Fixes
8
+
9
+ - **Stale-capture false-negative guard (#93)** — capture logs now print the fully resolved target URL per route (`... -> https://.../path`), so a `baseUrl` pointing at production instead of the PR preview is visible at a glance. Additionally, `SnapProvider.diff` now emits a warning when a diff run compared more than one route against a real baseline yet every comparison came back pixel-identical (0% drift) — the tell-tale signature of capturing a stale or wrong page rather than a genuine "no change". The guard only warns (never fails), since a PR with no visual change legitimately produces the same shape.
10
+
11
+ ### Dependencies
12
+
13
+ - Updated `js-yaml` from 4.1.0 to 5.2.1, including ESM import compatibility changes.
14
+ - Updated the pinned `actions/checkout` action from v6.0.3 to v7.0.0.
15
+
5
16
  ## 0.5.0 - 2026-06-08
6
17
 
7
18
  ### Features
@@ -2,7 +2,7 @@
2
2
 
3
3
  import fs from 'node:fs/promises';
4
4
  import path from 'node:path';
5
- import yaml from 'js-yaml';
5
+ import * as yaml from 'js-yaml';
6
6
 
7
7
  /** @typedef {import('../types/visual-diff-types').InitWarning} InitWarning */
8
8
 
@@ -870,6 +870,11 @@ export class SnapProvider {
870
870
  let changedScreenshots = 0;
871
871
  let missingInBaseline = 0;
872
872
  let missingInCurrent = 0;
873
+ // Track real comparisons (a baseline was attached) and how many came back
874
+ // pixel-identical (0% drift) so we can flag the "captured a stale/wrong
875
+ // page" pattern below. See issue #93.
876
+ let comparedWithBaseline = 0;
877
+ let exactZeroMatches = 0;
873
878
 
874
879
  /** @type {import('../types/visual-diff-types').VisualDiffChangedItem[]} */
875
880
  const changed = [];
@@ -919,6 +924,7 @@ export class SnapProvider {
919
924
  location: 'baseline'
920
925
  });
921
926
  } else if (capture.diffPct != null && capture.diffPct > config.diff.threshold) {
927
+ comparedWithBaseline++;
922
928
  changedScreenshots++;
923
929
  changed.push({
924
930
  id: capture.routeId || capture.id,
@@ -934,11 +940,35 @@ export class SnapProvider {
934
940
  status: 'changed'
935
941
  });
936
942
  } else {
943
+ comparedWithBaseline++;
944
+ if (capture.diffPct === 0) {
945
+ exactZeroMatches++;
946
+ }
937
947
  matchedScreenshots++;
938
948
  }
939
949
  }
940
950
  }
941
951
 
952
+ // False-negative guard: when a diff run compared every route against a real
953
+ // baseline yet every single comparison came back pixel-identical (0% drift),
954
+ // the most likely explanation is that the client captured a stale or wrong
955
+ // page (baseUrl pointing at production instead of the PR preview, the
956
+ // preview not being deployed yet, or a caching layer) rather than a genuine
957
+ // "nothing changed". Warn so a real regression isn't silently missed. We
958
+ // only warn (never fail): a PR with no visual change legitimately produces
959
+ // this same shape. We require more than one compared route — a single
960
+ // pixel-identical route is indistinguishable from an ordinary clean diff,
961
+ // whereas several independent routes all landing at exactly 0% is the
962
+ // tell-tale signature of a single stale source page. See issue #93.
963
+ if (comparedWithBaseline > 1 && exactZeroMatches === comparedWithBaseline) {
964
+ process.stderr.write(
965
+ `[SnapDrift] Warning: all ${comparedWithBaseline} compared route(s) were pixel-identical ` +
966
+ `to the baseline (0% drift). If you expected a visual change, the captured page may be ` +
967
+ `stale or wrong — verify the resolved baseUrl points at the PR preview and that the ` +
968
+ `preview was deployed before capture ran. See issue #93.\n`
969
+ );
970
+ }
971
+
942
972
  /** @type {import('../types/visual-diff-types').VisualDiffSummary} */
943
973
  const summary = {
944
974
  startedAt: run.startedAt || new Date().toISOString(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "snapdrift",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "SnapDrift captures, compares, and reports UI drift for Playwright-based app checks.",
@@ -41,7 +41,7 @@
41
41
  "@eslint/js": "^10.0.1",
42
42
  "@types/jest": "^30.0.0",
43
43
  "@types/js-yaml": "^4.0.9",
44
- "@types/node": "^25.3.5",
44
+ "@types/node": "^26.1.0",
45
45
  "@types/pngjs": "^6.0.5",
46
46
  "eslint": "^10.2.0",
47
47
  "globals": "^17.4.0",
@@ -95,11 +95,11 @@
95
95
  "registry": "https://registry.npmjs.org"
96
96
  },
97
97
  "dependencies": {
98
- "@snapdrift/adapter-fs": "^1.0.0",
98
+ "@snapdrift/adapter-fs": "^1.0.1",
99
99
  "@snapdrift/adapter-report-md": "^1.1.0",
100
100
  "@snapdrift/compare-core": "^1.0.0",
101
101
  "@snapdrift/manifest": "^1.2.0",
102
- "js-yaml": "^4.1.0",
102
+ "js-yaml": "^5.2.1",
103
103
  "playwright": "^1.59.1",
104
104
  "pngjs": "^7.0.0"
105
105
  }