userflow-mcp 0.2.1 → 0.3.0

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.
Files changed (59) hide show
  1. package/dist/feedback/generator.d.ts.map +1 -1
  2. package/dist/feedback/generator.js +105 -0
  3. package/dist/feedback/generator.js.map +1 -1
  4. package/dist/feedback/html-report.d.ts +8 -0
  5. package/dist/feedback/html-report.d.ts.map +1 -0
  6. package/dist/feedback/html-report.js +200 -0
  7. package/dist/feedback/html-report.js.map +1 -0
  8. package/dist/server.d.ts.map +1 -1
  9. package/dist/server.js +241 -15
  10. package/dist/server.js.map +1 -1
  11. package/dist/session/session-manager.d.ts +18 -1
  12. package/dist/session/session-manager.d.ts.map +1 -1
  13. package/dist/session/session-manager.js +61 -5
  14. package/dist/session/session-manager.js.map +1 -1
  15. package/dist/session/types.d.ts +4 -0
  16. package/dist/session/types.d.ts.map +1 -1
  17. package/dist/types.d.ts +159 -36
  18. package/dist/types.d.ts.map +1 -1
  19. package/dist/utils/accessibility.d.ts +43 -0
  20. package/dist/utils/accessibility.d.ts.map +1 -0
  21. package/dist/utils/accessibility.js +72 -0
  22. package/dist/utils/accessibility.js.map +1 -0
  23. package/dist/utils/actions.d.ts +2 -0
  24. package/dist/utils/actions.d.ts.map +1 -1
  25. package/dist/utils/actions.js +47 -13
  26. package/dist/utils/actions.js.map +1 -1
  27. package/dist/utils/console-monitor.d.ts +44 -0
  28. package/dist/utils/console-monitor.d.ts.map +1 -0
  29. package/dist/utils/console-monitor.js +90 -0
  30. package/dist/utils/console-monitor.js.map +1 -0
  31. package/dist/utils/device-profiles.d.ts +43 -0
  32. package/dist/utils/device-profiles.d.ts.map +1 -0
  33. package/dist/utils/device-profiles.js +132 -0
  34. package/dist/utils/device-profiles.js.map +1 -0
  35. package/dist/utils/network-monitor.d.ts +121 -0
  36. package/dist/utils/network-monitor.d.ts.map +1 -0
  37. package/dist/utils/network-monitor.js +238 -0
  38. package/dist/utils/network-monitor.js.map +1 -0
  39. package/dist/utils/page-snapshot.d.ts +12 -5
  40. package/dist/utils/page-snapshot.d.ts.map +1 -1
  41. package/dist/utils/page-snapshot.js +43 -2
  42. package/dist/utils/page-snapshot.js.map +1 -1
  43. package/dist/utils/performance.d.ts +43 -0
  44. package/dist/utils/performance.d.ts.map +1 -0
  45. package/dist/utils/performance.js +108 -0
  46. package/dist/utils/performance.js.map +1 -0
  47. package/dist/utils/screenshot-diff.d.ts +36 -0
  48. package/dist/utils/screenshot-diff.d.ts.map +1 -0
  49. package/dist/utils/screenshot-diff.js +62 -0
  50. package/dist/utils/screenshot-diff.js.map +1 -0
  51. package/dist/utils/selector-engine.d.ts +53 -0
  52. package/dist/utils/selector-engine.d.ts.map +1 -0
  53. package/dist/utils/selector-engine.js +180 -0
  54. package/dist/utils/selector-engine.js.map +1 -0
  55. package/dist/utils/storage-inspector.d.ts +47 -0
  56. package/dist/utils/storage-inspector.d.ts.map +1 -0
  57. package/dist/utils/storage-inspector.js +71 -0
  58. package/dist/utils/storage-inspector.js.map +1 -0
  59. package/package.json +5 -1
@@ -1,11 +1,18 @@
1
1
  import type { Page } from "puppeteer-core";
2
2
  import type { PageSnapshot } from "../types.js";
3
+ import type { NetworkMonitor } from "./network-monitor.js";
4
+ import type { ConsoleMonitor } from "./console-monitor.js";
5
+ export interface SnapshotOptions {
6
+ readonly fullPage?: boolean;
7
+ readonly networkMonitor?: NetworkMonitor;
8
+ readonly consoleMonitor?: ConsoleMonitor;
9
+ /** Skip heavy audits (accessibility, storage) for faster snapshots during steps. */
10
+ readonly lightweight?: boolean;
11
+ }
3
12
  /**
4
13
  * Extract a full snapshot of the current page state.
5
- * Gathers all interactive elements, text content, headings, error messages, etc.
6
- * Shared between session manager (step-by-step) and legacy flow walker (auto_walk).
14
+ * Gathers all interactive elements, text content, headings, error messages,
15
+ * plus optional v0.3 data: performance metrics, accessibility, network, console, storage.
7
16
  */
