@validate.qa/runner 1.0.101 → 1.0.103

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 (31) hide show
  1. package/README.md +3 -0
  2. package/dist/{chunk-SN3PN4G4.mjs → chunk-36AWDKPL.mjs} +6 -2
  3. package/dist/{chunk-CYWHPXNZ.mjs → chunk-7SH3COMQ.mjs} +1 -1
  4. package/dist/{chunk-BBTK6OX6.mjs → chunk-BECCGMU4.mjs} +383 -11
  5. package/dist/{chunk-4SZC5ZX3.mjs → chunk-CG75I3ZZ.mjs} +25477 -5374
  6. package/dist/{chunk-TPU42VH2.mjs → chunk-CMM4DOXC.mjs} +10 -5
  7. package/dist/{chunk-M3VZGHZQ.mjs → chunk-NNJYKR3O.mjs} +22 -11
  8. package/dist/{chunk-IGXGSDE3.mjs → chunk-OTKJZIOD.mjs} +1298 -384
  9. package/dist/{chunk-CO5KHIVX.mjs → chunk-TK5KEGNW.mjs} +1 -1
  10. package/dist/{chunk-FQUH2PU2.mjs → chunk-WVLBQDFP.mjs} +140 -7
  11. package/dist/{chunk-2OKZY3WN.mjs → chunk-YI3ZC2XI.mjs} +2 -2
  12. package/dist/{chunk-XZUUBMP3.mjs → chunk-YIM746WO.mjs} +1 -1
  13. package/dist/cli.js +140692 -118903
  14. package/dist/cli.mjs +362 -108
  15. package/dist/credential-mcp-server.js +1402 -350
  16. package/dist/credential-mcp-server.mjs +3 -3
  17. package/dist/discovery-mcp-server.js +1330 -401
  18. package/dist/discovery-mcp-server.mjs +4 -4
  19. package/dist/dist-2G7YTNH5.mjs +17 -0
  20. package/dist/inbox-mcp-server.js +1676 -629
  21. package/dist/inbox-mcp-server.mjs +3 -3
  22. package/dist/route-seed-worker.js +1244 -330
  23. package/dist/route-seed-worker.mjs +4 -4
  24. package/dist/run-write-guard-preload.js +1622 -332
  25. package/dist/run-write-guard-preload.mjs +4 -4
  26. package/dist/run-write-guard.js +1622 -332
  27. package/dist/run-write-guard.mjs +3 -3
  28. package/dist/spec-driver.js +1 -1
  29. package/dist/spec-driver.mjs +1 -1
  30. package/package.json +3 -2
  31. package/dist/dist-VTPBY2C4.mjs +0 -17
