@ia-qa/self-healing 1.7.13 → 1.7.15

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.
@@ -6,8 +6,43 @@ import type { IaQaConfig } from './config';
6
6
  * same page differently produce contracts that never meet: every page becomes a
7
7
  * phantom lost/new pair and the diff is garbage. The healer, `map`, and run-time
8
8
  * capture all funnel through here for exactly that reason.
9
+ *
10
+ * A page name is a **filename**, so it is also an identity claim: two URLs that
11
+ * resolve to the same name are asserting they are the same page. A pathname alone
12
+ * cannot carry that claim across hosts — five products with a `/login` are five
13
+ * different pages, and naming them all `login` made whichever the suite happened
14
+ * to visit last overwrite the others. The host is therefore part of the name
15
+ * whenever it is not the app's own (see `hostPrefix`).
16
+ */
17
+ /**
18
+ * A URL's host with a leading `www.` folded away — the key that answers "is this
19
+ * the same site?".
20
+ *
21
+ * Comparing raw hosts makes an apex `baseUrl` and a `www.` URL (or the `www.`→apex
22
+ * 301 that is the single most common way the two differ in the wild) look like two
23
+ * different applications. `discovery/safety.ts` builds its crawl-permission key on
24
+ * top of this; page naming uses the host alone, because `http` vs `https` on one
25
+ * host is never two applications — and renaming every contract over a protocol
26
+ * upgrade would be the phantom drift this file exists to prevent.
27
+ */
28
+ export declare function foldHost(u: URL, strictHost?: boolean): string;
29
+ /**
30
+ * Slug a URL into a page name. `baseUrl` is optional only because the discovery
31
+ * paths already filter to one host before they get here; every capture path passes
32
+ * it, and without it two hosts sharing a pathname collide into one contract.
33
+ */
34
+ export declare function pageNameFromUrl(url: string, baseUrl?: string): string;
35
+ /**
36
+ * The key a capture buffers a page under while a test run is in flight.
37
+ *
38
+ * The resolved name *and* the host it was seen on. With a config the two are
39
+ * already one-to-one — the name carries the host — so this is a no-op there. Without
40
+ * one, `resolvePageName` has no `baseUrl` to namespace against, and keying by name
41
+ * alone would union two applications' `/login` inside a single worker, where nothing
42
+ * downstream could ever see that it happened. Keeping them apart costs nothing and
43
+ * lets the merge say so out loud (`captureMerge.ts`).
9
44
  */
10
- export declare function pageNameFromUrl(url: string): string;
45
+ export declare function captureKey(name: string, url: string): string;
11
46
  export type PageNameResolution =
12
47
  /** The URL is a configured page — use the name its contract already has. */