8
- export declare function extractPageSnapshot(page: Page, options?: {
9
- readonly fullPage?: boolean;
10
- }): Promise<PageSnapshot>;
17
+ export declare function extractPageSnapshot(page: Page, options?: SnapshotOptions): Promise<PageSnapshot>;
11
18
  //# sourceMappingURL=page-snapshot.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"page-snapshot.d.ts","sourceRoot":"","sources":["../../src/utils/page-snapshot.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAe,MAAM,aAAa,CAAC;AAE7D;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,IAAI,EACV,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,GACxC,OAAO,CAAC,YAAY,CAAC,CA4GvB"}
1
+ {"version":3,"file":"page-snapshot.d.ts","sourceRoot":"","sources":["../../src/utils/page-snapshot.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAe,MAAM,aAAa,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAK3D,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,cAAc,CAAC,EAAE,cAAc,CAAC;IACzC,QAAQ,CAAC,cAAc,CAAC,EAAE,cAAc,CAAC;IACzC,oFAAoF;IACpF,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;CAChC;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,IAAI,EACV,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,YAAY,CAAC,CAqJvB"}
@@ -1,7 +1,10 @@
1
+ import { collectPerformanceMetrics } from "./performance.js";
2
+ import { runAccessibilityAudit } from "./accessibility.js";
3
+ import { inspectStorage } from "./storage-inspector.js";
1
4
  /**
2
5
  * Extract a full snapshot of the current page state.
3
- * Gathers all interactive elements, text content, headings, error messages, etc.
4
- * Shared between session manager (step-by-step) and legacy flow walker (auto_walk).
6
+ * Gathers all interactive elements, text content, headings, error messages,
7
+ * plus optional v0.3 data: performance metrics, accessibility, network, console, storage.
5
8
  */
6
9
  export async function extractPageSnapshot(page, options) {
7
10
  const startTime = Date.now();
@@ -84,6 +87,39 @@ export async function extractPageSnapshot(page, options) {
84
87
  });
85
88
  const screenshot = Buffer.from(screenshotBuffer).toString("base64");
86
89
  const loadTimeMs = Date.now() - startTime;
90
+ // ── v0.3 enrichment: collect performance, network, console, storage, a11y ──
91
+ // Performance metrics (always collected — lightweight)
92
+ let performance = undefined;
93
+ try {
94
+ performance = await collectPerformanceMetrics(page);
95
+ }
96
+ catch {
97
+ // Performance collection may fail on some pages — graceful degradation
98
+ }
99
+ // Network summary (from monitor if available)
100
+ const network = options?.networkMonitor?.getSummary() ?? undefined;
101
+ // Console summary (from monitor if available)
102
+ const console = options?.consoleMonitor?.getSummary() ?? undefined;
103
+ // Accessibility audit (skip in lightweight mode to keep step speed)
104
+ let accessibility = undefined;
105
+ if (!options?.lightweight) {
106
+ try {
107
+ accessibility = await runAccessibilityAudit(page);
108
+ }
109
+ catch {
110
+ // axe-core injection may fail on some pages
111
+ }
112
+ }
113
+ // Storage inspection (skip in lightweight mode)
114
+ let storage = undefined;
115
+ if (!options?.lightweight) {
116
+ try {
117
+ storage = await inspectStorage(page);
118
+ }
119
+ catch {
120
+ // Storage inspection may fail on cross-origin pages
121
+ }
122
+ }
87
123
  return {
88
124
  url,
89
125
  title,
@@ -97,6 +133,11 @@ export async function extractPageSnapshot(page, options) {
97
133
  buttons: pageData.buttons,
98
134
  errorMessages: pageData.errorMessages,
99
135
  loadTimeMs,
136
+ performance,
137
+ network,
138
+ console,
139
+ accessibility,
140
+ storage,
100
141
  };
101
142
  }
102
143
  //# sourceMappingURL=page-snapshot.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"page-snapshot.js","sourceRoot":"","sources":["../../src/utils/page-snapshot.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"page-snapshot.js","sourceRoot":"","sources":["../../src/utils/page-snapshot.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ import type { Page } from "puppeteer-core";
2
+ export interface PerformanceMetrics {
3
+ /** Largest Contentful Paint (ms) */
4
+ lcp: number | null;
5
+ /** Cumulative Layout Shift (unitless score) */
6
+ cls: number | null;
7
+ /** Interaction to Next Paint (ms) */
8
+ inp: number | null;
9
+ /** First Contentful Paint (ms) */
10
+ fcp: number | null;
11
+ /** Time to First Byte (ms) */
12
+ ttfb: number | null;
13
+ /** DOMContentLoaded relative to navigationStart (ms) */
14
+ domContentLoaded: number | null;
15
+ /** domComplete relative to navigationStart (ms) */
16
+ domComplete: number | null;
17
+ /** Total number of resources loaded */
18
+ resourceCount: number;
19
+ /** Total transfer size of all resources (bytes) */
20
+ totalResourceSize: number;
21
+ /** LCP quality rating per Google's thresholds */
22
+ lcpRating: "good" | "needs-improvement" | "poor" | null;
23
+ /** CLS quality rating per Google's thresholds */
24
+ clsRating: "good" | "needs-improvement" | "poor" | null;
25
+ /** INP quality rating per Google's thresholds */
26
+ inpRating: "good" | "needs-improvement" | "poor" | null;
27
+ }
28
+ /**
29
+ * Inject PerformanceObservers into every new document before navigation.
30
+ *
31
+ * Must be called before `page.goto()`. Stores collected values on
32
+ * `window.__userflow_perf` so they can be read by `collectPerformanceMetrics`.
33
+ */
34
+ export declare function injectPerformanceObservers(page: Page): Promise<void>;
35
+ /**
36
+ * Read all performance metrics from the page after it has loaded.
37
+ *
38
+ * Combines values captured by `injectPerformanceObservers` with
39
+ * Navigation Timing and Resource Timing data from the browser's
40
+ * Performance API. Missing or unsupported metrics are returned as `null`.
41
+ */
42
+ export declare function collectPerformanceMetrics(page: Page): Promise<PerformanceMetrics>;
43
+ //# sourceMappingURL=performance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"performance.d.ts","sourceRoot":"","sources":["../../src/utils/performance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAI3C,MAAM,WAAW,kBAAkB;IACjC,oCAAoC;IACpC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,+CAA+C;IAC/C,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,qCAAqC;IACrC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,kCAAkC;IAClC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,8BAA8B;IAC9B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,wDAAwD;IACxD,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,mDAAmD;IACnD,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,uCAAuC;IACvC,aAAa,EAAE,MAAM,CAAC;IACtB,mDAAmD;IACnD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iDAAiD;IACjD,SAAS,EAAE,MAAM,GAAG,mBAAmB,GAAG,MAAM,GAAG,IAAI,CAAC;IACxD,iDAAiD;IACjD,SAAS,EAAE,MAAM,GAAG,mBAAmB,GAAG,MAAM,GAAG,IAAI,CAAC;IACxD,iDAAiD;IACjD,SAAS,EAAE,MAAM,GAAG,mBAAmB,GAAG,MAAM,GAAG,IAAI,CAAC;CACzD;AA0BD;;;;;GAKG;AACH,wBAAsB,0BAA0B,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CA2B1E;AAID;;;;;;GAMG;AACH,wBAAsB,yBAAyB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAmDvF"}
@@ -0,0 +1,108 @@
1
+ function rateLcp(ms) {
2
+ if (ms <= 2500)
3
+ return "good";
4
+ if (ms <= 4000)
5
+ return "needs-improvement";
6
+ return "poor";
7
+ }
8
+ function rateCls(score) {
9
+ if (score <= 0.1)
10
+ return "good";
11
+ if (score <= 0.25)
12
+ return "needs-improvement";
13
+ return "poor";
14
+ }
15
+ function rateInp(ms) {
16
+ if (ms <= 200)
17
+ return "good";
18
+ if (ms <= 500)
19
+ return "needs-improvement";
20
+ return "poor";
21
+ }
22
+ // ── Observer injection ─────────────────────────────────────────
23
+ /**
24
+ * Inject PerformanceObservers into every new document before navigation.
25
+ *
26
+ * Must be called before `page.goto()`. Stores collected values on
27
+ * `window.__userflow_perf` so they can be read by `collectPerformanceMetrics`.
28
+ */
29
+ export async function injectPerformanceObservers(page) {
30
+ await page.evaluateOnNewDocument(() => {
31
+ const store = { lcp: null, cls: null, inp: null };
32
+ // @ts-expect-error — injected global not in Window typings
33
+ window.__userflow_perf = store;
34
+ const observe = (type, opts, cb) => {
35
+ try {
36
+ new PerformanceObserver((l) => l.getEntries().forEach(cb)).observe({ type, buffered: true, ...opts });
37
+ }
38
+ catch { /* entry type unsupported in this browser */ }
39
+ };
40
+ // LCP — last entry wins (browser re-fires until first user interaction)
41
+ observe("largest-contentful-paint", {}, (e) => { store.lcp = e.startTime; });
42
+ // CLS — accumulate shifts not preceded by user input
43
+ observe("layout-shift", {}, (e) => {
44
+ const s = e;
45
+ if (!s.hadRecentInput)
46
+ store.cls = (store.cls ?? 0) + s.value;
47
+ });
48
+ // INP — worst (max) event duration; durationThreshold cast needed for older TS lib defs
49
+ observe("event", { durationThreshold: 16 }, (e) => {
50
+ const d = e.duration;
51
+ if (store.inp === null || d > store.inp)
52
+ store.inp = d;
53
+ });
54
+ });
55
+ }
56
+ // ── Metric collection ──────────────────────────────────────────
57
+ /**
58
+ * Read all performance metrics from the page after it has loaded.
59
+ *
60
+ * Combines values captured by `injectPerformanceObservers` with
61
+ * Navigation Timing and Resource Timing data from the browser's
62
+ * Performance API. Missing or unsupported metrics are returned as `null`.
63
+ */
64
+ export async function collectPerformanceMetrics(page) {
65
+ const raw = await page.evaluate(() => {
66
+ // Observed vitals written by the injected PerformanceObservers
67
+ const vitals = window
68
+ .__userflow_perf ?? { lcp: null, cls: null, inp: null };
69
+ // Navigation Timing (Level 2)
70
+ const [navEntry] = performance.getEntriesByType("navigation");
71
+ const ttfb = navEntry ? navEntry.responseStart - navEntry.requestStart : null;
72
+ const domContentLoaded = navEntry ? navEntry.domContentLoadedEventEnd - navEntry.startTime : null;
73
+ const domComplete = navEntry ? navEntry.domComplete - navEntry.startTime : null;
74
+ // FCP via paint entries
75
+ const fcpEntry = performance.getEntriesByName("first-contentful-paint")[0];
76
+ const fcp = fcpEntry ? fcpEntry.startTime : null;
77
+ // Resource summary
78
+ const resources = performance.getEntriesByType("resource");
79
+ const resourceCount = resources.length;
80
+ const totalResourceSize = resources.reduce((sum, r) => sum + (r.transferSize ?? 0), 0);
81
+ return {
82
+ lcp: vitals.lcp,
83
+ cls: vitals.cls,
84
+ inp: vitals.inp,
85
+ fcp,
86
+ ttfb,
87
+ domContentLoaded,
88
+ domComplete,
89
+ resourceCount,
90
+ totalResourceSize,
91
+ };
92
+ });
93
+ return {
94
+ lcp: raw.lcp,
95
+ cls: raw.cls,
96
+ inp: raw.inp,
97
+ fcp: raw.fcp,
98
+ ttfb: raw.ttfb,
99
+ domContentLoaded: raw.domContentLoaded,
100
+ domComplete: raw.domComplete,
101
+ resourceCount: raw.resourceCount,
102
+ totalResourceSize: raw.totalResourceSize,
103
+ lcpRating: raw.lcp !== null ? rateLcp(raw.lcp) : null,
104
+ clsRating: raw.cls !== null ? rateCls(raw.cls) : null,
105
+ inpRating: raw.inp !== null ? rateInp(raw.inp) : null,
106
+ };
107
+ }
108
+ //# sourceMappingURL=performance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"performance.js","sourceRoot":"","sources":["../../src/utils/performance.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Visual screenshot comparison using pixelmatch and pngjs.
3
+ *
4
+ * Accepts two base64-encoded PNG screenshots, optionally pads the smaller
5
+ * one to match dimensions, computes a pixel-level diff, and returns match
6
+ * statistics together with a base64-encoded diff-overlay image.
7
+ */
8
+ /** Result of a pixel-level screenshot comparison. */
9
+ export interface ScreenshotDiff {
10
+ /** Percentage of matching pixels (0 = no match, 100 = identical). */
11
+ matchPercentage: number;
12
+ /** Number of pixels that differ beyond the threshold. */
13
+ diffPixels: number;
14
+ /** Total number of pixels in the (possibly padded) canvas. */
15
+ totalPixels: number;
16
+ dimensions: {
17
+ width: number;
18
+ height: number;
19
+ };
20
+ /** Base64-encoded PNG highlighting differing pixels in red. */
21
+ diffImage: string;
22
+ }
23
+ /**
24
+ * Compares two base64-encoded PNG screenshots and produces a visual diff.
25
+ *
26
+ * When the images have different dimensions the smaller one is padded with
27
+ * transparent pixels so both canvases share the same bounding box before
28
+ * comparison.
29
+ *
30
+ * @param screenshot1 - Base64-encoded PNG (first / "before" image).
31
+ * @param screenshot2 - Base64-encoded PNG (second / "after" image).
32
+ * @param threshold - Per-channel colour tolerance in [0, 1]. Defaults to 0.1.
33
+ * @returns Diff statistics and a base64 diff-overlay image.
34
+ */
35
+ export declare function compareScreenshots(screenshot1: string, screenshot2: string, threshold?: number): Promise<ScreenshotDiff>;
36
+ //# sourceMappingURL=screenshot-diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"screenshot-diff.d.ts","sourceRoot":"","sources":["../../src/utils/screenshot-diff.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,qDAAqD;AACrD,MAAM,WAAW,cAAc;IAC7B,qEAAqE;IACrE,eAAe,EAAE,MAAM,CAAC;IACxB,yDAAyD;IACzD,UAAU,EAAE,MAAM,CAAC;IACnB,8DAA8D;IAC9D,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9C,+DAA+D;IAC/D,SAAS,EAAE,MAAM,CAAC;CACnB;AAwBD;;;;;;;;;;;GAWG;AACH,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,SAAS,SAAM,GACd,OAAO,CAAC,cAAc,CAAC,CAoCzB"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Visual screenshot comparison using pixelmatch and pngjs.
3
+ *
4
+ * Accepts two base64-encoded PNG screenshots, optionally pads the smaller
5
+ * one to match dimensions, computes a pixel-level diff, and returns match
6
+ * statistics together with a base64-encoded diff-overlay image.
7
+ */
8
+ import pixelmatch from "pixelmatch";
9
+ import { PNG } from "pngjs";
10
+ /** Decodes a base64 PNG string into a `pngjs` `PNG` object. */
11
+ function decodePng(base64) {
12
+ const buffer = Buffer.from(base64, "base64");
13
+ return PNG.sync.read(buffer);
14
+ }
15
+ /**
16
+ * Pads a PNG canvas to the target dimensions by copying pixels into a new,
17
+ * zero-initialised (transparent black) buffer. Returns the original PNG
18
+ * unchanged when it already matches the target size.
19
+ */
20
+ function padPng(png, width, height) {
21
+ if (png.width === width && png.height === height)
22
+ return png;
23
+ const padded = new PNG({ width, height });
24
+ // Zero-fill guarantees transparent black padding pixels.
25
+ padded.data.fill(0);
26
+ PNG.bitblt(png, padded, 0, 0, Math.min(png.width, width), Math.min(png.height, height), 0, 0);
27
+ return padded;
28
+ }
29
+ /**
30
+ * Compares two base64-encoded PNG screenshots and produces a visual diff.
31
+ *
32
+ * When the images have different dimensions the smaller one is padded with
33
+ * transparent pixels so both canvases share the same bounding box before
34
+ * comparison.
35
+ *
36
+ * @param screenshot1 - Base64-encoded PNG (first / "before" image).
37
+ * @param screenshot2 - Base64-encoded PNG (second / "after" image).
38
+ * @param threshold - Per-channel colour tolerance in [0, 1]. Defaults to 0.1.
39
+ * @returns Diff statistics and a base64 diff-overlay image.
40
+ */
41
+ export async function compareScreenshots(screenshot1, screenshot2, threshold = 0.1) {
42
+ const png1 = decodePng(screenshot1);
43
+ const png2 = decodePng(screenshot2);
44
+ // Compute the bounding box that encloses both images.
45
+ const width = Math.max(png1.width, png2.width);
46
+ const height = Math.max(png1.height, png2.height);
47
+ const padded1 = padPng(png1, width, height);
48
+ const padded2 = padPng(png2, width, height);
49
+ const diff = new PNG({ width, height });
50
+ const totalPixels = width * height;
51
+ const diffPixels = pixelmatch(padded1.data, padded2.data, diff.data, width, height, { threshold, includeAA: false });
52
+ const matchPercentage = parseFloat((((totalPixels - diffPixels) / totalPixels) * 100).toFixed(2));
53
+ const diffImage = PNG.sync.write(diff).toString("base64");
54
+ return {
55
+ matchPercentage,
56
+ diffPixels,
57
+ totalPixels,
58
+ dimensions: { width, height },
59
+ diffImage,
60
+ };
61
+ }
62
+ //# sourceMappingURL=screenshot-diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"screenshot-diff.js","sourceRoot":"","sources":["../../src/utils/screenshot-diff.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,UAAU,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAe5B,+DAA+D;AAC/D,SAAS,SAAS,CAAC,MAAc;IAC/B,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC7C,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC/B,CAAC;AAED;;;;GAIG;AACH,SAAS,MAAM,CAAC,GAAQ,EAAE,KAAa,EAAE,MAAc;IACrD,IAAI,GAAG,CAAC,KAAK,KAAK,KAAK,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM;QAAE,OAAO,GAAG,CAAC;IAE7D,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IAC1C,yDAAyD;IACzD,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAEpB,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC9F,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,WAAmB,EACnB,WAAmB,EACnB,SAAS,GAAG,GAAG;IAEf,MAAM,IAAI,GAAG,SAAS,CAAC,WAAW,CAAC,CAAC;IACpC,MAAM,IAAI,GAAG,SAAS,CAAC,WAAW,CAAC,CAAC;IAEpC,sDAAsD;IACtD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAElD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IAE5C,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IACxC,MAAM,WAAW,GAAG,KAAK,GAAG,MAAM,CAAC;IAEnC,MAAM,UAAU,GAAG,UAAU,CAC3B,OAAO,CAAC,IAAI,EACZ,OAAO,CAAC,IAAI,EACZ,IAAI,CAAC,IAAI,EACT,KAAK,EACL,MAAM,EACN,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,CAChC,CAAC;IAEF,MAAM,eAAe,GAAG,UAAU,CAChC,CAAC,CAAC,CAAC,WAAW,GAAG,UAAU,CAAC,GAAG,WAAW,CAAC,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAC9D,CAAC;IAEF,MAAM,SAAS,GAAG,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAE1D,OAAO;QACL,eAAe;QACf,UAAU;QACV,WAAW;QACX,UAAU,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE;QAC7B,SAAS;KACV,CAAC;AACJ,CAAC"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Smart Selector Engine for Puppeteer
3
+ *
4
+ * Generates reliable, fallback-capable selectors that survive styled-components
5
+ * and dynamic class names. Each element gets multiple selector strategies tried
6
+ * in priority order, from most stable to least stable.
7
+ */
8
+ import type { Page, ElementHandle } from "puppeteer-core";
9
+ export interface SmartSelector {
10
+ /** The best selector to try first. */
11
+ primary: string;
12
+ /** Ordered list of alternatives to try if primary fails. */
13
+ fallbacks: string[];
14
+ /** Human-readable description of what the element is. */
15
+ description: string;
16
+ /** Strategy used to derive the primary selector. */
17
+ strategy: "testid" | "id" | "aria" | "role-text" | "input-attr" | "link-href" | "text" | "css";
18
+ }
19
+ /**
20
+ * Generates multiple selector strategies for an element.
21
+ * Designed to run inside `page.evaluate()` — has no Node.js dependencies.
22
+ *
23
+ * Priority order (most → least stable):
24
+ * 1. data-testid
25
+ * 2. Unique id
26
+ * 3. aria-label / aria-labelledby
27
+ * 4. role + visible text
28
+ * 5. input type + name or placeholder
29
+ * 6. anchor href
30
+ * 7. Puppeteer text pseudo-selector
31
+ * 8. Minimal CSS path (fallback)
32
+ */
33
+ export declare function generateSmartSelectors(element: Element): SmartSelector;
34
+ /**
35
+ * Tries to find an element on the page using multiple selector strategies.
36
+ * Returns the first `ElementHandle` that successfully resolves, or `null`.
37
+ *
38
+ * @param page - Puppeteer Page instance.
39
+ * @param target - Primary selector string or SmartSelector.primary.
40
+ * @param fallbacks - Additional selectors to try if primary fails.
41
+ * @param timeout - Per-selector wait timeout in ms (default: 3000).
42
+ */
43
+ export declare function resolveSelector(page: Page, target: string, fallbacks?: string[], timeout?: number): Promise<ElementHandle | null>;
44
+ /**
45
+ * Takes a basic CSS selector (e.g. from a snapshot), injects
46
+ * `generateSmartSelectors` into the page, and returns a richer SmartSelector
47
+ * with stable alternatives.
48
+ *
49
+ * @param page - Puppeteer Page instance.
50
+ * @param cssSelector - Existing (possibly fragile) CSS selector.
51
+ */
52
+ export declare function enhanceElementSelectors(page: Page, cssSelector: string): Promise<SmartSelector>;
53
+ //# sourceMappingURL=selector-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selector-engine.d.ts","sourceRoot":"","sources":["../../src/utils/selector-engine.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAM1D,MAAM,WAAW,aAAa;IAC5B,sCAAsC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,yDAAyD;IACzD,WAAW,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,QAAQ,EAAE,QAAQ,GAAG,IAAI,GAAG,MAAM,GAAG,WAAW,GAAG,YAAY,GAAG,WAAW,GAAG,MAAM,GAAG,KAAK,CAAC;CAChG;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,aAAa,CA2EtE;AAkDD;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM,EACd,SAAS,GAAE,MAAM,EAAO,EACxB,OAAO,SAAQ,GACd,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAa/B;AAED;;;;;;;GAOG;AACH,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,IAAI,EACV,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,aAAa,CAAC,CA0BxB"}
@@ -0,0 +1,180 @@
1
+ /**
2
+ * Smart Selector Engine for Puppeteer
3
+ *
4
+ * Generates reliable, fallback-capable selectors that survive styled-components
5
+ * and dynamic class names. Each element gets multiple selector strategies tried
6
+ * in priority order, from most stable to least stable.
7
+ */
8
+ // ---------------------------------------------------------------------------
9
+ // Browser-context helper (runs inside page.evaluate)
10
+ // ---------------------------------------------------------------------------
11
+ /**
12
+ * Generates multiple selector strategies for an element.
13
+ * Designed to run inside `page.evaluate()` — has no Node.js dependencies.
14
+ *
15
+ * Priority order (most → least stable):
16
+ * 1. data-testid
17
+ * 2. Unique id
18
+ * 3. aria-label / aria-labelledby
19
+ * 4. role + visible text
20
+ * 5. input type + name or placeholder
21
+ * 6. anchor href
22
+ * 7. Puppeteer text pseudo-selector
23
+ * 8. Minimal CSS path (fallback)
24
+ */
25
+ export function generateSmartSelectors(element) {
26
+ const tag = element.tagName.toLowerCase();
27
+ const candidates = [];
28
+ // 1. data-testid (most stable — explicit test hook)
29
+ const testid = element.getAttribute("data-testid") ?? element.getAttribute("data-test-id") ?? element.getAttribute("data-cy");
30
+ if (testid) {
31
+ const attr = element.hasAttribute("data-testid") ? "data-testid" : element.hasAttribute("data-test-id") ? "data-test-id" : "data-cy";
32
+ candidates.push({ selector: `[${attr}="${CSS.escape(testid)}"]`, strategy: "testid" });
33
+ }
34
+ // 2. Unique id attribute
35
+ const id = element.getAttribute("id");
36
+ if (id && document.querySelectorAll(`#${CSS.escape(id)}`).length === 1) {
37
+ candidates.push({ selector: `#${CSS.escape(id)}`, strategy: "id" });
38
+ }
39
+ // 3. aria-label / aria-labelledby
40
+ const ariaLabel = element.getAttribute("aria-label");
41
+ if (ariaLabel) {
42
+ candidates.push({ selector: `[aria-label="${CSS.escape(ariaLabel)}"]`, strategy: "aria" });
43
+ }
44
+ const labelledBy = element.getAttribute("aria-labelledby");
45
+ if (labelledBy) {
46
+ candidates.push({ selector: `[aria-labelledby="${CSS.escape(labelledBy)}"]`, strategy: "aria" });
47
+ }
48
+ // 4. Role + visible text content (for buttons, links, headings, etc.)
49
+ const role = element.getAttribute("role") ?? tag;
50
+ const visibleText = (element.textContent ?? "").trim().slice(0, 80);
51
+ if (visibleText && ["button", "a", "h1", "h2", "h3", "h4", "h5", "h6", "label", "li"].includes(tag)) {
52
+ candidates.push({ selector: `::-p-aria(${visibleText})`, strategy: "role-text" });
53
+ }
54
+ // 5. Input type + name or placeholder
55
+ if (tag === "input" || tag === "textarea" || tag === "select") {
56
+ const name = element.getAttribute("name");
57
+ const placeholder = element.getAttribute("placeholder");
58
+ const type = element.getAttribute("type") ?? "text";
59
+ if (name) {
60
+ candidates.push({ selector: `${tag}[name="${CSS.escape(name)}"]`, strategy: "input-attr" });
61
+ }
62
+ else if (placeholder) {
63
+ candidates.push({ selector: `${tag}[placeholder="${CSS.escape(placeholder)}"]`, strategy: "input-attr" });
64
+ }
65
+ else if (type !== "text") {
66
+ candidates.push({ selector: `${tag}[type="${CSS.escape(type)}"]`, strategy: "input-attr" });
67
+ }
68
+ }
69
+ // 6. Anchor href (for navigation links)
70
+ if (tag === "a") {
71
+ const href = element.getAttribute("href");
72
+ if (href && !href.startsWith("javascript:") && href !== "#") {
73
+ candidates.push({ selector: `a[href="${CSS.escape(href)}"]`, strategy: "link-href" });
74
+ }
75
+ }
76
+ // 7. Puppeteer text pseudo-selector
77
+ if (visibleText) {
78
+ candidates.push({ selector: `::-p-text(${visibleText})`, strategy: "text" });
79
+ }
80
+ // 8. Minimal CSS path (stable ancestor chain, stops at id or body)
81
+ candidates.push({ selector: buildMinimalCssPath(element), strategy: "css" });
82
+ // Build result: first candidate is primary, rest are fallbacks
83
+ const [first, ...rest] = candidates;
84
+ const description = buildDescription(tag, visibleText, ariaLabel, testid, id);
85
+ return {
86
+ primary: first.selector,
87
+ fallbacks: rest.map((c) => c.selector),
88
+ description,
89
+ strategy: first.strategy,
90
+ };
91
+ }
92
+ /** Builds a minimal CSS path by walking up the DOM, stopping at an id anchor or body. */
93
+ function buildMinimalCssPath(el) {
94
+ const parts = [];
95
+ let current = el;
96
+ while (current && current.tagName.toLowerCase() !== "body") {
97
+ const tag = current.tagName.toLowerCase();
98
+ const id = current.getAttribute("id");
99
+ if (id && document.querySelectorAll(`#${CSS.escape(id)}`).length === 1) {
100
+ parts.unshift(`#${CSS.escape(id)}`);
101
+ break;
102
+ }
103
+ // nth-of-type using only the tag (avoids fragile dynamic class names)
104
+ const siblings = Array.from(current.parentElement?.children ?? []).filter((s) => s.tagName === current.tagName);
105
+ if (siblings.length > 1) {
106
+ const idx = siblings.indexOf(current) + 1;
107
+ parts.unshift(`${tag}:nth-of-type(${idx})`);
108
+ }
109
+ else {
110
+ parts.unshift(tag);
111
+ }
112
+ current = current.parentElement;
113
+ }
114
+ return parts.join(" > ") || el.tagName.toLowerCase();
115
+ }
116
+ /** Builds a human-readable description of the element. */
117
+ function buildDescription(tag, text, ariaLabel, testid, id) {
118
+ const label = ariaLabel ?? testid ?? id ?? text;
119
+ if (label)
120
+ return `${tag}[${label.slice(0, 60)}]`;
121
+ return `<${tag}>`;
122
+ }
123
+ // ---------------------------------------------------------------------------
124
+ // Node.js-context helpers (use Page API)
125
+ // ---------------------------------------------------------------------------
126
+ /**
127
+ * Tries to find an element on the page using multiple selector strategies.
128
+ * Returns the first `ElementHandle` that successfully resolves, or `null`.
129
+ *
130
+ * @param page - Puppeteer Page instance.
131
+ * @param target - Primary selector string or SmartSelector.primary.
132
+ * @param fallbacks - Additional selectors to try if primary fails.
133
+ * @param timeout - Per-selector wait timeout in ms (default: 3000).
134
+ */
135
+ export async function resolveSelector(page, target, fallbacks = [], timeout = 3_000) {
136
+ const strategies = [target, ...fallbacks];
137
+ for (const selector of strategies) {
138
+ try {
139
+ const handle = await page.waitForSelector(selector, { timeout });
140
+ if (handle)
141
+ return handle;
142
+ }
143
+ catch {
144
+ // Selector not found within timeout — try next
145
+ }
146
+ }
147
+ return null;
148
+ }
149
+ /**
150
+ * Takes a basic CSS selector (e.g. from a snapshot), injects
151
+ * `generateSmartSelectors` into the page, and returns a richer SmartSelector
152
+ * with stable alternatives.
153
+ *
154
+ * @param page - Puppeteer Page instance.
155
+ * @param cssSelector - Existing (possibly fragile) CSS selector.
156
+ */
157
+ export async function enhanceElementSelectors(page, cssSelector) {
158
+ const result = await page.evaluate(
159
+ // NOTE: generateSmartSelectors is serialised and sent to the browser.
160
+ // It must remain self-contained (no closures over Node.js variables).
161
+ (sel, genFnSrc) => {
162
+ const el = document.querySelector(sel);
163
+ if (!el)
164
+ return null;
165
+ // eslint-disable-next-line no-new-func
166
+ const fn = new Function(`return (${genFnSrc})`)();
167
+ return fn(el);
168
+ }, cssSelector, generateSmartSelectors.toString());
169
+ if (!result) {
170
+ // Element not found — return a degenerate SmartSelector
171
+ return {
172
+ primary: cssSelector,
173
+ fallbacks: [],
174
+ description: `<not found: ${cssSelector}>`,
175
+ strategy: "css",
176
+ };
177
+ }
178
+ return result;
179
+ }
180
+ //# sourceMappingURL=selector-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selector-engine.js","sourceRoot":"","sources":["../../src/utils/selector-engine.ts"],"names":[],"mappings":"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"}