@@ -2,11 +2,11 @@ import {
2
2
  require_google_signin,
3
3
  require_harness_init_script,
4
4
  require_test_inbox_broker
5
- } from "./chunk-FQUH2PU2.mjs";
5
+ } from "./chunk-WVLBQDFP.mjs";
6
6
  import {
7
7
  dist_exports,
8
8
  init_dist
9
- } from "./chunk-IGXGSDE3.mjs";
9
+ } from "./chunk-OTKJZIOD.mjs";
10
10
  import {
11
11
  __commonJS,
12
12
  __require,
@@ -33,6 +33,7 @@ var require_browser_config = __commonJS({
33
33
  exports.fullChromiumCloudLaunch = fullChromiumCloudLaunch;
34
34
  exports.chooseCloudBrowser = chooseCloudBrowser;
35
35
  exports.appTimezoneConfigLine = appTimezoneConfigLine;
36
+ exports.discoveryTimezoneId = discoveryTimezoneId;
36
37
  exports.getMCPBrowserConfig = getMCPBrowserConfig;
37
38
  exports.getPlaywrightLaunchOptions = getPlaywrightLaunchOptions;
38
39
  exports.getLaunchOptions = getLaunchOptions;
@@ -251,7 +252,7 @@ var require_browser_config = __commonJS({
251
252
  try {
252
253
  (0, fs_1.cpSync)(localStateSrc, (0, path_1.join)(tempDir, "Local State"));
253
254
  } catch (err) {
254
- throw new Error(`Cannot copy Chrome profile (${err instanceof Error ? err.message : String(err)}). Quit Google Chrome completely, or use getChromeUserDataDirSource() for seeding.`);
255
+ throw new Error(`Cannot copy Chrome profile (${err instanceof Error ? err.message : String(err)}). Quit Google Chrome completely, or use getChromeUserDataDirSource() for seeding.`, { cause: err });
255
256
  }
256
257
  }
257
258
  for (const file of essentialFiles) {
@@ -442,6 +443,10 @@ var require_browser_config = __commonJS({
442
443
  const zone = (0, shared_1.appTimezoneFromVariables)(vars);
443
444
  return zone ? `timezoneId: ${JSON.stringify(zone)},` : "";
444
445
  }
446
+ function discoveryTimezoneId(ctx) {
447
+ const vars = ctx.variableContext;
448
+ return (0, shared_1.appTimezoneFromVariables)(vars?.publicTestVariables) ?? (0, shared_1.appTimezoneFromVariables)(vars?.allTestVariables);
449
+ }
445
450
  function getMCPBrowserConfig(opts) {
446
451
  const userDataDir = opts?.forceIsolated ? null : getTestUserDataDir();
447
452
  const timezoneOption = opts?.timezoneId ? { timezoneId: opts.timezoneId } : {};
@@ -1253,7 +1258,7 @@ var require_runs_dir = __commonJS({
1253
1258
  } catch (error) {
1254
1259
  if (error.code === "EEXIST" && resolvesFrom(runsDir) === own)
1255
1260
  return;
1256
- throw new Error(`Could not link ${link} to the runner's node_modules (${error.message}). Set RUNS_DIR to a writable folder outside node_modules that can resolve @playwright/test.`);
1261
+ throw new Error(`Could not link ${link} to the runner's node_modules (${error.message}). Set RUNS_DIR to a writable folder outside node_modules that can resolve @playwright/test.`, { cause: error });
1257
1262
  }
1258
1263
  }
1259
1264
  }
@@ -3179,7 +3184,7 @@ var require_survey_door_harvester = __commonJS({
3179
3184
  }
3180
3185
  if (!payload)
3181
3186
  continue;
3182
- const cleaned = payload.replace(/^\s*```(json)?\s*\n?/, "").replace(/\n?```\s*$/, "").trim();
3187
+ const cleaned = payload.replace(/^\s*```(json)?\s*\n?/i, "").replace(/\n?```\s*$/, "").trim();
3183
3188
  if (!cleaned)
3184
3189
  continue;
3185
3190
  try {
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  require_route_manifest
3
- } from "./chunk-CO5KHIVX.mjs";
3
+ } from "./chunk-TK5KEGNW.mjs";
4
4
  import {
5
5
  require_survey_network_guard
6
- } from "./chunk-SN3PN4G4.mjs";
6
+ } from "./chunk-36AWDKPL.mjs";
7
7
  import {
8
8
  dist_exports,
9
9
  init_dist
10
- } from "./chunk-IGXGSDE3.mjs";
10
+ } from "./chunk-OTKJZIOD.mjs";
11
11
  import {
12
12
  __commonJS,
13
13
  __toCommonJS
@@ -20,6 +20,7 @@ var require_exploration_parser = __commonJS({
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
21
  exports.extractCodeLines = extractCodeLines;
22
22
  exports.extractProvenLocator = extractProvenLocator;
23
+ exports.maskTypedValues = maskTypedValues;
23
24
  exports.sanitizePromptCodeLine = sanitizePromptCodeLine;
24
25
  exports.extractPageUrl = extractPageUrl;
25
26
  exports.extractPageTitle = extractPageTitle;
@@ -34,7 +35,7 @@ var require_exploration_parser = __commonJS({
34
35
  var shared_1 = (init_dist(), __toCommonJS(dist_exports));
35
36
  function extractCodeLines(toolResultContent) {
36
37
  const isPlaywrightLine = (l) => l.startsWith("await page.") || l.startsWith("await expect(");
37
- const codeSection = toolResultContent.match(/###\s*Ran Playwright code\s*\n([\s\S]*?)(?=\n###|\n$|$)/);
38
+ const codeSection = toolResultContent.match(/###\s*Ran Playwright code\s*\n(?![^\S\n]*\n)([\s\S]*?)(?=\n###|\n$|$)/);
38
39
  if (codeSection) {
39
40
  return codeSection[1].split("\n").map((l) => l.trim()).filter(isPlaywrightLine).map((l) => l.replace(/;$/, ""));
40
41
  }
@@ -78,7 +79,7 @@ var require_exploration_parser = __commonJS({
78
79
  cut = idx;
79
80
  }
80
81
  let locator = cut > start ? codeLine.slice(start, cut) : codeLine.slice(start);
81
- locator = locator.trim().replace(/;+\s*$/, "").trim();
82
+ locator = locator.trim().replace(/(?<!;);+\s*$/, "").trim();
82
83
  if (!locator.includes("("))
83
84
  return null;
84
85
  if (!/^(getBy\w+|locator)\(/.test(locator))
@@ -158,13 +159,17 @@ var require_exploration_parser = __commonJS({
158
159
  return false;
159
160
  return RECORD_TITLE_WITH_COMPANY.test(name);
160
161
  }
162
+ var TYPED_VALUE_CALL_RE = /\.(fill|type|pressSequentially|insertText)\(\s*(['"`])(?:\\.|(?!\2)[^\\])*\2(\s*,\s*\{[^{}]*\})?\s*\)/g;
163
+ var TWO_ARG_TYPED_VALUE_CALL_RE = /\.(fill|type)\(\s*((?:(['"`])(?:\\.|(?!\3)[^\\])*\3|[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*))\s*,\s*(['"`])(?:\\.|(?!\4)[^\\])*\4(\s*,\s*\{[^{}]*\})?\s*\)/g;
164
+ function maskTypedValues(codeLine, mask) {
165
+ return codeLine.replace(TWO_ARG_TYPED_VALUE_CALL_RE, (_all, method, selector, _selQuote, _quote, options) => `.${method}(${selector}, ${mask}${options ?? ""})`).replace(TYPED_VALUE_CALL_RE, (_all, method, _quote, options) => `.${method}(${mask}${options ?? ""})`);
166
+ }
161
167
  function sanitizePromptCodeLine(codeLine) {
162
168
  let sanitized = codeLine;
163
169
  sanitized = sanitized.replace(/getByRole\('(textbox|searchbox|combobox|spinbutton)',\s*\{\s*name:\s*['"]([^'"]*)['"]\s*\}\)/g, (match, role, name, _offset, line) => looksDynamicFieldLabel(name, line) ? `getByRole('${role}')` : match);
164
170
  sanitized = sanitized.replace(/getByLabel\(\s*(['"])([^'"]*)\1\s*\)(?=\)?\.(?:fill|type|toHaveValue|inputValue|press)\()/g, (match, _quote, label, _offset, line) => looksDynamicFieldLabel(label, line) ? "getByRole('textbox')" : match);
165
171
  sanitized = sanitized.replace(/getByLabel\(\s*(['"])([^'"]*)\1\s*\)(?=\)?\.selectOption\()/g, (match, _quote, label, _offset, line) => looksDynamicFieldLabel(label, line) ? "getByRole('combobox')" : match);
166
- sanitized = sanitized.replace(/\.fill\(\s*(['"]).*?\1\s*\)/g, ".fill('<test-value>')");
167
- sanitized = sanitized.replace(/\.type\(\s*(['"]).*?\1\s*\)/g, ".type('<test-value>')");
172
+ sanitized = maskTypedValues(sanitized, "'<test-value>'");
168
173
  sanitized = sanitized.replace(/\.toHaveValue\(\s*(['"]).*?\1\s*\)/g, ".toHaveValue(/./)");
169
174
  sanitized = sanitized.replace(/getByRole\('heading',\s*\{\s*name:\s*'([^']*)'\s*\}\)/g, (match, name) => looksDynamicRecordTitle(name) ? "getByRole('heading')" : match);
170
175
  sanitized = sanitized.replace(/getByRole\('heading',\s*\{\s*name:\s*"([^"]*)"\s*\}\)/g, (match, name) => looksDynamicRecordTitle(name) ? "getByRole('heading')" : match);
@@ -188,7 +193,7 @@ var require_exploration_parser = __commonJS({
188
193
  return match ? match[1].trim() : null;
189
194
  }
190
195
  function extractSnapshotSection(content) {
191
- const match = content.match(/###\s*Snapshot\s*\n([\s\S]*?)(?=\n###|$)/);
196
+ const match = content.match(/###\s*Snapshot\s*\n(?![^\S\n]*\n)([\s\S]*?)(?=\n###|$)/);
192
197
  if (!match)
193
198
  return null;
194
199
  if (/^\s*- \[Snapshot\]\([^)\n]*\)\s*$/.test(match[1]))
@@ -256,7 +261,7 @@ var require_exploration_parser = __commonJS({
256
261
  return hints;
257
262
  }
258
263
  function extractFirstAlert(snapshotYaml) {
259
- const match = snapshotYaml.match(/^\s*-\s+(?:alert|status)\s+"([^"]+)"/m);
264
+ const match = snapshotYaml.match(/^[^\S\n\r\u2028\u2029]*-\s+(?:alert|status)\s+"([^"]+)"/m);
260
265
  return match ? match[1] : null;
261
266
  }
262
267
  function buildInteractionLogEntry(toolName, toolArgs, codeLines, pageUrl, pageTitle, snapshotSection) {
@@ -297,6 +302,12 @@ var require_exploration_parser = __commonJS({
297
302
  return /^\d{10,}$/.test(value);
298
303
  return false;
299
304
  }
305
+ function hashRouterPathWithoutTrailingSlash(hash) {
306
+ const q = hash.indexOf("?");
307
+ const path = q < 0 ? hash : hash.slice(0, q);
308
+ const stripped = (0, shared_1.stripTrailingSlashes)(path);
309
+ return stripped === "#" || stripped === "" ? hash : stripped + (q < 0 ? "" : hash.slice(q));
310
+ }
300
311
  function normalizeRoute(url) {
301
312
  let route = url.pathname;
302
313
  const encodeQueryPart = (part) => part.replace(/[%&=#+?]/g, (char) => `%${char.charCodeAt(0).toString(16).toUpperCase().padStart(2, "0")}`);
@@ -315,7 +326,7 @@ var require_exploration_parser = __commonJS({
315
326
  }
316
327
  }
317
328
  if (url.hash && url.hash !== "#" && url.hash !== "#/") {
318
- route += url.hash;
329
+ route += url.hash.startsWith("#/") ? hashRouterPathWithoutTrailingSlash(url.hash) : url.hash;
319
330
  }
320
331
  return route;
321
332
  }
@@ -1948,7 +1959,7 @@ var require_repo_feature_verification = __commonJS({
1948
1959
  return null;
1949
1960
  }
1950
1961
  function normalizeControlText(text) {
1951
- return text.toLowerCase().replace(/[^a-z0-9]+/g, " ").trim();
1962
+ return text.normalize("NFKC").toLowerCase().replace(/[^\p{L}\p{N}\p{M}]+/gu, " ").trim();
1952
1963
  }
1953
1964
  var SESSION_END_LABEL = /^(?:log|sign) ?(?:out|off)$/;
1954
1965
  var SESSION_END_SPELLINGS = ["log out", "logout", "log off", "logoff", "sign out", "signout", "sign off", "signoff"];