13
48
  {
package/dist/pageName.js CHANGED
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.foldHost = foldHost;
3
4
  exports.pageNameFromUrl = pageNameFromUrl;
5
+ exports.captureKey = captureKey;
4
6
  exports.resolvePageName = resolvePageName;
5
7
  /**
6
8
  * URL → logical page name, the one resolver every capture path must share.
@@ -9,30 +11,108 @@ exports.resolvePageName = resolvePageName;
9
11
  * same page differently produce contracts that never meet: every page becomes a
10
12
  * phantom lost/new pair and the diff is garbage. The healer, `map`, and run-time
11
13
  * capture all funnel through here for exactly that reason.
14
+ *
15
+ * A page name is a **filename**, so it is also an identity claim: two URLs that
16
+ * resolve to the same name are asserting they are the same page. A pathname alone
17
+ * cannot carry that claim across hosts — five products with a `/login` are five
18
+ * different pages, and naming them all `login` made whichever the suite happened
19
+ * to visit last overwrite the others. The host is therefore part of the name
20
+ * whenever it is not the app's own (see `hostPrefix`).
12
21
  */
13
- function pageNameFromUrl(url) {
14
- let pathname = '/';
22
+ /**
23
+ * A URL's host with a leading `www.` folded away — the key that answers "is this
24
+ * the same site?".
25
+ *
26
+ * Comparing raw hosts makes an apex `baseUrl` and a `www.` URL (or the `www.`→apex
27
+ * 301 that is the single most common way the two differ in the wild) look like two
28
+ * different applications. `discovery/safety.ts` builds its crawl-permission key on
29
+ * top of this; page naming uses the host alone, because `http` vs `https` on one
30
+ * host is never two applications — and renaming every contract over a protocol
31
+ * upgrade would be the phantom drift this file exists to prevent.
32
+ */
33
+ function foldHost(u, strictHost = false) {
34
+ return strictHost ? u.host : u.host.replace(/^www\./i, '');
35
+ }
36
+ function parseUrl(url) {
15
37
  try {
16
- pathname = new URL(url).pathname;
38
+ return new URL(url);
17
39
  }
18
40
  catch {
19
- /* fall through to default */
41
+ return null;
20
42
  }
21
- const slug = pathname.replace(/^\/+|\/+$/g, '').replace(/\//g, '-');
22
- return slug || 'home';
43
+ }
44
+ /** Trailing slashes and query strings do not make another page. */
45
+ function normalizePath(pathname) {
46
+ return pathname.replace(/\/+$/, '') || '/';
47
+ }
48
+ /**
49
+ * The `host--` part of a name, or '' when the URL belongs to the app itself.
50
+ *
51
+ * Empty for every single-host suite, which is what keeps existing contracts
52
+ * byte-identical: the prefix only appears where a collision was previously
53
+ * possible. Sanitized to what `mappingPath` allows, so the name a diff pairs on
54
+ * and the filename it lands in stay the same string.
55
+ */
56
+ function hostPrefix(here, baseUrl) {
57
+ if (!baseUrl)
58
+ return '';
59
+ const base = parseUrl(baseUrl);
60
+ if (!base || foldHost(base) === foldHost(here))
61
+ return '';
62
+ return here.host.replace(/[^a-zA-Z0-9.-]/g, '-') + '--';
63
+ }
64
+ /**
65
+ * Slug a URL into a page name. `baseUrl` is optional only because the discovery
66
+ * paths already filter to one host before they get here; every capture path passes
67
+ * it, and without it two hosts sharing a pathname collide into one contract.
68
+ */
69
+ function pageNameFromUrl(url, baseUrl) {
70
+ const parsed = parseUrl(url);
71
+ const pathname = parsed ? parsed.pathname : '/';
72
+ const slug = pathname.replace(/^\/+|\/+$/g, '').replace(/\//g, '-') || 'home';
73
+ return parsed ? hostPrefix(parsed, baseUrl) + slug : slug;
74
+ }
75
+ /**
76
+ * The key a capture buffers a page under while a test run is in flight.
77
+ *
78
+ * The resolved name *and* the host it was seen on. With a config the two are
79
+ * already one-to-one — the name carries the host — so this is a no-op there. Without
80
+ * one, `resolvePageName` has no `baseUrl` to namespace against, and keying by name
81
+ * alone would union two applications' `/login` inside a single worker, where nothing
82
+ * downstream could ever see that it happened. Keeping them apart costs nothing and
83
+ * lets the merge say so out loud (`captureMerge.ts`).
84
+ */
85
+ function captureKey(name, url) {
86
+ const parsed = parseUrl(url);
87
+ return parsed ? `${name}\u0000${foldHost(parsed)}` : name;
23
88
  }
24
89
  function resolvePageName(url, config) {
25
90
  if (!config)
26
91
  return { kind: 'unconfigured', name: pageNameFromUrl(url) };
27
- const currentPath = new URL(url).pathname.replace(/\/+$/, '') || '/';
28
- const samePath = (p) => (new URL(p.url, config.baseUrl).pathname.replace(/\/+$/, '') || '/') === currentPath;
29
- const match = config.pages.find((p) => !p.steps?.length && samePath(p));
92
+ const here = parseUrl(url);
93
+ if (!here)
94
+ return { kind: 'unconfigured', name: pageNameFromUrl(url) };
95
+ const currentPath = normalizePath(here.pathname);
96
+ // Host *and* path: a configured `/login` names this app's login page, never the
97
+ // one on the partner portal the suite also drives. A target declared with an
98
+ // absolute URL on another host is how a multi-app suite names those explicitly.
99
+ const sameTarget = (p) => {
100
+ let target;
101
+ try {
102
+ target = new URL(p.url, config.baseUrl);
103
+ }
104
+ catch {
105
+ return false;
106
+ }
107
+ return foldHost(target) === foldHost(here) && normalizePath(target.pathname) === currentPath;
108
+ };
109
+ const match = config.pages.find((p) => !p.steps?.length && sameTarget(p));
30
110
  if (match)
31
111
  return { kind: 'configured', name: match.name };
32
- const behindSteps = config.pages.filter((p) => p.steps?.length && samePath(p));
112
+ const behindSteps = config.pages.filter((p) => p.steps?.length && sameTarget(p));
33
113
  if (behindSteps.length > 0) {
34
114
  return { kind: 'steps', candidates: behindSteps.map((p) => p.name) };
35
115
  }
36
- return { kind: 'unconfigured', name: pageNameFromUrl(url) };
116
+ return { kind: 'unconfigured', name: pageNameFromUrl(url, config.baseUrl) };
37
117
  }
38
118
  //# sourceMappingURL=pageName.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"pageName.js","sourceRoot":"","sources":["../src/pageName.ts"],"names":[],"mappings":";;AAWA,0CASC;AAcD,0CAgBC;AAhDD;;;;;;;GAOG;AAEH,SAAgB,eAAe,CAAC,GAAW;IACzC,IAAI,QAAQ,GAAG,GAAG,CAAC;IACnB,IAAI,CAAC;QACH,QAAQ,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,6BAA6B;IAC/B,CAAC;IACD,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACpE,OAAO,IAAI,IAAI,MAAM,CAAC;AACxB,CAAC;AAcD,SAAgB,eAAe,CAAC,GAAW,EAAE,MAAyB;IACpE,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;IAEzE,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC;IACrE,MAAM,QAAQ,GAAG,CAAC,CAAa,EAAE,EAAE,CACjC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,KAAK,WAAW,CAAC;IAEvF,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,MAAM,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACxE,IAAI,KAAK;QAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;IAE3D,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,MAAM,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/E,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;IACvE,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;AAC9D,CAAC"}
1
+ {"version":3,"file":"pageName.js","sourceRoot":"","sources":["../src/pageName.ts"],"names":[],"mappings":"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"}
@@ -91,8 +91,10 @@ async function capturePage(page) {
91
91
  const elements = await (0, aom_1.extractInteractiveElements)(page);
92
92
  if (elements.length === 0)
93
93
  return;
94
- const prev = state.pages.get(resolved.name);
95
- state.pages.set(resolved.name, {
94
+ const key = (0, pageName_1.captureKey)(resolved.name, url);
95
+ const prev = state.pages.get(key);
96
+ state.pages.set(key, {
97
+ page: resolved.name,
96
98
  url,
97
99
  elements: prev ? (0, captureMerge_1.unionElements)(prev.elements, elements) : elements,
98
100
  });
@@ -108,8 +110,8 @@ function writeShard() {
108
110
  const dir = (0, captureMerge_1.captureDir)();
109
111
  fs.mkdirSync(dir, { recursive: true });
110
112
  const worker = process.env.TEST_WORKER_INDEX ?? String(process.pid);
111
- const pages = Array.from(state.pages, ([name, c]) => ({
112
- page: name,
113
+ const pages = Array.from(state.pages.values(), (c) => ({
114
+ page: c.page,
113
115
  url: c.url,
114
116
  elements: c.elements,
115
117
  }));
@@ -1 +1 @@
1
- {"version":3,"file":"capture.js","sourceRoot":"","sources":["../../src/playwright/capture.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"capture.js","sourceRoot":"","sources":["../../src/playwright/capture.ts"],"names":[],"mappings":"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"}
@@ -67,6 +67,7 @@ exports.CAPTURE_ENV = 'IAQA_CAPTURE';
67
67
  function captureEnabled() {
68
68
  return process.env[exports.CAPTURE_ENV] === '1';
69
69
  }
70
+ /** Keyed by `captureKey()`, not by page name — see there. */
70
71
  const pages = new Map();
71
72
  let cfg = null;
72
73
  let cfgLoaded = false;
@@ -89,8 +90,8 @@ function writeShard() {
89
90
  const dir = (0, captureMerge_1.captureDir)();
90
91
  fs.mkdirSync(dir, { recursive: true });
91
92
  const worker = process.env.TEST_WORKER_INDEX ?? String(process.pid);
92
- const shardPages = Array.from(pages, ([name, c]) => ({
93
- page: name,
93
+ const shardPages = Array.from(pages.values(), (c) => ({
94
+ page: c.page,
94
95
  url: c.url,
95
96
  elements: c.elements,
96
97
  }));
@@ -125,8 +126,10 @@ async function capture(driver) {
125
126
  const elements = (await driver.executeScript(extract_1.extractInPage)) || [];
126
127
  if (elements.length === 0)
127
128
  return;
128
- const prev = pages.get(resolved.name);
129
- pages.set(resolved.name, {
129
+ const key = (0, pageName_1.captureKey)(resolved.name, url);
130
+ const prev = pages.get(key);
131
+ pages.set(key, {
132
+ page: resolved.name,
130
133
  url,
131
134
  elements: prev ? (0, captureMerge_1.unionElements)(prev.elements, elements) : elements,
132
135
  });
@@ -1 +1 @@
1
- {"version":3,"file":"capture.js","sourceRoot":"","sources":["../../src/selenium/capture.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"capture.js","sourceRoot":"","sources":["../../src/selenium/capture.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ia-qa/self-healing",
3
- "version": "1.7.13",
3
+ "version": "1.7.15",
4
4
  "description": "Your Playwright, Cypress or Selenium tests break when a selector moves — this finds the element again and rewrites the test. Deterministic: no LLM decides whether your build passes. Runs entirely on your machine, with a local MCP server for agents.",
5
5
  "keywords": [
6
6
  "self-healing",