@validate.qa/runner 1.0.101 → 1.0.102
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/README.md +3 -0
- package/dist/{chunk-IGXGSDE3.mjs → chunk-3JM6XTSZ.mjs} +1298 -384
- package/dist/{chunk-BBTK6OX6.mjs → chunk-4WLP3RWN.mjs} +383 -11
- package/dist/{chunk-XZUUBMP3.mjs → chunk-5DFBEL72.mjs} +1 -1
- package/dist/{chunk-M3VZGHZQ.mjs → chunk-BXLEPT4M.mjs} +20 -10
- package/dist/{chunk-FQUH2PU2.mjs → chunk-CBVHPYVJ.mjs} +62 -2
- package/dist/{chunk-4SZC5ZX3.mjs → chunk-DN3O6EYT.mjs} +19461 -4077
- package/dist/{chunk-SN3PN4G4.mjs → chunk-E2RRAE27.mjs} +6 -2
- package/dist/{chunk-2OKZY3WN.mjs → chunk-E2VEMBQQ.mjs} +2 -2
- package/dist/{chunk-CYWHPXNZ.mjs → chunk-HJ6FKHMM.mjs} +1 -1
- package/dist/{chunk-CO5KHIVX.mjs → chunk-PWFWMVZU.mjs} +1 -1
- package/dist/{chunk-TPU42VH2.mjs → chunk-ZZYBRIBT.mjs} +10 -5
- package/dist/cli.js +135916 -118926
- package/dist/cli.mjs +349 -101
- package/dist/credential-mcp-server.js +1327 -348
- package/dist/credential-mcp-server.mjs +3 -3
- package/dist/discovery-mcp-server.js +1328 -400
- package/dist/discovery-mcp-server.mjs +4 -4
- package/dist/dist-52M5RDZ6.mjs +17 -0
- package/dist/inbox-mcp-server.js +1579 -605
- package/dist/inbox-mcp-server.mjs +3 -3
- package/dist/route-seed-worker.js +1244 -330
- package/dist/route-seed-worker.mjs +4 -4
- package/dist/run-write-guard-preload.js +1622 -332
- package/dist/run-write-guard-preload.mjs +4 -4
- package/dist/run-write-guard.js +1622 -332
- package/dist/run-write-guard.mjs +3 -3
- package/dist/spec-driver.js +1 -1
- package/dist/spec-driver.mjs +1 -1
- package/package.json +3 -2
- package/dist/dist-VTPBY2C4.mjs +0 -17
package/dist/inbox-mcp-server.js
CHANGED
|
@@ -67537,163 +67537,6 @@ var require_verification_inbox = __commonJS({
|
|
|
67537
67537
|
}
|
|
67538
67538
|
});
|
|
67539
67539
|
|
|
67540
|
-
// ../runner-core/dist/services/harness-init-script.js
|
|
67541
|
-
var require_harness_init_script = __commonJS({
|
|
67542
|
-
"../runner-core/dist/services/harness-init-script.js"(exports2) {
|
|
67543
|
-
"use strict";
|
|
67544
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
67545
|
-
exports2.HARNESS_INIT_SOURCE_URL = void 0;
|
|
67546
|
-
exports2.withHarnessSourceUrl = withHarnessSourceUrl;
|
|
67547
|
-
exports2.buildAnimationDisablingSource = buildAnimationDisablingSource;
|
|
67548
|
-
exports2.isHarnessInitLocation = isHarnessInitLocation;
|
|
67549
|
-
exports2.isHarnessInitErrorStack = isHarnessInitErrorStack;
|
|
67550
|
-
exports2.isHarnessInitConsoleLine = isHarnessInitConsoleLine;
|
|
67551
|
-
exports2.stripHarnessConsoleEntries = stripHarnessConsoleEntries;
|
|
67552
|
-
var node_crypto_1 = require("crypto");
|
|
67553
|
-
exports2.HARNESS_INIT_SOURCE_URL = `vqa-harness-init-${(0, node_crypto_1.randomBytes)(4).toString("hex")}.js`;
|
|
67554
|
-
function withHarnessSourceUrl(content) {
|
|
67555
|
-
return `${content}
|
|
67556
|
-
//# sourceURL=${exports2.HARNESS_INIT_SOURCE_URL}`;
|
|
67557
|
-
}
|
|
67558
|
-
function buildAnimationDisablingSource(opts) {
|
|
67559
|
-
return withHarnessSourceUrl(`(() => {
|
|
67560
|
-
// Layer 1: CSS transitions and animations - instant, not removed
|
|
67561
|
-
// (duration 0s preserves final state; 'none' would prevent keyframes from completing)
|
|
67562
|
-
try {
|
|
67563
|
-
let applied = false;
|
|
67564
|
-
const apply = () => {
|
|
67565
|
-
if (applied) return true;
|
|
67566
|
-
const root = document.head || document.documentElement;
|
|
67567
|
-
if (!root) return false;
|
|
67568
|
-
const style = document.createElement('style');
|
|
67569
|
-
style.textContent = '*, *::before, *::after { transition-duration: 0s !important; animation-duration: 0s !important; transition-delay: 0s !important; animation-delay: 0s !important; }';
|
|
67570
|
-
root.appendChild(style);
|
|
67571
|
-
applied = true;
|
|
67572
|
-
return true;
|
|
67573
|
-
};
|
|
67574
|
-
if (!apply()) {
|
|
67575
|
-
// The document has no root element yet (iframe, about:blank, empty document): wait for it.
|
|
67576
|
-
let observer = null;
|
|
67577
|
-
const stop = () => { try { if (observer) observer.disconnect(); } catch (e) {} };
|
|
67578
|
-
const retry = () => { try { if (apply()) stop(); } catch (e) { stop(); } };
|
|
67579
|
-
try {
|
|
67580
|
-
observer = new MutationObserver(retry);
|
|
67581
|
-
observer.observe(document, { childList: true });
|
|
67582
|
-
} catch (e) {}
|
|
67583
|
-
document.addEventListener('readystatechange', retry);
|
|
67584
|
-
document.addEventListener('DOMContentLoaded', () => { retry(); stop(); }, { once: true });
|
|
67585
|
-
}
|
|
67586
|
-
} catch (e) {}
|
|
67587
|
-
${opts.hideWebdriver ? `
|
|
67588
|
-
try {
|
|
67589
|
-
Object.defineProperty(navigator, 'webdriver', { get: () => undefined });
|
|
67590
|
-
} catch (e) {}
|
|
67591
|
-
` : ""}
|
|
67592
|
-
// Layer 2: Web Animations API - make instant instead of no-op
|
|
67593
|
-
// (preserves animation completion callbacks that app code may depend on)
|
|
67594
|
-
try {
|
|
67595
|
-
const origAnimate = Element.prototype.animate;
|
|
67596
|
-
if (typeof origAnimate === 'function') {
|
|
67597
|
-
Element.prototype.animate = function (keyframes, options) {
|
|
67598
|
-
if (typeof options === 'object' && options !== null) {
|
|
67599
|
-
options = Object.assign({}, options, { duration: 0, delay: 0 });
|
|
67600
|
-
} else {
|
|
67601
|
-
options = 0; // covers number, undefined, and any other type
|
|
67602
|
-
}
|
|
67603
|
-
return origAnimate.call(this, keyframes, options);
|
|
67604
|
-
};
|
|
67605
|
-
}
|
|
67606
|
-
} catch (e) {}
|
|
67607
|
-
})();`);
|
|
67608
|
-
}
|
|
67609
|
-
function isHarnessInitLocation(url) {
|
|
67610
|
-
return url === exports2.HARNESS_INIT_SOURCE_URL;
|
|
67611
|
-
}
|
|
67612
|
-
var MAX_MATCHED_LINE_CHARS = 2048;
|
|
67613
|
-
var MAX_SCANNED_LINES = 200;
|
|
67614
|
-
var STACK_FRAME_RE = /^\s*at\s+(?:[^()\s][^()]*\()?([^()\s]+):\d+:\d+\)?\s*$/;
|
|
67615
|
-
function isHarnessInitErrorStack(stack) {
|
|
67616
|
-
if (!stack)
|
|
67617
|
-
return false;
|
|
67618
|
-
const lines = stack.split("\n", MAX_SCANNED_LINES);
|
|
67619
|
-
for (const line of lines) {
|
|
67620
|
-
if (line.length > MAX_MATCHED_LINE_CHARS)
|
|
67621
|
-
continue;
|
|
67622
|
-
const match = STACK_FRAME_RE.exec(line);
|
|
67623
|
-
if (match)
|
|
67624
|
-
return match[1] === exports2.HARNESS_INIT_SOURCE_URL;
|
|
67625
|
-
}
|
|
67626
|
-
return false;
|
|
67627
|
-
}
|
|
67628
|
-
var MCP_CONSOLE_LINE_LOCATION_RE = / @ ([^\s@]+):\d+$/;
|
|
67629
|
-
function isHarnessInitConsoleLine(line) {
|
|
67630
|
-
const trimmed = line.trim();
|
|
67631
|
-
if (trimmed.length > MAX_MATCHED_LINE_CHARS)
|
|
67632
|
-
return false;
|
|
67633
|
-
const match = MCP_CONSOLE_LINE_LOCATION_RE.exec(trimmed);
|
|
67634
|
-
return match !== null && match[1] === exports2.HARNESS_INIT_SOURCE_URL;
|
|
67635
|
-
}
|
|
67636
|
-
var MCP_LEVEL_LINE_RE = /^\s*(?:-\s+)?\[([A-Za-z]+)\]/;
|
|
67637
|
-
var MCP_FRAME_LINE_RE = /^\s+at\s/;
|
|
67638
|
-
var MCP_TOTALS_RE = /^(\s*Total messages:\s*)(\d+)(\s*\(Errors:\s*)(\d+)(,\s*Warnings:\s*)(\d+)(\).*)$/;
|
|
67639
|
-
var MCP_RETURNING_RE = /^(\s*Returning\s+)(\d+)(\s+messages\b.*)$/;
|
|
67640
|
-
function stripHarnessConsoleEntries(text) {
|
|
67641
|
-
if (!text.includes(exports2.HARNESS_INIT_SOURCE_URL))
|
|
67642
|
-
return text;
|
|
67643
|
-
const lines = text.split("\n");
|
|
67644
|
-
const out = [];
|
|
67645
|
-
let removed = 0;
|
|
67646
|
-
let removedErrors = 0;
|
|
67647
|
-
let removedWarnings = 0;
|
|
67648
|
-
let i = 0;
|
|
67649
|
-
while (i < lines.length) {
|
|
67650
|
-
const line = lines[i];
|
|
67651
|
-
const level = MCP_LEVEL_LINE_RE.exec(line);
|
|
67652
|
-
if (level && isHarnessInitConsoleLine(line.replace(/^\s*-\s+/, ""))) {
|
|
67653
|
-
removed++;
|
|
67654
|
-
const kind = level[1].toLowerCase();
|
|
67655
|
-
if (kind === "error")
|
|
67656
|
-
removedErrors++;
|
|
67657
|
-
else if (kind === "warning" || kind === "warn")
|
|
67658
|
-
removedWarnings++;
|
|
67659
|
-
i++;
|
|
67660
|
-
continue;
|
|
67661
|
-
}
|
|
67662
|
-
if (MCP_FRAME_LINE_RE.test(line)) {
|
|
67663
|
-
let end = i;
|
|
67664
|
-
while (end < lines.length && MCP_FRAME_LINE_RE.test(lines[end]))
|
|
67665
|
-
end++;
|
|
67666
|
-
const frames = lines.slice(i, end);
|
|
67667
|
-
if (isHarnessInitErrorStack(frames.join("\n"))) {
|
|
67668
|
-
const previous = out[out.length - 1];
|
|
67669
|
-
if (previous !== void 0 && previous.trim() !== "" && !/^\s*(?:#|Total messages|Returning)/.test(previous) && !MCP_LEVEL_LINE_RE.test(previous))
|
|
67670
|
-
out.pop();
|
|
67671
|
-
removed++;
|
|
67672
|
-
removedErrors++;
|
|
67673
|
-
} else {
|
|
67674
|
-
out.push(...frames);
|
|
67675
|
-
}
|
|
67676
|
-
i = end;
|
|
67677
|
-
continue;
|
|
67678
|
-
}
|
|
67679
|
-
out.push(line);
|
|
67680
|
-
i++;
|
|
67681
|
-
}
|
|
67682
|
-
if (removed === 0)
|
|
67683
|
-
return text;
|
|
67684
|
-
return out.map((line) => {
|
|
67685
|
-
const totals = MCP_TOTALS_RE.exec(line);
|
|
67686
|
-
if (totals) {
|
|
67687
|
-
const [, a, total, b, errors2, c, warnings, d] = totals;
|
|
67688
|
-
return `${a}${Math.max(0, +total - removed)}${b}${Math.max(0, +errors2 - removedErrors)}${c}${Math.max(0, +warnings - removedWarnings)}${d}`;
|
|
67689
|
-
}
|
|
67690
|
-
const returning = MCP_RETURNING_RE.exec(line);
|
|
67691
|
-
return returning ? `${returning[1]}${Math.max(0, +returning[2] - removed)}${returning[3]}` : line;
|
|
67692
|
-
}).join("\n");
|
|
67693
|
-
}
|
|
67694
|
-
}
|
|
67695
|
-
});
|
|
67696
|
-
|
|
67697
67540
|
// ../shared/dist/types.js
|
|
67698
67541
|
function isUIVariant(value) {
|
|
67699
67542
|
return typeof value === "string" && UI_VARIANTS.includes(value);
|
|
@@ -67743,13 +67586,13 @@ function isBlockedEnvVar(key) {
|
|
|
67743
67586
|
function sanitizeTestVariables(vars) {
|
|
67744
67587
|
if (!vars)
|
|
67745
67588
|
return {};
|
|
67746
|
-
const
|
|
67589
|
+
const clean3 = {};
|
|
67747
67590
|
for (const [key, value] of Object.entries(vars)) {
|
|
67748
67591
|
if (!isBlockedEnvVar(key)) {
|
|
67749
|
-
|
|
67592
|
+
clean3[key] = value;
|
|
67750
67593
|
}
|
|
67751
67594
|
}
|
|
67752
|
-
return
|
|
67595
|
+
return clean3;
|
|
67753
67596
|
}
|
|
67754
67597
|
function buildSandboxedEnv(processEnv, testVariables) {
|
|
67755
67598
|
const env = {};
|
|
@@ -69206,9 +69049,40 @@ function semanticTarget(label, platform, base2) {
|
|
|
69206
69049
|
}
|
|
69207
69050
|
};
|
|
69208
69051
|
}
|
|
69052
|
+
function androidResourceOwners(value) {
|
|
69053
|
+
const owners = [];
|
|
69054
|
+
for (const match of value.matchAll(ANDROID_RESOURCE_ID_SUFFIX_RE)) {
|
|
69055
|
+
let runStart = match.index;
|
|
69056
|
+
while (runStart > 0 && /[a-z0-9_.]/i.test(value[runStart - 1]))
|
|
69057
|
+
runStart--;
|
|
69058
|
+
const owner = ownerAtEndOfRun(value.slice(runStart, match.index));
|
|
69059
|
+
if (owner !== null)
|
|
69060
|
+
owners.push(owner);
|
|
69061
|
+
}
|
|
69062
|
+
return owners;
|
|
69063
|
+
}
|
|
69064
|
+
function ownerAtEndOfRun(run) {
|
|
69065
|
+
const segments = run.split(".");
|
|
69066
|
+
const last = segments.length - 1;
|
|
69067
|
+
const startsWithLetter = (segment) => /^[a-z]/i.test(segment);
|
|
69068
|
+
if (last < 1 || !startsWithLetter(segments[last]))
|
|
69069
|
+
return null;
|
|
69070
|
+
let first = last;
|
|
69071
|
+
while (first > 0 && startsWithLetter(segments[first - 1]))
|
|
69072
|
+
first--;
|
|
69073
|
+
let offset = 0;
|
|
69074
|
+
for (let i = 0; i < first - 1; i++)
|
|
69075
|
+
offset += segments[i].length + 1;
|
|
69076
|
+
if (first > 0) {
|
|
69077
|
+
const letterAt = segments[first - 1].search(/[a-z]/i);
|
|
69078
|
+
if (letterAt >= 0)
|
|
69079
|
+
return run.slice(offset + letterAt);
|
|
69080
|
+
offset += segments[first - 1].length + 1;
|
|
69081
|
+
}
|
|
69082
|
+
return first < last ? run.slice(offset) : null;
|
|
69083
|
+
}
|
|
69209
69084
|
function containsForeignAppPackage(value, targetAppId) {
|
|
69210
|
-
for (const
|
|
69211
|
-
const owner = match[1];
|
|
69085
|
+
for (const owner of androidResourceOwners(value)) {
|
|
69212
69086
|
if (targetAppId && owner !== targetAppId && !owner.startsWith(`${targetAppId}.`))
|
|
69213
69087
|
return true;
|
|
69214
69088
|
}
|
|
@@ -69345,7 +69219,7 @@ function healMobileTestSteps(input) {
|
|
|
69345
69219
|
summary: changed ? uniq(summary).slice(0, 12) : []
|
|
69346
69220
|
};
|
|
69347
69221
|
}
|
|
69348
|
-
var MOBILE_STEP_ACTIONS, FOREIGN_PACKAGE_RE,
|
|
69222
|
+
var MOBILE_STEP_ACTIONS, FOREIGN_PACKAGE_RE, ANDROID_RESOURCE_ID_SUFFIX_RE, COMMON_EXTERNAL_PREFIXES;
|
|
69349
69223
|
var init_mobile_step_healer = __esm({
|
|
69350
69224
|
"../shared/dist/mobile-step-healer.js"() {
|
|
69351
69225
|
"use strict";
|
|
@@ -69366,7 +69240,7 @@ var init_mobile_step_healer = __esm({
|
|
|
69366
69240
|
"assertStateDelta"
|
|
69367
69241
|
]);
|
|
69368
69242
|
FOREIGN_PACKAGE_RE = /\b[a-z][a-z0-9_]*(?:\.[a-z][a-z0-9_]*){2,}\b/gi;
|
|
69369
|
-
|
|
69243
|
+
ANDROID_RESOURCE_ID_SUFFIX_RE = /:id\//gi;
|
|
69370
69244
|
COMMON_EXTERNAL_PREFIXES = [
|
|
69371
69245
|
"com.android.",
|
|
69372
69246
|
"com.google.",
|
|
@@ -71076,7 +70950,7 @@ var init_assertion_classifier = __esm({
|
|
|
71076
70950
|
// toHaveCount(0) stays tier 4 (absence proof) via TIER4_PATTERNS.
|
|
71077
70951
|
[/\.toHaveCount\s*\(\s*[1-9]\d*\s*\)/, "non-zero toHaveCount asserts a record count that changes between runs"],
|
|
71078
70952
|
// parenthesised counts like "(3)" or "[12]" in text - but not Playwright method args
|
|
71079
|
-
[
|
|
70953
|
+
[/\((?<!\.\w{3,20}\s*\()\s*\d+\s*\)(?!\s*(?:[,;]\s*)?\))/i, "parenthesised count is session-specific"],
|
|
71080
70954
|
// bare email addresses in assertion content
|
|
71081
70955
|
[/\b[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}\b/i, "email address is user-specific"],
|
|
71082
70956
|
// currency/balance amounts (dynamic account data)
|
|
@@ -71322,7 +71196,7 @@ var init_assertion_proof = __esm({
|
|
|
71322
71196
|
PRESENCE_MATCHER = /\.(?:toBeVisible|toBeAttached|toBeEnabled|toBeInViewport|toBeEditable|toBeFocused)\s*\(|\.toHaveCount\s*\(\s*1\s*\)/;
|
|
71323
71197
|
TEXT_MATCHER = /\.(?:toHaveText|toContainText)\s*\(/;
|
|
71324
71198
|
ANY_VALUE_SOURCE = /^(?:\.|\\S|\\w|\\d|\[\^\\s\]|\[0-9\]|\[\\d\]|\[\\w\]|\[\\s\\S\])[+*]?\??$/;
|
|
71325
|
-
ANY_VALUE_MATCHER = /\.(?:toHaveValue|toHaveText|toContainText)\s*\(\s*\/((?:\\.|[^/\\]){1,300})\/[a-z]*\s
|
|
71199
|
+
ANY_VALUE_MATCHER = /\.(?:toHaveValue|toHaveText|toContainText)\s*\(\s*\/((?:\\.|[^/\\]){1,300})\/[a-z]*\s*[,)]/;
|
|
71326
71200
|
EMPTY_NOT_VALUE = /\.not\s*\.\s*toHaveValue\s*\(\s*(?:['"`]{2}|\/\^?\$?\/)/;
|
|
71327
71201
|
TEXT_MATCHER_LITERAL = /\.(?:toHaveText|toContainText)\s*\(\s*(['"`])((?:(?!\1).){1,300})\1/;
|
|
71328
71202
|
GET_BY_TEXT_LITERAL = /getByText\s*\(\s*(['"`])((?:(?!\1).){1,300})\1/;
|
|
@@ -71339,7 +71213,7 @@ var init_assertion_proof = __esm({
|
|
|
71339
71213
|
DATA_ROLE = /getByRole\s*\(\s*['"`](?:dialog|alertdialog|alert|cell|gridcell|row|rowheader|columnheader|listitem|article|option|status|note|tooltip|paragraph|term|definition|log|marquee|timer|meter)['"`]/gi;
|
|
71340
71214
|
TEXT_LOCATOR = /\.getByText\s*\(|\.filter\s*\(\s*\{\s*hasText\s*:/g;
|
|
71341
71215
|
CSS_LOCATOR = /\.locator\s*\(\s*(['"`])((?:(?!\1).){1,300})\1/g;
|
|
71342
|
-
SPECIFIC_CSS = /\[[^\]]*=|#[\w-]|has-text|:text/;
|
|
71216
|
+
SPECIFIC_CSS = /\[[^\][=]*=|#[\w-]|has-text|:text/;
|
|
71343
71217
|
}
|
|
71344
71218
|
});
|
|
71345
71219
|
|
|
@@ -72303,22 +72177,37 @@ function classifyAuthHandoffIntent(text) {
|
|
|
72303
72177
|
function withoutIdpUrlAsserts(code) {
|
|
72304
72178
|
return code.replace(/\.(?:toHaveURL|waitForURL)\s*\((?:[^)(]|\([^)]*\))*\)/g, (match) => /accountchooser|accounts\.google|appleid\.apple|login\.microsoftonline|\/v\d+\/signin|oauth/i.test(match) ? "" : match);
|
|
72305
72179
|
}
|
|
72180
|
+
function stripLineComment(line) {
|
|
72181
|
+
let from = line.length;
|
|
72182
|
+
while (from > 0) {
|
|
72183
|
+
const c = line.charCodeAt(from - 1);
|
|
72184
|
+
if (c === 10 || c === 13 || c === 8232 || c === 8233)
|
|
72185
|
+
break;
|
|
72186
|
+
from--;
|
|
72187
|
+
}
|
|
72188
|
+
const at = line.indexOf("//", from);
|
|
72189
|
+
return at < 0 ? line : line.slice(0, at);
|
|
72190
|
+
}
|
|
72306
72191
|
function stripComments(code) {
|
|
72307
|
-
return replaceBlockComments(code, () => "").split("\n").map(
|
|
72192
|
+
return replaceBlockComments(code, () => "").split("\n").map(stripLineComment).join("\n");
|
|
72308
72193
|
}
|
|
72309
|
-
function
|
|
72310
|
-
const
|
|
72311
|
-
|
|
72312
|
-
|
|
72313
|
-
let depth = 0;
|
|
72314
|
-
for (let i = open; i < code.length; i++) {
|
|
72194
|
+
function closingParens(code) {
|
|
72195
|
+
const close = new Int32Array(code.length).fill(-1);
|
|
72196
|
+
const open = [];
|
|
72197
|
+
for (let i = 0; i < code.length; i++) {
|
|
72315
72198
|
const c = code[i];
|
|
72316
72199
|
if (c === "(")
|
|
72317
|
-
|
|
72318
|
-
else if (c === ")" &&
|
|
72319
|
-
|
|
72200
|
+
open.push(i);
|
|
72201
|
+
else if (c === ")" && open.length > 0)
|
|
72202
|
+
close[open.pop()] = i;
|
|
72320
72203
|
}
|
|
72321
|
-
return
|
|
72204
|
+
return close;
|
|
72205
|
+
}
|
|
72206
|
+
function balancedCall(code, close, start) {
|
|
72207
|
+
const open = code.indexOf("(", start);
|
|
72208
|
+
if (open < 0 || close[open] < 0)
|
|
72209
|
+
return null;
|
|
72210
|
+
return { inner: code.slice(open + 1, close[open]), end: close[open] };
|
|
72322
72211
|
}
|
|
72323
72212
|
function resolveLocator(code, subject) {
|
|
72324
72213
|
const id = subject.trim().match(/^([A-Za-z_$][\w$]*)$/);
|
|
@@ -72366,8 +72255,10 @@ function isAuthHandoffDismissCode(code) {
|
|
|
72366
72255
|
const expects = [];
|
|
72367
72256
|
const re = new RegExp(EXPECT_CALL_RE.source, "g");
|
|
72368
72257
|
let match;
|
|
72258
|
+
let close = null;
|
|
72369
72259
|
while (match = re.exec(body)) {
|
|
72370
|
-
|
|
72260
|
+
close ??= closingParens(body);
|
|
72261
|
+
const found = balancedCall(body, close, match.index);
|
|
72371
72262
|
if (found)
|
|
72372
72263
|
expects.push({ inner: found.inner, tail: body.slice(found.end, found.end + 48) });
|
|
72373
72264
|
}
|
|
@@ -72412,59 +72303,256 @@ var init_auth_handoff_coverage = __esm({
|
|
|
72412
72303
|
}
|
|
72413
72304
|
});
|
|
72414
72305
|
|
|
72415
|
-
// ../shared/dist/
|
|
72416
|
-
function
|
|
72417
|
-
|
|
72418
|
-
|
|
72306
|
+
// ../shared/dist/auth-plan.js
|
|
72307
|
+
function hasInlineLoginSteps(playwrightCode) {
|
|
72308
|
+
if (!playwrightCode)
|
|
72309
|
+
return false;
|
|
72310
|
+
return /process\.env\.TEST_USER_EMAIL!?/.test(playwrightCode) && /process\.env\.TEST_USER_PASSWORD!?/.test(playwrightCode);
|
|
72419
72311
|
}
|
|
72420
|
-
function
|
|
72421
|
-
|
|
72422
|
-
|
|
72423
|
-
|
|
72424
|
-
if (quote) {
|
|
72425
|
-
if (c === quote && ln[i - 1] !== "\\")
|
|
72426
|
-
quote = null;
|
|
72427
|
-
continue;
|
|
72428
|
-
}
|
|
72429
|
-
if (c === '"' || c === "'" || c === "`") {
|
|
72430
|
-
quote = c;
|
|
72431
|
-
continue;
|
|
72432
|
-
}
|
|
72433
|
-
if (c === "/" && ln[i + 1] === "/")
|
|
72434
|
-
return ln.slice(0, i);
|
|
72435
|
-
}
|
|
72436
|
-
return ln;
|
|
72312
|
+
function hasGeneratedAuthGuard(playwrightCode) {
|
|
72313
|
+
if (!playwrightCode)
|
|
72314
|
+
return false;
|
|
72315
|
+
return /\/\/ >>> VALIDATE_QA_AUTH v(\d+)\b[\s\S]*?process\.env\.AUTH_FILE[\s\S]*?\/\/ <<< VALIDATE_QA_AUTH v\1\b/.test(playwrightCode);
|
|
72437
72316
|
}
|
|
72438
|
-
function
|
|
72439
|
-
|
|
72440
|
-
|
|
72441
|
-
|
|
72442
|
-
|
|
72443
|
-
|
|
72444
|
-
|
|
72445
|
-
|
|
72446
|
-
|
|
72447
|
-
|
|
72448
|
-
|
|
72449
|
-
|
|
72450
|
-
|
|
72451
|
-
|
|
72452
|
-
|
|
72453
|
-
|
|
72454
|
-
|
|
72455
|
-
|
|
72456
|
-
|
|
72317
|
+
function legacyNeedsCookieState(tags, code, sharedAuthInjectEnabled) {
|
|
72318
|
+
if (!sharedAuthInjectEnabled)
|
|
72319
|
+
return false;
|
|
72320
|
+
if (tags.includes("@auth"))
|
|
72321
|
+
return false;
|
|
72322
|
+
if (tags.includes("@api"))
|
|
72323
|
+
return true;
|
|
72324
|
+
if (!tags.includes("@needs-auth"))
|
|
72325
|
+
return false;
|
|
72326
|
+
if (sharedAuthInjectEnabled && tags.includes("@auth-guarded") && hasGeneratedAuthGuard(code))
|
|
72327
|
+
return true;
|
|
72328
|
+
const isGeneratedVariant = tags.includes("@edge") || tags.includes("@bug");
|
|
72329
|
+
const hasLegacyInlineLogin = tags.includes("@discovered") && !isGeneratedVariant && hasInlineLoginSteps(code);
|
|
72330
|
+
return !tags.includes("@inline-login") && !hasLegacyInlineLogin;
|
|
72331
|
+
}
|
|
72332
|
+
function codeReadsStoredCredentials(code) {
|
|
72333
|
+
if (!code)
|
|
72334
|
+
return false;
|
|
72335
|
+
if (/__vqaLogin\b/.test(code))
|
|
72336
|
+
return true;
|
|
72337
|
+
for (const m of code.matchAll(/TEST_[A-Z0-9_]+/g)) {
|
|
72338
|
+
if (/_(?:EMAIL|PASSWORD)/.test(m[0]))
|
|
72339
|
+
return true;
|
|
72457
72340
|
}
|
|
72458
|
-
|
|
72341
|
+
for (const m of code.matchAll(/process\.env\s*\[([^\]]*)\]?/g)) {
|
|
72342
|
+
if (!/^\s*(['"])[^'"`]*\1\s*$/.test(m[1]))
|
|
72343
|
+
return true;
|
|
72344
|
+
}
|
|
72345
|
+
return false;
|
|
72459
72346
|
}
|
|
72460
|
-
function
|
|
72461
|
-
const
|
|
72347
|
+
function explicitAuthTypeTags(t) {
|
|
72348
|
+
const found = /* @__PURE__ */ new Set();
|
|
72349
|
+
for (const tag of t) {
|
|
72350
|
+
if (AUTH_TYPE_TAGS.includes(tag))
|
|
72351
|
+
found.add(tag);
|
|
72352
|
+
else if (Object.hasOwn(AUTH_TAG_ALIASES, tag))
|
|
72353
|
+
found.add(AUTH_TAG_ALIASES[tag]);
|
|
72354
|
+
}
|
|
72355
|
+
return [...found];
|
|
72356
|
+
}
|
|
72357
|
+
function invalidPlan(configurationError) {
|
|
72358
|
+
return {
|
|
72359
|
+
version: 1,
|
|
72360
|
+
source: "invalid",
|
|
72361
|
+
acquisition: "unsupported",
|
|
72362
|
+
presentation: "none",
|
|
72363
|
+
needsCookieState: false,
|
|
72364
|
+
needsStandingHeaders: false,
|
|
72365
|
+
standingHeadersMode: "none",
|
|
72366
|
+
needsLoginCreds: false,
|
|
72367
|
+
requiredEnvKeys: [],
|
|
72368
|
+
configurationError
|
|
72369
|
+
};
|
|
72370
|
+
}
|
|
72371
|
+
function explicitPlan(authTypeTag2, acquisition, presentation, opts) {
|
|
72372
|
+
return {
|
|
72373
|
+
version: 1,
|
|
72374
|
+
source: "explicit",
|
|
72375
|
+
authTypeTag: authTypeTag2,
|
|
72376
|
+
acquisition,
|
|
72377
|
+
presentation,
|
|
72378
|
+
needsCookieState: opts.cookie,
|
|
72379
|
+
needsStandingHeaders: opts.standingMode === "required",
|
|
72380
|
+
standingHeadersMode: opts.standingMode,
|
|
72381
|
+
needsLoginCreds: TEST_USER_ENV_KEYS.every((k) => opts.requiredEnvKeys.includes(k)),
|
|
72382
|
+
requiredEnvKeys: opts.requiredEnvKeys
|
|
72383
|
+
};
|
|
72384
|
+
}
|
|
72385
|
+
function deriveAuthPlan(tags, code, opts) {
|
|
72386
|
+
const t = Array.isArray(tags) ? tags : [];
|
|
72387
|
+
const sharedFlag = opts?.sharedAuthInjectEnabled ?? false;
|
|
72388
|
+
const isApi = t.includes("@api");
|
|
72389
|
+
const explicit = isApi ? explicitAuthTypeTags(t) : [];
|
|
72390
|
+
if (explicit.length > 0) {
|
|
72391
|
+
if (t.includes("@auth")) {
|
|
72392
|
+
return invalidPlan("@auth (self-login UI) cannot be combined with an explicit @api auth-type tag");
|
|
72393
|
+
}
|
|
72394
|
+
const loginCompose = explicit.filter((e) => e === AUTH_TAG_COOKIE_STATE || e === AUTH_TAG_LOGIN_COOKIE || e === AUTH_TAG_LOGIN_BEARER);
|
|
72395
|
+
if (explicit.length === 2 && explicit.includes(AUTH_TAG_STANDING) && loginCompose.length === 1) {
|
|
72396
|
+
const composedKeys = [...TEST_USER_ENV_KEYS, API_AUTH_HEADERS_ENV_KEY];
|
|
72397
|
+
switch (loginCompose[0]) {
|
|
72398
|
+
case AUTH_TAG_COOKIE_STATE:
|
|
72399
|
+
return explicitPlan(AUTH_TAG_COOKIE_STATE, "browser-bootstrap", "cookie", { cookie: sharedFlag, standingMode: "required", requiredEnvKeys: composedKeys });
|
|
72400
|
+
case AUTH_TAG_LOGIN_COOKIE:
|
|
72401
|
+
return explicitPlan(AUTH_TAG_LOGIN_COOKIE, "request-login", "cookie", { cookie: false, standingMode: "required", requiredEnvKeys: composedKeys });
|
|
72402
|
+
case AUTH_TAG_LOGIN_BEARER:
|
|
72403
|
+
return explicitPlan(AUTH_TAG_LOGIN_BEARER, "request-login", "bearer", { cookie: false, standingMode: "required", requiredEnvKeys: composedKeys });
|
|
72404
|
+
}
|
|
72405
|
+
}
|
|
72406
|
+
if (explicit.length > 1) {
|
|
72407
|
+
return invalidPlan(`conflicting auth-type tags: ${explicit.join(", ")}`);
|
|
72408
|
+
}
|
|
72409
|
+
switch (explicit[0]) {
|
|
72410
|
+
case AUTH_TAG_UNSUPPORTED:
|
|
72411
|
+
return {
|
|
72412
|
+
...invalidPlan("auth scheme not yet drivable (e.g. HMAC / mTLS / provider-replay) \u2014 needs manual configuration")
|
|
72413
|
+
};
|
|
72414
|
+
case AUTH_TAG_NONE:
|
|
72415
|
+
return explicitPlan(AUTH_TAG_NONE, "none", "none", { cookie: false, standingMode: "none", requiredEnvKeys: [] });
|
|
72416
|
+
case AUTH_TAG_STANDING:
|
|
72417
|
+
return explicitPlan(AUTH_TAG_STANDING, "standing-secret", "standing-header", { cookie: false, standingMode: "required", requiredEnvKeys: [API_AUTH_HEADERS_ENV_KEY] });
|
|
72418
|
+
case AUTH_TAG_LOGIN_BEARER:
|
|
72419
|
+
return explicitPlan(AUTH_TAG_LOGIN_BEARER, "request-login", "bearer", { cookie: false, standingMode: "none", requiredEnvKeys: [...TEST_USER_ENV_KEYS] });
|
|
72420
|
+
case AUTH_TAG_LOGIN_COOKIE:
|
|
72421
|
+
return explicitPlan(AUTH_TAG_LOGIN_COOKIE, "request-login", "cookie", { cookie: false, standingMode: "legacy-if-configured", requiredEnvKeys: [...TEST_USER_ENV_KEYS] });
|
|
72422
|
+
case AUTH_TAG_COOKIE_STATE:
|
|
72423
|
+
return explicitPlan(AUTH_TAG_COOKIE_STATE, "browser-bootstrap", "cookie", { cookie: sharedFlag, standingMode: "legacy-if-configured", requiredEnvKeys: [...TEST_USER_ENV_KEYS] });
|
|
72424
|
+
}
|
|
72425
|
+
}
|
|
72426
|
+
const cookie = legacyNeedsCookieState(t, code, sharedFlag);
|
|
72427
|
+
const authedLegacy = t.includes("@auth") || t.includes("@needs-auth") || isApi;
|
|
72428
|
+
const selfLoginWithoutStoredCreds = t.includes("@auth") && !t.includes("@needs-auth") && !isApi && !!code?.trim() && !/TEST_USER_EMAIL|TEST_USER_PASSWORD|__vqaLogin\b/.test(code);
|
|
72429
|
+
const apiWithoutStoredCreds = isApi && !t.includes("@auth") && !t.includes("@needs-auth") && !!code?.trim() && !codeReadsStoredCredentials(code);
|
|
72430
|
+
const needsLoginCreds = authedLegacy && !selfLoginWithoutStoredCreds && !apiWithoutStoredCreds;
|
|
72431
|
+
return {
|
|
72432
|
+
version: 1,
|
|
72433
|
+
source: "legacy",
|
|
72434
|
+
acquisition: cookie ? "browser-bootstrap" : authedLegacy ? "request-login" : "none",
|
|
72435
|
+
presentation: authedLegacy ? "cookie" : "none",
|
|
72436
|
+
needsCookieState: cookie,
|
|
72437
|
+
needsStandingHeaders: false,
|
|
72438
|
+
// A legacy bare-@api test keeps injecting standing headers IF the project configured them
|
|
72439
|
+
// (preserving today's behavior) — but does not require them. Non-@api legacy tests never inject.
|
|
72440
|
+
standingHeadersMode: isApi ? "legacy-if-configured" : "none",
|
|
72441
|
+
needsLoginCreds,
|
|
72442
|
+
requiredEnvKeys: needsLoginCreds ? [...TEST_USER_ENV_KEYS] : []
|
|
72443
|
+
};
|
|
72444
|
+
}
|
|
72445
|
+
function authTypeTag(tags) {
|
|
72446
|
+
const t = Array.isArray(tags) ? tags : [];
|
|
72447
|
+
const explicit = explicitAuthTypeTags(t);
|
|
72448
|
+
return explicit.length === 1 ? explicit[0] : void 0;
|
|
72449
|
+
}
|
|
72450
|
+
var AUTH_TAG_COOKIE_STATE, AUTH_TAG_LOGIN_COOKIE, AUTH_TAG_LOGIN_BEARER, AUTH_TAG_STANDING, AUTH_TAG_NONE, AUTH_TAG_UNSUPPORTED, AUTH_TYPE_TAGS, AUTH_TAG_ALIASES, TEST_USER_ENV_KEYS, API_AUTH_HEADERS_ENV_KEY;
|
|
72451
|
+
var init_auth_plan = __esm({
|
|
72452
|
+
"../shared/dist/auth-plan.js"() {
|
|
72453
|
+
"use strict";
|
|
72454
|
+
AUTH_TAG_COOKIE_STATE = "@auth-cookie-state";
|
|
72455
|
+
AUTH_TAG_LOGIN_COOKIE = "@auth-login-cookie";
|
|
72456
|
+
AUTH_TAG_LOGIN_BEARER = "@auth-login-bearer";
|
|
72457
|
+
AUTH_TAG_STANDING = "@auth-standing";
|
|
72458
|
+
AUTH_TAG_NONE = "@auth-none";
|
|
72459
|
+
AUTH_TAG_UNSUPPORTED = "@auth-unsupported";
|
|
72460
|
+
AUTH_TYPE_TAGS = [
|
|
72461
|
+
AUTH_TAG_COOKIE_STATE,
|
|
72462
|
+
AUTH_TAG_LOGIN_COOKIE,
|
|
72463
|
+
AUTH_TAG_LOGIN_BEARER,
|
|
72464
|
+
AUTH_TAG_STANDING,
|
|
72465
|
+
AUTH_TAG_NONE,
|
|
72466
|
+
AUTH_TAG_UNSUPPORTED
|
|
72467
|
+
];
|
|
72468
|
+
AUTH_TAG_ALIASES = {
|
|
72469
|
+
"@auth-cookie": AUTH_TAG_COOKIE_STATE,
|
|
72470
|
+
"@auth-bearer": AUTH_TAG_LOGIN_BEARER,
|
|
72471
|
+
"@auth-token": AUTH_TAG_LOGIN_BEARER,
|
|
72472
|
+
"@auth-api-key": AUTH_TAG_STANDING,
|
|
72473
|
+
"@auth-standing-header": AUTH_TAG_STANDING
|
|
72474
|
+
};
|
|
72475
|
+
TEST_USER_ENV_KEYS = ["TEST_USER_EMAIL", "TEST_USER_PASSWORD"];
|
|
72476
|
+
API_AUTH_HEADERS_ENV_KEY = "API_AUTH_HEADERS";
|
|
72477
|
+
}
|
|
72478
|
+
});
|
|
72479
|
+
|
|
72480
|
+
// ../shared/dist/assertion-strength.js
|
|
72481
|
+
function parseLastActionProofMode(raw) {
|
|
72482
|
+
const v = (raw ?? "").trim().toLowerCase();
|
|
72483
|
+
return v === "on" || v === "shadow" ? v : "off";
|
|
72484
|
+
}
|
|
72485
|
+
function isUrlProof(stmt) {
|
|
72486
|
+
if (URL_PROOF.test(stmt))
|
|
72487
|
+
return true;
|
|
72488
|
+
let calls = 0;
|
|
72489
|
+
for (const open of stmt.matchAll(POLL_OPEN)) {
|
|
72490
|
+
if (++calls > POLL_CALLS_MAX)
|
|
72491
|
+
break;
|
|
72492
|
+
const from = open.index + open[0].length;
|
|
72493
|
+
const args = balancedArguments(stmt, from, MATCHER_ARGS_MAX);
|
|
72494
|
+
if (args === null)
|
|
72495
|
+
continue;
|
|
72496
|
+
const subject = pollSubject(args);
|
|
72497
|
+
if (!POLL_PAGE_URL.test(subject))
|
|
72498
|
+
continue;
|
|
72499
|
+
if (!POLL_PAGE_URL_ONLY.test(subject) || PAGE_VALUE_MATCHER.test(stmt.slice(from + args.length)))
|
|
72500
|
+
return true;
|
|
72501
|
+
}
|
|
72502
|
+
return false;
|
|
72503
|
+
}
|
|
72504
|
+
function liveExpectStatements(uncommented) {
|
|
72505
|
+
const masked = maskedOutsideStrings(uncommented).split("\n");
|
|
72506
|
+
return accumulateStatements(uncommented.split("\n")).filter((s) => EXPECT_STMT.test(s.stmt) && EXPECT_STMT.test(masked[s.startLine - 1] ?? ""));
|
|
72507
|
+
}
|
|
72508
|
+
function stripLineComment2(ln) {
|
|
72509
|
+
let quote = null;
|
|
72510
|
+
for (let i = 0; i < ln.length; i++) {
|
|
72511
|
+
const c = ln[i];
|
|
72512
|
+
if (quote) {
|
|
72513
|
+
if (c === quote && ln[i - 1] !== "\\")
|
|
72514
|
+
quote = null;
|
|
72515
|
+
continue;
|
|
72516
|
+
}
|
|
72517
|
+
if (c === '"' || c === "'" || c === "`") {
|
|
72518
|
+
quote = c;
|
|
72519
|
+
continue;
|
|
72520
|
+
}
|
|
72521
|
+
if (c === "/" && ln[i + 1] === "/")
|
|
72522
|
+
return ln.slice(0, i);
|
|
72523
|
+
}
|
|
72524
|
+
return ln;
|
|
72525
|
+
}
|
|
72526
|
+
function splitInteractionStatementsWithLines(lines) {
|
|
72527
|
+
const out = [];
|
|
72528
|
+
let depth = 0;
|
|
72529
|
+
let scaffold = false;
|
|
72530
|
+
for (let i = 0; i < lines.length; i++) {
|
|
72531
|
+
const ln = stripLineComment2(lines[i]).trim();
|
|
72532
|
+
if (!ln)
|
|
72533
|
+
continue;
|
|
72534
|
+
const isContinuation = out.length > 0 && (ln.startsWith(".") || depth > 0 && !scaffold);
|
|
72535
|
+
if (isContinuation) {
|
|
72536
|
+
out[out.length - 1].stmt += " " + ln;
|
|
72537
|
+
depth += parenDepthDelta(ln);
|
|
72538
|
+
} else {
|
|
72539
|
+
out.push({ stmt: ln, startLine: i + 1 });
|
|
72540
|
+
depth = parenDepthDelta(ln);
|
|
72541
|
+
scaffold = BLOCK_SCAFFOLD2.test(ln);
|
|
72542
|
+
}
|
|
72543
|
+
if (depth < 0)
|
|
72544
|
+
depth = 0;
|
|
72545
|
+
}
|
|
72546
|
+
return out;
|
|
72547
|
+
}
|
|
72548
|
+
function testBlockIds(lines) {
|
|
72549
|
+
const ids = new Array(lines.length).fill(0);
|
|
72462
72550
|
let depth = 0;
|
|
72463
72551
|
let open = false;
|
|
72464
72552
|
let any = false;
|
|
72465
72553
|
let block = 0;
|
|
72466
72554
|
for (let i = 0; i < lines.length; i++) {
|
|
72467
|
-
const ln =
|
|
72555
|
+
const ln = stripLineComment2(lines[i]).trim();
|
|
72468
72556
|
if (!open) {
|
|
72469
72557
|
if (!TEST_BLOCK_OPEN.test(ln))
|
|
72470
72558
|
continue;
|
|
@@ -72548,7 +72636,7 @@ function expectSubjectSpan(stmt) {
|
|
|
72548
72636
|
}
|
|
72549
72637
|
return null;
|
|
72550
72638
|
}
|
|
72551
|
-
function resolveSubjectBindings(stmts, bindings, blockOfLine) {
|
|
72639
|
+
function resolveSubjectBindings(stmts, bindings, blockOfLine, boundAt) {
|
|
72552
72640
|
if (bindings.length === 0)
|
|
72553
72641
|
return [...stmts];
|
|
72554
72642
|
return stmts.map((item) => {
|
|
@@ -72571,14 +72659,22 @@ function resolveSubjectBindings(stmts, bindings, blockOfLine) {
|
|
|
72571
72659
|
subject = `${lead[1]}${found.expr.replace(/;\s*$/, "")}${subject.slice(lead[0].length)}`;
|
|
72572
72660
|
line = found.line;
|
|
72573
72661
|
}
|
|
72574
|
-
|
|
72662
|
+
const out = { ...item, stmt: `${item.stmt.slice(0, span.from)}${subject}${item.stmt.slice(span.to)}` };
|
|
72663
|
+
if (boundAt !== void 0 && line !== item.startLine)
|
|
72664
|
+
boundAt.set(out, line);
|
|
72665
|
+
return out;
|
|
72575
72666
|
});
|
|
72576
72667
|
}
|
|
72577
72668
|
function stripLoginScaffolding(code) {
|
|
72578
|
-
const
|
|
72669
|
+
const lines = code.split("\n");
|
|
72670
|
+
return keptScaffoldingLines(lines).map((i) => lines[i]).join("\n");
|
|
72671
|
+
}
|
|
72672
|
+
function keptScaffoldingLines(lines) {
|
|
72673
|
+
const kept = [];
|
|
72579
72674
|
let inAuth = false;
|
|
72580
72675
|
let inInbox = false;
|
|
72581
|
-
for (
|
|
72676
|
+
for (let i = 0; i < lines.length; i++) {
|
|
72677
|
+
const ln = lines[i];
|
|
72582
72678
|
if (!inAuth && !inInbox && AUTH_START.test(ln)) {
|
|
72583
72679
|
inAuth = true;
|
|
72584
72680
|
continue;
|
|
@@ -72599,9 +72695,9 @@ function stripLoginScaffolding(code) {
|
|
|
72599
72695
|
}
|
|
72600
72696
|
if (LOGIN_CALL_LINE.test(ln))
|
|
72601
72697
|
continue;
|
|
72602
|
-
|
|
72698
|
+
kept.push(i);
|
|
72603
72699
|
}
|
|
72604
|
-
return
|
|
72700
|
+
return kept;
|
|
72605
72701
|
}
|
|
72606
72702
|
function stripCommentsAndLogs(code) {
|
|
72607
72703
|
return stripCoverageComments(code).split("\n").filter((ln) => !/^\s*console\./.test(ln)).join("\n");
|
|
@@ -72753,6 +72849,41 @@ function isVacuousErrorAbsence(stmt, presence) {
|
|
|
72753
72849
|
return false;
|
|
72754
72850
|
return !presence().includes(m[1]);
|
|
72755
72851
|
}
|
|
72852
|
+
function isVacuousAccountAbsence(stmt, shown, account) {
|
|
72853
|
+
if (!claimsAbsence(stmt))
|
|
72854
|
+
return false;
|
|
72855
|
+
if (!ABSENCE_MATCHER.test(stmt)) {
|
|
72856
|
+
const negated = NEGATED_TEXT.exec(stmt);
|
|
72857
|
+
if (!negated)
|
|
72858
|
+
return false;
|
|
72859
|
+
const read = account.exec(stmt.slice(negated.index));
|
|
72860
|
+
return read !== null && !shown().has(read[0]);
|
|
72861
|
+
}
|
|
72862
|
+
const m = account.exec(stmt);
|
|
72863
|
+
if (!m || shown().has(m[0]))
|
|
72864
|
+
return false;
|
|
72865
|
+
for (let at = endOfEnclosingCall(stmt, m.index + m[0].length); at < stmt.length; at = endOfEnclosingCall(stmt, at)) {
|
|
72866
|
+
SCOPING_STEP.lastIndex = at;
|
|
72867
|
+
if (SCOPING_STEP.test(stmt))
|
|
72868
|
+
return false;
|
|
72869
|
+
}
|
|
72870
|
+
return true;
|
|
72871
|
+
}
|
|
72872
|
+
function endOfEnclosingCall(stmt, from) {
|
|
72873
|
+
let depth = 0;
|
|
72874
|
+
for (let i = from; i < stmt.length; i++) {
|
|
72875
|
+
const c = stmt[i];
|
|
72876
|
+
if (c === "'" || c === '"') {
|
|
72877
|
+
for (i++; i < stmt.length && stmt[i] !== c; i++)
|
|
72878
|
+
if (stmt[i] === "\\")
|
|
72879
|
+
i++;
|
|
72880
|
+
} else if (c === "(")
|
|
72881
|
+
depth++;
|
|
72882
|
+
else if (c === ")" && depth-- === 0)
|
|
72883
|
+
return i + 1;
|
|
72884
|
+
}
|
|
72885
|
+
return stmt.length;
|
|
72886
|
+
}
|
|
72756
72887
|
function isBareContainerVisibility(stmt) {
|
|
72757
72888
|
return BARE_CONTAINER_ROLE.test(stmt) && !GET_BY_TEXT.test(stmt) && !HAS_TEXT_FILTER.test(stmt) && !TEXT_CONTENT_MATCHER.test(stmt);
|
|
72758
72889
|
}
|
|
@@ -72834,7 +72965,7 @@ function roleNames(s) {
|
|
|
72834
72965
|
function interactedControlNames(lines) {
|
|
72835
72966
|
const names = /* @__PURE__ */ new Set();
|
|
72836
72967
|
for (const raw of lines) {
|
|
72837
|
-
const ln =
|
|
72968
|
+
const ln = stripLineComment2(raw);
|
|
72838
72969
|
if (!INTERACT_VERB.test(ln))
|
|
72839
72970
|
continue;
|
|
72840
72971
|
for (const n of roleNames(ln))
|
|
@@ -73030,6 +73161,14 @@ function balancedArguments(code, from, limit = code.length) {
|
|
|
73030
73161
|
}
|
|
73031
73162
|
return null;
|
|
73032
73163
|
}
|
|
73164
|
+
function expectCallTail(stmt) {
|
|
73165
|
+
const at = stmt.search(EXPECT_CALL_RE);
|
|
73166
|
+
if (at < 0)
|
|
73167
|
+
return null;
|
|
73168
|
+
const from = stmt.indexOf("(", at) + 1;
|
|
73169
|
+
const args = balancedArguments(stmt, from, MATCHER_ARGS_MAX);
|
|
73170
|
+
return args === null ? null : stmt.slice(from + args.length).trimStart();
|
|
73171
|
+
}
|
|
73033
73172
|
function matcherArgumentsAreConstant(body, from) {
|
|
73034
73173
|
MATCHER_OPEN.lastIndex = from;
|
|
73035
73174
|
const opened = MATCHER_OPEN.exec(body);
|
|
@@ -73071,9 +73210,12 @@ function envValueKey(name) {
|
|
|
73071
73210
|
function enteredValues(stmts) {
|
|
73072
73211
|
const values = /* @__PURE__ */ new Map();
|
|
73073
73212
|
const navLines = [];
|
|
73213
|
+
const accountConsts = /* @__PURE__ */ new Set();
|
|
73074
73214
|
for (const { stmt, startLine } of stmts) {
|
|
73075
73215
|
if (PAGE_NAV.test(stmt))
|
|
73076
73216
|
navLines.push(startLine);
|
|
73217
|
+
for (const c of stmt.matchAll(ACCOUNT_CONST))
|
|
73218
|
+
accountConsts.add(c[1].replace(/\$/g, "\\$"));
|
|
73077
73219
|
let m;
|
|
73078
73220
|
ENTERED_VALUE.lastIndex = 0;
|
|
73079
73221
|
const add = (value) => {
|
|
@@ -73089,7 +73231,8 @@ function enteredValues(stmts) {
|
|
|
73089
73231
|
while (m = ENTERED_ENV.exec(stmt))
|
|
73090
73232
|
add(envValueKey(m[1] ?? m[2] ?? m[3] ?? m[4]));
|
|
73091
73233
|
}
|
|
73092
|
-
|
|
73234
|
+
const consts = accountConsts.size > 0 ? `|(?<![\\w$.])(?:${[...accountConsts].join("|")})(?![\\w$])` : "";
|
|
73235
|
+
return { values, navLines, account: new RegExp(`${ACCOUNT_ENV}${consts}`) };
|
|
73093
73236
|
}
|
|
73094
73237
|
function countBelow(lines, line) {
|
|
73095
73238
|
let lo = 0;
|
|
@@ -73226,6 +73369,9 @@ function comparesWithItself(subject, tail) {
|
|
|
73226
73369
|
return expected === squash2(m[1] === "toHaveCount" ? `${subject}.count()` : subject);
|
|
73227
73370
|
}
|
|
73228
73371
|
function asPlainAssertion(s) {
|
|
73372
|
+
return plainAssertion(s, false);
|
|
73373
|
+
}
|
|
73374
|
+
function plainAssertion(s, keepSelfCompare) {
|
|
73229
73375
|
const { stmt } = s;
|
|
73230
73376
|
if (COUNT_AT_LEAST_ZERO.test(stmt))
|
|
73231
73377
|
return [];
|
|
@@ -73234,13 +73380,13 @@ function asPlainAssertion(s) {
|
|
|
73234
73380
|
return [s];
|
|
73235
73381
|
const plain = subject.replace(/^await\s+/, "").trim();
|
|
73236
73382
|
const subjectAt = stmt.indexOf(subject, stmt.search(EXPECT_CALL_RE));
|
|
73237
|
-
const tail = stmt.slice(subjectAt + subject.length).trimStart();
|
|
73383
|
+
const tail = (stmt.startsWith("expect.poll", stmt.search(EXPECT_CALL_RE)) ? expectCallTail(stmt) : null) ?? stmt.slice(subjectAt + subject.length).trimStart();
|
|
73238
73384
|
const as = (rewritten) => [{ ...s, stmt: rewritten }];
|
|
73239
73385
|
if (LOCATOR_EXPR.test(plain) && !LOCATOR_VALUE_READ.test(plain) && ALWAYS_TRUE_ON_OBJECT.test(tail))
|
|
73240
73386
|
return [];
|
|
73241
73387
|
if (DEFINED_VALUE_READ.test(plain) && ALWAYS_DEFINED.test(tail))
|
|
73242
73388
|
return [];
|
|
73243
|
-
if (comparesWithItself(plain, tail))
|
|
73389
|
+
if (!keepSelfCompare && comparesWithItself(plain, tail))
|
|
73244
73390
|
return [];
|
|
73245
73391
|
const visible = /^(.+)\.\s*isVisible\s*\(\s*\)$/s.exec(plain);
|
|
73246
73392
|
if (visible && IS_VISIBLE_TRUE.test(tail))
|
|
@@ -73251,6 +73397,9 @@ function asPlainAssertion(s) {
|
|
|
73251
73397
|
}
|
|
73252
73398
|
return [s];
|
|
73253
73399
|
}
|
|
73400
|
+
function assertionStrengthHoistedReadsOn(value = typeof process !== "undefined" ? process.env?.ASSERTION_STRENGTH_HOISTED_READS : void 0) {
|
|
73401
|
+
return /^(1|true|on)$/i.test((value ?? "").trim());
|
|
73402
|
+
}
|
|
73254
73403
|
function creditsOutcomeAlways(stmt, entered, startLine) {
|
|
73255
73404
|
if (!OUTCOME_ALWAYS.some((re) => re.test(stmt)))
|
|
73256
73405
|
return false;
|
|
@@ -73283,6 +73432,22 @@ function successNoticeQuote(stmt) {
|
|
|
73283
73432
|
}
|
|
73284
73433
|
return null;
|
|
73285
73434
|
}
|
|
73435
|
+
function namedPagePath(arg) {
|
|
73436
|
+
const text = arg.trim();
|
|
73437
|
+
let path;
|
|
73438
|
+
const quoted = /^(['"`])([^'"`]*)\1$/.exec(text);
|
|
73439
|
+
const regex = quoted ? null : /^\/((?:\\.|[^/\\])+)\/[a-z]*$/.exec(text);
|
|
73440
|
+
if (quoted) {
|
|
73441
|
+
path = quoted[2].replace(/^\$\{[^}]*\}/, "").replace(/^\*\*/, "").replace(/^[a-z][a-z\d+.-]*:\/\/[^/]*/i, "").replace(/\*\*$/, "");
|
|
73442
|
+
} else if (regex) {
|
|
73443
|
+
path = regex[1].replace(/^\^/, "").replace(/^\.\*/, "").replace(/\$$/, "").replace(/\\([/.-])/g, "$1");
|
|
73444
|
+
} else {
|
|
73445
|
+
return null;
|
|
73446
|
+
}
|
|
73447
|
+
if (!PLAIN_PAGE_PATH.test(path))
|
|
73448
|
+
return null;
|
|
73449
|
+
return path.length > 1 && path.endsWith("/") ? path.slice(0, -1) : path;
|
|
73450
|
+
}
|
|
73286
73451
|
function provesStoredControlValue(stmt, startLine, persistence) {
|
|
73287
73452
|
if (!persistence || startLine === void 0)
|
|
73288
73453
|
return false;
|
|
@@ -73309,7 +73474,64 @@ function reopenedAfterSave(startLine, persistence, reopens = persistence.reloadL
|
|
|
73309
73474
|
}
|
|
73310
73475
|
return lo < reopens.length && reopens[lo] < startLine;
|
|
73311
73476
|
}
|
|
73312
|
-
function
|
|
73477
|
+
function actsBetween(withLines, from, to) {
|
|
73478
|
+
let acts = actLinesOf.get(withLines);
|
|
73479
|
+
if (acts === void 0) {
|
|
73480
|
+
acts = withLines.filter((s) => ACTS.test(s.stmt)).map((s) => s.startLine).sort((a, b) => a - b);
|
|
73481
|
+
actLinesOf.set(withLines, acts);
|
|
73482
|
+
}
|
|
73483
|
+
let lo = 0;
|
|
73484
|
+
let hi = acts.length;
|
|
73485
|
+
while (lo < hi) {
|
|
73486
|
+
const mid = lo + hi >> 1;
|
|
73487
|
+
if (acts[mid] <= from)
|
|
73488
|
+
lo = mid + 1;
|
|
73489
|
+
else
|
|
73490
|
+
hi = mid;
|
|
73491
|
+
}
|
|
73492
|
+
return lo < acts.length && acts[lo] < to;
|
|
73493
|
+
}
|
|
73494
|
+
function signInProofWindow(stmts, withLines, lines, blockIds) {
|
|
73495
|
+
if (blockIds === null)
|
|
73496
|
+
return void 0;
|
|
73497
|
+
const testBodies2 = /* @__PURE__ */ new Set();
|
|
73498
|
+
for (let i = 0; i < lines.length; i++) {
|
|
73499
|
+
const id = blockIds[i];
|
|
73500
|
+
if (id > 0 && (i === 0 || blockIds[i - 1] !== id) && TEST_BODY_OPEN.test(stripLineComment2(lines[i]).trim()))
|
|
73501
|
+
testBodies2.add(id);
|
|
73502
|
+
}
|
|
73503
|
+
const blockOf = (i) => blockIds[withLines[i].startLine - 1];
|
|
73504
|
+
const passwordAt = stmts.findIndex((stmt, i) => testBodies2.has(blockOf(i)) && ENV_PASSWORD_ENTRY.test(stmt));
|
|
73505
|
+
if (passwordAt < 0)
|
|
73506
|
+
return void 0;
|
|
73507
|
+
const body = blockOf(passwordAt);
|
|
73508
|
+
let clickAt = passwordAt + 1;
|
|
73509
|
+
while (clickAt < stmts.length && FORM_INPUT.test(stmts[clickAt]) && !ANY_CLICK.test(stmts[clickAt]))
|
|
73510
|
+
clickAt++;
|
|
73511
|
+
if (clickAt >= stmts.length || blockOf(clickAt) !== body || !ANY_CLICK.test(stmts[clickAt]) || NAV_LOCATOR.test(stmts[clickAt]))
|
|
73512
|
+
return void 0;
|
|
73513
|
+
let end = clickAt + 1;
|
|
73514
|
+
for (; end < stmts.length && blockOf(end) === body; end++) {
|
|
73515
|
+
if (CLOSERS_ONLY.test(stmts[end]))
|
|
73516
|
+
continue;
|
|
73517
|
+
if (!ASSERT_OR_WAIT.test(stmts[end]) || ACTS.test(stmts[end]))
|
|
73518
|
+
return void 0;
|
|
73519
|
+
}
|
|
73520
|
+
return { after: withLines[clickAt].startLine, until: end < stmts.length ? withLines[end].startLine : Number.POSITIVE_INFINITY };
|
|
73521
|
+
}
|
|
73522
|
+
function isAccountControlCheck(stmt) {
|
|
73523
|
+
if (!VISIBILITY_MATCHER.test(stmt) || NEGATED_ASSERT.test(stmt) || OPTION_ABSENCE.test(stmt))
|
|
73524
|
+
return false;
|
|
73525
|
+
const role = ACCOUNT_CONTROL_ROLE.exec(stmt);
|
|
73526
|
+
if (!role)
|
|
73527
|
+
return false;
|
|
73528
|
+
const rest = stmt.slice(role.index + role[0].length, role.index + role[0].length + 300);
|
|
73529
|
+
const close = rest.indexOf("}");
|
|
73530
|
+
const options = close < 0 ? rest : rest.slice(0, close);
|
|
73531
|
+
const name = options.match(/(?:^|[\s,])name\s*:\s*/);
|
|
73532
|
+
return name !== null && ACCOUNT_EMAIL_ENV.test(options.slice(name.index + name[0].length));
|
|
73533
|
+
}
|
|
73534
|
+
function classifyOutcomeProof(stmts, mutated, reloaded, clicked, entered, firstMutLine, persistence, signedIn) {
|
|
73313
73535
|
if (mutated && hasAttributeTransition(stmts))
|
|
73314
73536
|
return { kind: "durable" };
|
|
73315
73537
|
const notices = [];
|
|
@@ -73319,6 +73541,13 @@ function classifyOutcomeProof(stmts, mutated, reloaded, clicked, entered, firstM
|
|
|
73319
73541
|
};
|
|
73320
73542
|
let presenceText;
|
|
73321
73543
|
const presence = () => presenceText ??= stmts.filter((o) => !ABSENCE_MATCHER.test(o.stmt) && !NEGATED_ASSERT.test(o.stmt)).map((o) => o.stmt).join("\n");
|
|
73544
|
+
let shownAccounts;
|
|
73545
|
+
const shown = () => {
|
|
73546
|
+
if (shownAccounts)
|
|
73547
|
+
return shownAccounts;
|
|
73548
|
+
const ref = new RegExp(entered.account.source, "g");
|
|
73549
|
+
return shownAccounts = new Set(stmts.filter((o) => !claimsAbsence(o.stmt)).flatMap((o) => Array.from(o.stmt.matchAll(ref), (m) => m[0])));
|
|
73550
|
+
};
|
|
73322
73551
|
for (const { stmt, startLine } of stmts) {
|
|
73323
73552
|
if (firstMutLine !== void 0 && startLine !== void 0 && startLine < firstMutLine)
|
|
73324
73553
|
continue;
|
|
@@ -73326,6 +73555,11 @@ function classifyOutcomeProof(stmts, mutated, reloaded, clicked, entered, firstM
|
|
|
73326
73555
|
continue;
|
|
73327
73556
|
if (COUNT_ONE.test(stmt) && quotedAssertedStrings(stmt).some((t) => clicked.has(t.toLowerCase())))
|
|
73328
73557
|
continue;
|
|
73558
|
+
if (isVacuousAccountAbsence(stmt, shown, entered.account))
|
|
73559
|
+
continue;
|
|
73560
|
+
if (signedIn && startLine !== void 0 && startLine > signedIn.after && startLine < signedIn.until && isAccountControlCheck(stmt)) {
|
|
73561
|
+
return { kind: "durable" };
|
|
73562
|
+
}
|
|
73329
73563
|
if (creditsOutcomeAlways(stmt, entered, startLine))
|
|
73330
73564
|
return { kind: "durable" };
|
|
73331
73565
|
if (mutated && !NEGATED_ASSERT.test(stmt) && MESSAGE_SURFACE.test(stmt) && OUTCOME_TEXT.test(assertedText(stmt))) {
|
|
@@ -73407,6 +73641,53 @@ function noticeOnlyExemption(clicked, noticeText, interactionStmts) {
|
|
|
73407
73641
|
function detectOutcomeProof(stmts, mutated, reloaded, clicked, entered, firstMutLine) {
|
|
73408
73642
|
return classifyOutcomeProof(stmts, mutated, reloaded, clicked, entered, firstMutLine).kind !== "none";
|
|
73409
73643
|
}
|
|
73644
|
+
function clickLabel(stmt) {
|
|
73645
|
+
let label = null;
|
|
73646
|
+
for (const m of stmt.matchAll(CONTROL_LABEL))
|
|
73647
|
+
label = m[2] ?? m[3] ?? null;
|
|
73648
|
+
return label;
|
|
73649
|
+
}
|
|
73650
|
+
function teardownLines(lines) {
|
|
73651
|
+
const out = new Array(lines.length).fill(false);
|
|
73652
|
+
let open = false;
|
|
73653
|
+
let depth = 0;
|
|
73654
|
+
for (let i = 0; i < lines.length; i++) {
|
|
73655
|
+
const ln = stripLineComment2(lines[i]).trim();
|
|
73656
|
+
let from = 0;
|
|
73657
|
+
if (!open) {
|
|
73658
|
+
const m = TEARDOWN_OPEN.exec(ln);
|
|
73659
|
+
if (!m)
|
|
73660
|
+
continue;
|
|
73661
|
+
open = true;
|
|
73662
|
+
depth = 0;
|
|
73663
|
+
from = m.index;
|
|
73664
|
+
}
|
|
73665
|
+
out[i] = true;
|
|
73666
|
+
let closed = false;
|
|
73667
|
+
let quote = null;
|
|
73668
|
+
for (let k = from; k < ln.length; k++) {
|
|
73669
|
+
const ch = ln[k];
|
|
73670
|
+
if (quote !== null) {
|
|
73671
|
+
if (ch === "\\")
|
|
73672
|
+
k++;
|
|
73673
|
+
else if (ch === quote)
|
|
73674
|
+
quote = null;
|
|
73675
|
+
continue;
|
|
73676
|
+
}
|
|
73677
|
+
if (ch === "'" || ch === '"' || ch === "`")
|
|
73678
|
+
quote = ch;
|
|
73679
|
+
else if (ch === "{")
|
|
73680
|
+
depth++;
|
|
73681
|
+
else if (ch === "}") {
|
|
73682
|
+
depth--;
|
|
73683
|
+
closed = true;
|
|
73684
|
+
}
|
|
73685
|
+
}
|
|
73686
|
+
if (depth <= 0 && closed)
|
|
73687
|
+
open = false;
|
|
73688
|
+
}
|
|
73689
|
+
return out;
|
|
73690
|
+
}
|
|
73410
73691
|
function validateAssertionStrength(code, opts = {}) {
|
|
73411
73692
|
const body = stripLoginScaffolding(code);
|
|
73412
73693
|
const lines = body.split("\n");
|
|
@@ -73450,7 +73731,13 @@ function validateAssertionStrength(code, opts = {}) {
|
|
|
73450
73731
|
const interactionStmts = inlineLocatorBindings(interactionStmtsRaw);
|
|
73451
73732
|
const blockIds = testBlockIds(lines);
|
|
73452
73733
|
const blockOfLine = (line) => blockIds?.[line - 1] ?? 0;
|
|
73453
|
-
const
|
|
73734
|
+
const hoistedReads = assertionStrengthHoistedReadsOn();
|
|
73735
|
+
const boundAt = hoistedReads ? /* @__PURE__ */ new Map() : void 0;
|
|
73736
|
+
const resolved = resolveSubjectBindings(stmts, scopedLocatorBindings(interactionStmtsWithLines, blockOfLine), blockOfLine, boundAt);
|
|
73737
|
+
const checks = boundAt === void 0 ? resolved : resolved.flatMap((s) => {
|
|
73738
|
+
const from = boundAt.get(s);
|
|
73739
|
+
return plainAssertion(s, from !== void 0 && actsBetween(interactionStmtsWithLines, from, s.startLine));
|
|
73740
|
+
});
|
|
73454
73741
|
const insideTest = linesInsideTestBlocks(lines);
|
|
73455
73742
|
const inTestOrder = (i) => insideTest === null || insideTest[interactionStmtsWithLines[i].startLine - 1] === true;
|
|
73456
73743
|
let mutated = opts.interactionPerformed === true;
|
|
@@ -73460,9 +73747,34 @@ function validateAssertionStrength(code, opts = {}) {
|
|
|
73460
73747
|
let navClicks = 0;
|
|
73461
73748
|
const persistence = { mutLines: [], reloadLines: [], reloadCalls: [] };
|
|
73462
73749
|
const openedPages = /* @__PURE__ */ new Set();
|
|
73750
|
+
let checkedPage = null;
|
|
73751
|
+
const savedOnCheckedPage = /* @__PURE__ */ new Set();
|
|
73752
|
+
const saveAt = (i, at) => {
|
|
73753
|
+
lastMutIdx = i;
|
|
73754
|
+
if (!inTestOrder(i))
|
|
73755
|
+
return;
|
|
73756
|
+
persistence.mutLines.push(at);
|
|
73757
|
+
if (firstMutIdx < 0)
|
|
73758
|
+
firstMutIdx = i;
|
|
73759
|
+
if (checkedPage !== null)
|
|
73760
|
+
savedOnCheckedPage.add(checkedPage);
|
|
73761
|
+
};
|
|
73762
|
+
const lastActionProof = opts.lastActionProof ?? "off";
|
|
73763
|
+
const teardown = lastActionProof === "off" ? null : teardownLines(lines);
|
|
73764
|
+
const acts = { last: null, prev: null, count: 0 };
|
|
73765
|
+
const noteAct = (i, at, kind) => {
|
|
73766
|
+
if (teardown === null || teardown[at - 1] || !inTestOrder(i))
|
|
73767
|
+
return;
|
|
73768
|
+
if (kind !== "enter")
|
|
73769
|
+
acts.count++;
|
|
73770
|
+
acts.prev = acts.last;
|
|
73771
|
+
acts.last = { i, kind };
|
|
73772
|
+
};
|
|
73463
73773
|
for (let i = 0; i < interactionStmts.length; i++) {
|
|
73464
73774
|
const ln = interactionStmts[i];
|
|
73465
73775
|
const at = interactionStmtsWithLines[i].startLine;
|
|
73776
|
+
if (teardown !== null && acts.last?.kind === "fill" && ENTER_PRESS.test(ln))
|
|
73777
|
+
noteAct(i, at, "enter");
|
|
73466
73778
|
if (RELOAD.test(ln)) {
|
|
73467
73779
|
persistence.reloadLines.push(at);
|
|
73468
73780
|
persistence.reloadCalls.push(at);
|
|
@@ -73470,32 +73782,31 @@ function validateAssertionStrength(code, opts = {}) {
|
|
|
73470
73782
|
const opened = ln.match(/\.goto\s*\(\s*([^,)]+)/);
|
|
73471
73783
|
if (opened) {
|
|
73472
73784
|
const page = opened[1].trim();
|
|
73473
|
-
|
|
73785
|
+
const path = namedPagePath(page);
|
|
73786
|
+
if (openedPages.has(page) || path !== null && savedOnCheckedPage.has(path))
|
|
73474
73787
|
persistence.reloadLines.push(at);
|
|
73475
|
-
|
|
73476
|
-
|
|
73477
|
-
}
|
|
73788
|
+
openedPages.add(page);
|
|
73789
|
+
checkedPage = null;
|
|
73790
|
+
}
|
|
73791
|
+
if (/\bpage\s*\.\s*go(?:Back|Forward)\s*\(/.test(ln))
|
|
73792
|
+
checkedPage = null;
|
|
73793
|
+
const checked = URL_CHECK_ARG.exec(ln);
|
|
73794
|
+
if (checked)
|
|
73795
|
+
checkedPage = namedPagePath(checked[1] ?? checked[2]);
|
|
73478
73796
|
if (FORM_INPUT.test(ln)) {
|
|
73479
73797
|
mutated = true;
|
|
73480
|
-
|
|
73481
|
-
|
|
73482
|
-
persistence.mutLines.push(at);
|
|
73483
|
-
if (firstMutIdx < 0)
|
|
73484
|
-
firstMutIdx = i;
|
|
73485
|
-
}
|
|
73798
|
+
saveAt(i, at);
|
|
73799
|
+
noteAct(i, at, "fill");
|
|
73486
73800
|
continue;
|
|
73487
73801
|
}
|
|
73488
73802
|
if (ANY_CLICK.test(ln)) {
|
|
73489
73803
|
if (NAV_LOCATOR.test(ln)) {
|
|
73490
73804
|
navClicks++;
|
|
73805
|
+
checkedPage = null;
|
|
73491
73806
|
} else {
|
|
73492
73807
|
mutated = true;
|
|
73493
|
-
|
|
73494
|
-
|
|
73495
|
-
persistence.mutLines.push(at);
|
|
73496
|
-
if (firstMutIdx < 0)
|
|
73497
|
-
firstMutIdx = i;
|
|
73498
|
-
}
|
|
73808
|
+
saveAt(i, at);
|
|
73809
|
+
noteAct(i, at, "click");
|
|
73499
73810
|
}
|
|
73500
73811
|
}
|
|
73501
73812
|
}
|
|
@@ -73528,9 +73839,28 @@ function validateAssertionStrength(code, opts = {}) {
|
|
|
73528
73839
|
};
|
|
73529
73840
|
}
|
|
73530
73841
|
const orderedPersistence = firstMutLine !== void 0 ? persistence : void 0;
|
|
73531
|
-
const
|
|
73842
|
+
const signedIn = signInProofWindow(interactionStmts, interactionStmtsWithLines, lines, blockIds);
|
|
73843
|
+
const proof = classifyOutcomeProof(checks, mutated, reloaded, clickedControlNames(interactionStmts), entered, firstMutLine, orderedPersistence, signedIn);
|
|
73532
73844
|
if (proof.kind === "durable") {
|
|
73533
73845
|
const signals2 = base2({ interacted, mutated, navOnly, hasOutcomeProof: true, terminal });
|
|
73846
|
+
const { last, prev } = acts;
|
|
73847
|
+
if (teardown !== null && last !== null && acts.count >= 2 && last.kind !== "fill" && (last.kind === "enter" || isCommitClick(interactionStmts[last.i]) && !(prev?.kind === "click" && isDestructiveClick(interactionStmts[prev.i])))) {
|
|
73848
|
+
const lastLine = interactionStmtsWithLines[last.i].startLine;
|
|
73849
|
+
const clicked = clickedControlNames(interactionStmts);
|
|
73850
|
+
const after = classifyOutcomeProof(checks, mutated, reloaded, clicked, entered, lastLine, orderedPersistence, signedIn);
|
|
73851
|
+
const unproven = after.kind === "none" || after.kind === "notice" && noticeOnlyExemption(clicked, after.noticeText, interactionStmts) === null;
|
|
73852
|
+
if (unproven && lastActionProof === "on") {
|
|
73853
|
+
const line = (keptScaffoldingLines(code.split("\n"))[lastLine - 1] ?? lastLine - 1) + 1;
|
|
73854
|
+
return {
|
|
73855
|
+
ok: false,
|
|
73856
|
+
severity: "block",
|
|
73857
|
+
reason: `the last save (line ${line}) has no outcome check after it (the earlier check proves only the earlier action)`,
|
|
73858
|
+
signals: { ...signals2, lastActionUnproven: true }
|
|
73859
|
+
};
|
|
73860
|
+
}
|
|
73861
|
+
if (unproven)
|
|
73862
|
+
signals2.lastActionUnproven = true;
|
|
73863
|
+
}
|
|
73534
73864
|
return { ok: true, severity: "none", reason: "proves an outcome (count / diff / value / revealed content)", signals: signals2 };
|
|
73535
73865
|
}
|
|
73536
73866
|
if (mutated && proof.kind === "notice") {
|
|
@@ -73579,7 +73909,7 @@ function validateAssertionStrength(code, opts = {}) {
|
|
|
73579
73909
|
signals
|
|
73580
73910
|
};
|
|
73581
73911
|
}
|
|
73582
|
-
const urlProofAfter = interactionStmts.some((s, i) => i > lastMutIdx &&
|
|
73912
|
+
const urlProofAfter = interactionStmts.some((s, i) => i > lastMutIdx && isUrlProof(s));
|
|
73583
73913
|
if (urlProofAfter) {
|
|
73584
73914
|
return {
|
|
73585
73915
|
ok: false,
|
|
@@ -73616,7 +73946,7 @@ function validateAssertionStrength(code, opts = {}) {
|
|
|
73616
73946
|
signals
|
|
73617
73947
|
};
|
|
73618
73948
|
}
|
|
73619
|
-
var ERROR_BANNER, OUTCOME_ALWAYS, FORM_INPUT, ANY_CLICK, NAV_LOCATOR, URL_PROOF, RELOAD, EXPECT_STMT, BLOCK_SCAFFOLD2, TEST_BLOCK_OPEN, LOCATOR_BINDING, EXPECT_OPEN, STATE_MATCHER, CHROME_LOCATOR, CONTENT_ROLE, GET_BY_TEXT, BARE_CONTAINER_ROLE, HAS_TEXT_FILTER, OUTCOME_TEXT, SUCCESS_NOTICE_TEXT, NOT_A_SUCCESS_NOTICE, ANNOUNCE_ROLE, MESSAGE_SURFACE, TEXT_CONTENT_MATCHER, VISIBILITY_MATCHER, ADDITIVE_AFFORDANCE, EXCLUDE_AFFORDANCE, EMPTY_STATE_TEXT, AUTH_START, AUTH_END, LOGIN_CALL_LINE, INBOX_START, INBOX_END, NEGATED_ASSERT, NEGATED_ASSERT_NOT, CONST_CHAIN_MAX_DEPTH, TYPED_INPUT, TITLE_LINE, FAILURE_STATUS_ASSERT, FAILED_LIST_ASSERT, ENDPOINT_DOWN, NAVIGATION_RESPONSE_VAR, DIRECT_REQUEST_VAR, CATCH_ALL_PATTERN, GUARD_HANDLER, ABSENCE_MATCHER, VALUE_ABSENCE, OPTION_ABSENCE, NOT_BEFORE_MATCHER, ERROR_TEXT_WORDS, TEXT_REGEX_ARG, NEGATED_TEXT, ASYNC_DESTRUCTURE_OPEN, REQUEST_WORD, ROLE_NAME_RE, INTERACT_VERB, ROLE_SIG_RE, TRANSIENT_CONTROL_ROLES, POLL_CALLBACK, CONSTANT_WORD, CONSTANT_GLUE_CHARS, WORD_CHAR, MATCHER_ARGS_MAX, MATCHER_OPEN, ENTERED_VALUE, PAGE_NAV, ENV_READ, ENTERED_ENV, HAVE_VALUE_ENV, IN_FLIGHT_TEXT, LOCATOR_VALUE_READ, LOCATOR_EXPR, ALWAYS_TRUE_ON_OBJECT, COUNT_AT_LEAST_ZERO, DEFINED_VALUE_READ, ALWAYS_DEFINED, SELF_COMPARE_MATCHER, IS_VISIBLE_TRUE, PAGE_VALUE_MATCHER, COUNT_ONE, FORM_CONTROL_LOCATOR, CONTROL_VALUE_MATCHER, COPY_CONTROL, COPIED_NOTICE, SEND_CONTROL, SEND_NOTICE, MARK_READ_CONTROL, APP_DATA_FIELD;
|
|
73949
|
+
var ERROR_BANNER, OUTCOME_ALWAYS, FORM_INPUT, ANY_CLICK, NAV_LOCATOR, URL_PROOF, POLL_OPEN, POLL_PAGE_URL, POLL_PAGE_URL_ONLY, POLL_CALLS_MAX, RELOAD, EXPECT_STMT, BLOCK_SCAFFOLD2, TEST_BLOCK_OPEN, LOCATOR_BINDING, EXPECT_OPEN, STATE_MATCHER, CHROME_LOCATOR, CONTENT_ROLE, GET_BY_TEXT, BARE_CONTAINER_ROLE, HAS_TEXT_FILTER, OUTCOME_TEXT, SUCCESS_NOTICE_TEXT, NOT_A_SUCCESS_NOTICE, ANNOUNCE_ROLE, MESSAGE_SURFACE, TEXT_CONTENT_MATCHER, VISIBILITY_MATCHER, ADDITIVE_AFFORDANCE, EXCLUDE_AFFORDANCE, EMPTY_STATE_TEXT, AUTH_START, AUTH_END, LOGIN_CALL_LINE, INBOX_START, INBOX_END, NEGATED_ASSERT, NEGATED_ASSERT_NOT, CONST_CHAIN_MAX_DEPTH, TYPED_INPUT, TITLE_LINE, FAILURE_STATUS_ASSERT, FAILED_LIST_ASSERT, ENDPOINT_DOWN, NAVIGATION_RESPONSE_VAR, DIRECT_REQUEST_VAR, CATCH_ALL_PATTERN, GUARD_HANDLER, ABSENCE_MATCHER, VALUE_ABSENCE, OPTION_ABSENCE, NOT_BEFORE_MATCHER, ERROR_TEXT_WORDS, TEXT_REGEX_ARG, SCOPING_STEP, NEGATED_TEXT, ASYNC_DESTRUCTURE_OPEN, REQUEST_WORD, ROLE_NAME_RE, INTERACT_VERB, ROLE_SIG_RE, TRANSIENT_CONTROL_ROLES, POLL_CALLBACK, CONSTANT_WORD, CONSTANT_GLUE_CHARS, WORD_CHAR, MATCHER_ARGS_MAX, MATCHER_OPEN, ENTERED_VALUE, PAGE_NAV, ENV_READ, ENTERED_ENV, HAVE_VALUE_ENV, ACCOUNT_KEYS, ACCOUNT_ENV, ACCOUNT_CONST, IN_FLIGHT_TEXT, LOCATOR_VALUE_READ, LOCATOR_EXPR, ALWAYS_TRUE_ON_OBJECT, COUNT_AT_LEAST_ZERO, DEFINED_VALUE_READ, ALWAYS_DEFINED, SELF_COMPARE_MATCHER, IS_VISIBLE_TRUE, PAGE_VALUE_MATCHER, COUNT_ONE, URL_CHECK_ARG, PLAIN_PAGE_PATH, FORM_CONTROL_LOCATOR, CONTROL_VALUE_MATCHER, ACCOUNT_EMAIL_ENV, ENV_PASSWORD_ENTRY, ACCOUNT_CONTROL_ROLE, ASSERT_OR_WAIT, ACTS, actLinesOf, CLOSERS_ONLY, TEST_BODY_OPEN, COPY_CONTROL, COPIED_NOTICE, SEND_CONTROL, SEND_NOTICE, MARK_READ_CONTROL, APP_DATA_FIELD, COMMIT_CONTROL, NOT_COMMIT_CONTROL, DESTRUCTIVE_CONTROL, ENTER_PRESS, CONTROL_LABEL, isCommitClick, isDestructiveClick, TEARDOWN_OPEN;
|
|
73620
73950
|
var init_assertion_strength = __esm({
|
|
73621
73951
|
"../shared/dist/assertion-strength.js"() {
|
|
73622
73952
|
"use strict";
|
|
@@ -73625,6 +73955,7 @@ var init_assertion_strength = __esm({
|
|
|
73625
73955
|
init_assertion_proof();
|
|
73626
73956
|
init_auth_handoff_coverage();
|
|
73627
73957
|
init_expect_call();
|
|
73958
|
+
init_auth_plan();
|
|
73628
73959
|
ERROR_BANNER = /(client-side exception|application error|something (?:went wrong|broke)|unhandled (?:exception|error|rejection)|runtime error|error boundary|an unexpected error|internal server error|\b5\d\d\s+(?:internal\s+)?server error|stack trace|chunkloaderror|hydration failed|maximum update depth exceeded)/i;
|
|
73629
73960
|
OUTCOME_ALWAYS = [
|
|
73630
73961
|
/\.toHaveCount\s*\(/,
|
|
@@ -73641,7 +73972,7 @@ var init_assertion_strength = __esm({
|
|
|
73641
73972
|
// form field value
|
|
73642
73973
|
/\.toMatch\s*\(/,
|
|
73643
73974
|
// string/regex content match (e.g. textContent() vs /[2-9] selected/)
|
|
73644
|
-
|
|
73975
|
+
/\.(?<!\.not\s*\.)\s*toBeDisabled\s*\(/,
|
|
73645
73976
|
// a control became DISABLED — a gating/validation outcome (not.toBeDisabled is the toBeEnabled twin)
|
|
73646
73977
|
/\.not\.toBeVisible\s*\(/,
|
|
73647
73978
|
/\.toBeHidden\s*\(/
|
|
@@ -73650,12 +73981,16 @@ var init_assertion_strength = __esm({
|
|
|
73650
73981
|
FORM_INPUT = /\.(fill|selectOption|setInputFiles|check|uncheck|setChecked|pressSequentially)\s*\(|keyboard\.type\s*\(/;
|
|
73651
73982
|
ANY_CLICK = /\.click\s*\(/;
|
|
73652
73983
|
NAV_LOCATOR = /getByRole\s*\(\s*['"`](?:link|menuitem)['"`]/i;
|
|
73653
|
-
URL_PROOF = /\.toHaveURL\s*\(|\.waitForURL\s*\(|\bexpect\s*\(\s*(?:await\s+)?page\s*\.\s*url\s*\(\s*\)\s*\)
|
|
73984
|
+
URL_PROOF = /\.toHaveURL\s*\(|\.waitForURL\s*\(|\bexpect\s*\(\s*(?:await\s+)?page\s*\.\s*url\s*\(\s*\)\s*\)\s*\.\s*(?:toBe|toEqual|toStrictEqual|toMatch|toContain)\s*\(/;
|
|
73985
|
+
POLL_OPEN = /\bexpect\s*\.\s*poll\s*\(/g;
|
|
73986
|
+
POLL_PAGE_URL = /^page\s*\.\s*url\s*\(\s*\)/;
|
|
73987
|
+
POLL_PAGE_URL_ONLY = /^page\s*\.\s*url\s*\(\s*\)$/;
|
|
73988
|
+
POLL_CALLS_MAX = 8;
|
|
73654
73989
|
RELOAD = /\.reload\s*\(/;
|
|
73655
73990
|
EXPECT_STMT = /\bexpect\s*[.(]/;
|
|
73656
73991
|
BLOCK_SCAFFOLD2 = /=>|\b(?:test|describe|it|beforeEach|afterEach|beforeAll|afterAll|function)\b/;
|
|
73657
73992
|
TEST_BLOCK_OPEN = /^(?:test|it)(?:\.(?:only|skip|fixme|slow|serial|describe\.serial))?\s*\(|^(?:test\.)?(?:beforeEach|beforeAll)\s*\(/;
|
|
73658
|
-
LOCATOR_BINDING = /^(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s
|
|
73993
|
+
LOCATOR_BINDING = /^(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=(?:\s*(?!\s)|\s*(?=\s(?:getByRole|getByText|getByLabel|getByPlaceholder|getByTestId|getByAltText|getByTitle|locator)\s*\())(.+?(?:getByRole|getByText|getByLabel|getByPlaceholder|getByTestId|getByAltText|getByTitle|locator)\s*\(.+)$/;
|
|
73659
73994
|
EXPECT_OPEN = /\bexpect(?:\.soft)?\s*\(/;
|
|
73660
73995
|
STATE_MATCHER = /\.(toBeChecked|toBeVisible|toHaveValue|toBeDisabled|toBeEnabled)\s*\(/;
|
|
73661
73996
|
CHROME_LOCATOR = /getByRole\s*\(\s*['"`](?:heading|navigation|banner|main|contentinfo|complementary|region|search|tablist|tab|button|link|menuitem|textbox|searchbox|combobox|spinbutton)['"`]/i;
|
|
@@ -73675,7 +74010,7 @@ var init_assertion_strength = __esm({
|
|
|
73675
74010
|
EMPTY_STATE_TEXT = /\bno\b[\s\S]{0,24}?\b(yet|found|results?|items?|favou?rites?|entries|records?|matches|posts?|comments?)\b|nothing (?:here|yet|to show|found)|\bempty\b|\(\s*0\s*\)|\b0\s+(?:favou?rites?|results?|items?|entries|records?|matches|posts?|comments?)\b/i;
|
|
73676
74011
|
AUTH_START = /^\s*\/\/\s*>>>\s*VALIDATE_QA_AUTH/;
|
|
73677
74012
|
AUTH_END = /^\s*\/\/\s*<<<\s*VALIDATE_QA_AUTH/;
|
|
73678
|
-
LOGIN_CALL_LINE = /^\s*await\s+__vqaLogin\s*\(\s*page\s*\)\s
|
|
74013
|
+
LOGIN_CALL_LINE = /^\s*await\s+__vqaLogin\s*\(\s*page\s*\)\s*(?:;\s*)?$/;
|
|
73679
74014
|
INBOX_START = /^\s*\/\/\s*>>>\s*VALIDATE_QA_INBOX/;
|
|
73680
74015
|
INBOX_END = /^\s*\/\/\s*<<<\s*VALIDATE_QA_INBOX/;
|
|
73681
74016
|
NEGATED_ASSERT = /\.not\s*\.\s*to[A-Z]\w*|\.toBeHidden\s*\(/;
|
|
@@ -73685,7 +74020,7 @@ var init_assertion_strength = __esm({
|
|
|
73685
74020
|
TITLE_LINE = /^\s*(?:test|describe)(?:\.\w+)?\s*\(/;
|
|
73686
74021
|
FAILURE_STATUS_ASSERT = [
|
|
73687
74022
|
/\.status\s*\(\s*\)[^;]{0,200}\.(?:toBeGreaterThanOrEqual|toBeGreaterThan)\s*\(\s*(?:399|[45]\d\d)\b/,
|
|
73688
|
-
/\bexpect\s*\(\s*[^;]{0,200}\bstatus\s*(?:\(\s*\))
|
|
74023
|
+
/\bexpect\s*\(\s*[^;]{0,200}\bstatus\s*(?:\(\s*\)\s*)?>=?\s*(?:399|[45]\d\d)\b[^;]{0,200}\)\s*\.\s*(?:toBe\s*\(\s*true|toBeTruthy)/,
|
|
73689
74024
|
/\bexpect\s*\([^;]{0,200}\.ok\s*\(\s*\)\s*\)\s*\.\s*(?:toBe\s*\(\s*false\s*\)|toBeFalsy\s*\()/
|
|
73690
74025
|
];
|
|
73691
74026
|
FAILED_LIST_ASSERT = /\bexpect\s*\(\s*[^;]{0,200}(?:fail|abort|error)\w{0,40}(?:\.length)?\s*\)\s*\.\s*(?:toBeGreaterThan\s*\(\s*0|toHaveLength\s*\(\s*[1-9]|not\s*\.\s*toHaveLength\s*\(\s*0|not\s*\.\s*toEqual\s*\(\s*\[\s*\])/i;
|
|
@@ -73700,6 +74035,7 @@ var init_assertion_strength = __esm({
|
|
|
73700
74035
|
NOT_BEFORE_MATCHER = /\.not\s*\.\s*(?=to[A-Z])/g;
|
|
73701
74036
|
ERROR_TEXT_WORDS = /error|fail|wrong|try again|unable|could ?n.?t|can.?t|problem|invalid|unavailable/i;
|
|
73702
74037
|
TEXT_REGEX_ARG = /(?:getByText|hasText|getByRole\([^)]{0,200}name)\s*[:(]\s*(\/(?:\\.|[^/\\\n])+\/[a-z]*)/;
|
|
74038
|
+
SCOPING_STEP = /(?:\s*\.\s*(?:first|last|nth)\s*\([^()]*\))*\s*\.\s*(?:getBy[A-Z]\w*|locator|filter)\s*\(/y;
|
|
73703
74039
|
NEGATED_TEXT = /\.not\s*\.\s*(?:toHaveText|toContainText)\s*\(\s*(?:['"`]([^'"`]*)['"`]|\/((?:\\.|[^/\\\n])+)\/)?/;
|
|
73704
74040
|
ASYNC_DESTRUCTURE_OPEN = /async\s*\(\s*\{/g;
|
|
73705
74041
|
REQUEST_WORD = /\brequest\b/;
|
|
@@ -73726,6 +74062,9 @@ var init_assertion_strength = __esm({
|
|
|
73726
74062
|
ENV_READ = String.raw`process\.env(?:(?:\?\.|\.)([A-Za-z_]\w*)|(?:\?\.)?\[\s*['"]([A-Za-z_]\w*)['"]\s*\])`;
|
|
73727
74063
|
ENTERED_ENV = new RegExp(String.raw`\.(?:fill|pressSequentially)\s*\(\s*${ENV_READ}|keyboard\.type\s*\(\s*${ENV_READ}`, "g");
|
|
73728
74064
|
HAVE_VALUE_ENV = new RegExp(String.raw`\.toHaveValue\s*\(\s*${ENV_READ}`);
|
|
74065
|
+
ACCOUNT_KEYS = TEST_USER_ENV_KEYS.join("|");
|
|
74066
|
+
ACCOUNT_ENV = `process\\.env(?:\\??\\.(?:${ACCOUNT_KEYS})\\b|(?:\\?\\.)?\\[\\s*['"\`](?:${ACCOUNT_KEYS})['"\`]\\s*\\])`;
|
|
74067
|
+
ACCOUNT_CONST = new RegExp(`\\b(?:const|let|var)\\s+([A-Za-z_$][\\w$]*)\\s*(?::\\s*string\\s*)?=\\s*${ACCOUNT_ENV}`, "g");
|
|
73729
74068
|
IN_FLIGHT_TEXT = /^(?:(?:sending|saving|loading|searching|checking|processing|submitting|preparing|updating|please wait|working|one moment)\b[^.]{0,40}\.{2,3}|\.{3}|…)$/i;
|
|
73730
74069
|
LOCATOR_VALUE_READ = /\.(?:count|textContent|innerText|innerHTML|inputValue|getAttribute|isVisible|isHidden|isChecked|isEnabled|isDisabled|isEditable|allTextContents|allInnerTexts|evaluate|evaluateAll|boundingBox|all)\s*\(/;
|
|
73731
74070
|
LOCATOR_EXPR = /^(?:this\.)?page\s*\.\s*(?:getBy\w+|locator)\s*\(/;
|
|
@@ -73737,20 +74076,47 @@ var init_assertion_strength = __esm({
|
|
|
73737
74076
|
IS_VISIBLE_TRUE = /^\)*\s*\.\s*(?:toBe\s*\(\s*true\s*\)|toBeTruthy\s*\(\s*\))/;
|
|
73738
74077
|
PAGE_VALUE_MATCHER = /^\)\s*\.\s*(?:toBe|toEqual|toStrictEqual|toMatch|toContain)\s*\(/;
|
|
73739
74078
|
COUNT_ONE = /\.\s*toHaveCount\s*\(\s*1\s*\)/;
|
|
74079
|
+
URL_CHECK_ARG = /\bpage\s*\.\s*waitForURL\s*\(\s*([^,)]+)|\bexpect(?:\s*\.\s*soft)?\s*\(\s*page\s*\)\s*\.\s*toHaveURL\s*\(\s*([^,)]+)/;
|
|
74080
|
+
PLAIN_PAGE_PATH = /^\/[\w\-./~%]*(?:[?#][^\s]*)?$/;
|
|
73740
74081
|
FORM_CONTROL_LOCATOR = /getByRole\s*\(\s*['"`](?:combobox|switch|checkbox|radio|textbox|searchbox|spinbutton|slider)['"`]|getByLabel\s*\(|getByPlaceholder\s*\(/;
|
|
73741
74082
|
CONTROL_VALUE_MATCHER = /\.(?:toHaveValue|toHaveText|toContainText)\s*\(|\.toHaveAttribute\s*\(\s*['"`]aria-checked['"`]/;
|
|
74083
|
+
ACCOUNT_EMAIL_ENV = /^process\.env(?:(?:\?\.|\.)TEST_USER_EMAIL\b|(?:\?\.)?\[\s*['"]TEST_USER_EMAIL['"]\s*\])/;
|
|
74084
|
+
ENV_PASSWORD_ENTRY = /\.(?:fill|pressSequentially)\s*\(\s*process\.env(?:(?:\?\.|\.)TEST_USER_PASSWORD\b|(?:\?\.)?\[\s*['"]TEST_USER_PASSWORD['"]\s*\])/;
|
|
74085
|
+
ACCOUNT_CONTROL_ROLE = /getByRole\s*\(\s*['"`](?:button|link|menuitem)['"`]\s*,\s*\{/;
|
|
74086
|
+
ASSERT_OR_WAIT = /^(?:await\s+)?(?:expect(?:\.soft|\.poll)?\s*\(|[\w$]+(?:\.[\w$]+)*\.waitFor[A-Za-z]*\s*\()/;
|
|
74087
|
+
ACTS = /\.(?:click|dblclick|tap|press|pressSequentially|fill|clear|type|check|uncheck|setChecked|selectOption|setInputFiles|dispatchEvent|hover|focus|dragTo|goto|reload|goBack|goForward|evaluate|evaluateHandle)\s*\(|\b(?:keyboard|mouse|touchscreen)\s*\.|\.toPass\s*\(/;
|
|
74088
|
+
actLinesOf = /* @__PURE__ */ new WeakMap();
|
|
74089
|
+
CLOSERS_ONLY = /^[})\];,\s]+$/;
|
|
74090
|
+
TEST_BODY_OPEN = /^(?:test|it)(?:\.(?:only|skip|fixme|slow))?\s*\(/;
|
|
73742
74091
|
COPY_CONTROL = /\bcopy\b/i;
|
|
73743
74092
|
COPIED_NOTICE = /\bcopied\b/i;
|
|
73744
74093
|
SEND_CONTROL = /\b(send|submit|subscribe|sign up for|contact|feedback|join (the )?waitlist)\b/i;
|
|
73745
74094
|
SEND_NOTICE = /\b(thank|thanks|sent|subscribed|received|in touch)\b/i;
|
|
73746
74095
|
MARK_READ_CONTROL = /\bmark(?:ed)? as read\b|\bmark all(?: as)? read\b/i;
|
|
73747
74096
|
APP_DATA_FIELD = /\b(title|name of|amount|price|quantity|sku|status|due|assignee|project|ticket|invoice|order)\b/i;
|
|
74097
|
+
COMMIT_CONTROL = /\b(?:save|submit|update|apply|add|create|post|send|publish)\b|\bconfirm\s+changes\b/i;
|
|
74098
|
+
NOT_COMMIT_CONTROL = /\b(?:delete|remove|cancel|close|dismiss|discard|back|sign\s*out|log\s*out|logout|done|ok|got\s+it|export|download)\b/i;
|
|
74099
|
+
DESTRUCTIVE_CONTROL = /\b(?:delete|remove|discard)\b/i;
|
|
74100
|
+
ENTER_PRESS = /\.press\s*\(\s*['"`]Enter['"`]/;
|
|
74101
|
+
CONTROL_LABEL = /(?:name\s*:\s*|getBy(?:Text|Label|Title|TestId)\s*\(\s*|has-text\(\s*)(?:(['"`])((?:(?!\1).)*)\1|\/((?:\\.|[^/\\])+)\/)/g;
|
|
74102
|
+
isCommitClick = (stmt) => {
|
|
74103
|
+
const label = clickLabel(stmt);
|
|
74104
|
+
return label !== null && COMMIT_CONTROL.test(label) && !NOT_COMMIT_CONTROL.test(label) && !EXCLUDE_AFFORDANCE.test(label);
|
|
74105
|
+
};
|
|
74106
|
+
isDestructiveClick = (stmt) => {
|
|
74107
|
+
const label = clickLabel(stmt);
|
|
74108
|
+
return label !== null && DESTRUCTIVE_CONTROL.test(label);
|
|
74109
|
+
};
|
|
74110
|
+
TEARDOWN_OPEN = /\bfinally\s*\{|^(?:test\.)?(?:after|before)(?:Each|All)\s*\(/;
|
|
73748
74111
|
}
|
|
73749
74112
|
});
|
|
73750
74113
|
|
|
73751
74114
|
// ../shared/dist/run-classification.js
|
|
73752
|
-
function
|
|
73753
|
-
|
|
74115
|
+
function isCancelledReason(error2) {
|
|
74116
|
+
if (typeof error2 !== "string")
|
|
74117
|
+
return false;
|
|
74118
|
+
const text = error2.trim();
|
|
74119
|
+
return CANCELLED_REASON_PREFIXES.some((prefix) => text.startsWith(prefix));
|
|
73754
74120
|
}
|
|
73755
74121
|
function isHeldHealRun(run) {
|
|
73756
74122
|
return run?.status === "PASSED" && typeof run.error === "string" && run.error.startsWith(HEAL_PATCH_HELD_RUN_ERROR_PREFIX);
|
|
@@ -73783,7 +74149,7 @@ function pickLatestHealthRun(runs) {
|
|
|
73783
74149
|
for (const run of runs) {
|
|
73784
74150
|
if (run.mode === "auth-setup")
|
|
73785
74151
|
continue;
|
|
73786
|
-
if (run.status === "ERROR" &&
|
|
74152
|
+
if (run.status === "ERROR" && isCancelledReason(run.error))
|
|
73787
74153
|
continue;
|
|
73788
74154
|
if (isHeldHealRun(run))
|
|
73789
74155
|
continue;
|
|
@@ -73801,6 +74167,15 @@ function pickDisplayRun(runs) {
|
|
|
73801
74167
|
return latest;
|
|
73802
74168
|
return pickLatestHealthRun(runs) ?? latest;
|
|
73803
74169
|
}
|
|
74170
|
+
function featureRowRunStatus(runs) {
|
|
74171
|
+
const latest = runs.find((run) => run.mode !== "auth-setup");
|
|
74172
|
+
if (!latest)
|
|
74173
|
+
return null;
|
|
74174
|
+
const decisive = pickLatestHealthRun(runs.filter((run) => !isEnvironmentalError(run)));
|
|
74175
|
+
if (decisive)
|
|
74176
|
+
return decisive.status;
|
|
74177
|
+
return latest.status === "PENDING" || latest.status === "RUNNING" ? latest.status : null;
|
|
74178
|
+
}
|
|
73804
74179
|
function isEnvironmentalError(run) {
|
|
73805
74180
|
if (!run)
|
|
73806
74181
|
return false;
|
|
@@ -73832,7 +74207,7 @@ function classifyErrorMessage(error2) {
|
|
|
73832
74207
|
return "config_issue";
|
|
73833
74208
|
if (EMAIL_NOT_RECEIVED_PREFIXES.some((prefix) => normalized.startsWith(prefix)))
|
|
73834
74209
|
return "email_not_received";
|
|
73835
|
-
if (
|
|
74210
|
+
if (isCancelledReason(error2))
|
|
73836
74211
|
return "cancelled";
|
|
73837
74212
|
if (isRetriedRunInterruption(error2))
|
|
73838
74213
|
return "interrupted";
|
|
@@ -73867,7 +74242,7 @@ function heldHealRunWhere() {
|
|
|
73867
74242
|
function excludeCancelledRunsWhere() {
|
|
73868
74243
|
return {
|
|
73869
74244
|
NOT: [
|
|
73870
|
-
{ status: "ERROR", error: { not: null, startsWith:
|
|
74245
|
+
{ status: "ERROR", OR: CANCELLED_REASON_PREFIXES.map((prefix) => ({ error: { not: null, startsWith: prefix } })) },
|
|
73871
74246
|
heldHealRunWhere()
|
|
73872
74247
|
]
|
|
73873
74248
|
};
|
|
@@ -73945,11 +74320,25 @@ function reportedBugWhere() {
|
|
|
73945
74320
|
function bugReviewStatus(status) {
|
|
73946
74321
|
return status === "QUARANTINED" ? "confirmed" : "needs-review";
|
|
73947
74322
|
}
|
|
73948
|
-
var USER_CANCELLED_RUN_ERROR, HEAL_PATCH_HELD_RUN_ERROR_PREFIX, RUNNER_INTERRUPT_ERROR_PREFIX, SERVER_INTERRUPT_ERROR_PREFIX, RUN_LOST_ERROR_PREFIX, RUN_INTERRUPTED_ERROR_PREFIXES, RUN_INTERRUPTION_RETRIED_MARKER, RUN_INTERRUPTION_NOT_RETRIED_MARKERS, BUG_ASSERTION_TAG, UNEXPECTED_PASS_ERROR_PREFIX, BUG_TEST_BROKEN_ERROR_PREFIX, BUG_TEST_BROKEN_REASON, TEST_DID_NOT_RUN_ERROR, EMAIL_NOT_RECEIVED_PREFIXES, ENVIRONMENTAL_ERROR_PREFIXES, ENVIRONMENTAL_ERROR_STORED_PREFIXES, BUG_SURFACE_SUPPRESSING_TAGS, QUARANTINE_CLOSE_TAGS, BUG_CANDIDATE_TAG, BUG_TEST_BROKEN_TAG;
|
|
74323
|
+
var USER_CANCELLED_RUN_ERROR, PLATFORM_SUPPORT_CANCELLED_RUN_ERROR, PLATFORM_ADMIN_CANCELLED_RUN_ERROR, ADMIN_FORCE_CANCELLED_RUN_ERROR, CHAIN_CANCELLED_RUN_ERROR, RETRY_HELD_RUN_ERROR, CANCELLED_REASON_PREFIXES, isUserCancelledError, HEAL_PATCH_HELD_RUN_ERROR_PREFIX, RUNNER_INTERRUPT_ERROR_PREFIX, SERVER_INTERRUPT_ERROR_PREFIX, RUN_LOST_ERROR_PREFIX, RUN_INTERRUPTED_ERROR_PREFIXES, RUN_INTERRUPTION_RETRIED_MARKER, RUN_INTERRUPTION_NOT_RETRIED_MARKERS, BUG_ASSERTION_TAG, UNEXPECTED_PASS_ERROR_PREFIX, BUG_TEST_BROKEN_ERROR_PREFIX, BUG_TEST_BROKEN_REASON, TEST_DID_NOT_RUN_ERROR, EMAIL_NOT_RECEIVED_PREFIXES, ENVIRONMENTAL_ERROR_PREFIXES, ENVIRONMENTAL_ERROR_STORED_PREFIXES, FEATURE_ROW_RUN_WINDOW, BUG_SURFACE_SUPPRESSING_TAGS, QUARANTINE_CLOSE_TAGS, BUG_CANDIDATE_TAG, BUG_TEST_BROKEN_TAG;
|
|
73949
74324
|
var init_run_classification = __esm({
|
|
73950
74325
|
"../shared/dist/run-classification.js"() {
|
|
73951
74326
|
"use strict";
|
|
73952
74327
|
USER_CANCELLED_RUN_ERROR = "Cancelled by user";
|
|
74328
|
+
PLATFORM_SUPPORT_CANCELLED_RUN_ERROR = "Cancelled by platform support";
|
|
74329
|
+
PLATFORM_ADMIN_CANCELLED_RUN_ERROR = "Cancelled by platform admin";
|
|
74330
|
+
ADMIN_FORCE_CANCELLED_RUN_ERROR = "Admin force-cancelled all active runs";
|
|
74331
|
+
CHAIN_CANCELLED_RUN_ERROR = "Cancelled: parent run cancelled";
|
|
74332
|
+
RETRY_HELD_RUN_ERROR = "Cancelled: auto generation paused";
|
|
74333
|
+
CANCELLED_REASON_PREFIXES = [
|
|
74334
|
+
USER_CANCELLED_RUN_ERROR,
|
|
74335
|
+
PLATFORM_SUPPORT_CANCELLED_RUN_ERROR,
|
|
74336
|
+
PLATFORM_ADMIN_CANCELLED_RUN_ERROR,
|
|
74337
|
+
ADMIN_FORCE_CANCELLED_RUN_ERROR,
|
|
74338
|
+
CHAIN_CANCELLED_RUN_ERROR,
|
|
74339
|
+
RETRY_HELD_RUN_ERROR
|
|
74340
|
+
];
|
|
74341
|
+
isUserCancelledError = isCancelledReason;
|
|
73953
74342
|
HEAL_PATCH_HELD_RUN_ERROR_PREFIX = "Heal patch held";
|
|
73954
74343
|
RUNNER_INTERRUPT_ERROR_PREFIX = "Runner shutting down";
|
|
73955
74344
|
SERVER_INTERRUPT_ERROR_PREFIX = "Run interrupted by server restart";
|
|
@@ -73978,9 +74367,10 @@ var init_run_classification = __esm({
|
|
|
73978
74367
|
];
|
|
73979
74368
|
ENVIRONMENTAL_ERROR_STORED_PREFIXES = [
|
|
73980
74369
|
...ENVIRONMENTAL_ERROR_PREFIXES.flatMap((prefix) => [prefix, `Error: ${prefix}`]),
|
|
73981
|
-
// Written by the
|
|
73982
|
-
|
|
74370
|
+
// Written by the cancels as is, with no prefix wrapper.
|
|
74371
|
+
...CANCELLED_REASON_PREFIXES
|
|
73983
74372
|
];
|
|
74373
|
+
FEATURE_ROW_RUN_WINDOW = 10;
|
|
73984
74374
|
BUG_SURFACE_SUPPRESSING_TAGS = ["@rate-limit-blocked", "@quota-exceeded", "@auth-lost"];
|
|
73985
74375
|
QUARANTINE_CLOSE_TAGS = [
|
|
73986
74376
|
"@bug-found",
|
|
@@ -76320,270 +76710,96 @@ function hostOf(url) {
|
|
|
76320
76710
|
return null;
|
|
76321
76711
|
}
|
|
76322
76712
|
}
|
|
76323
|
-
function projectAppHosts(baseUrls) {
|
|
76324
|
-
const hosts = baseUrls.map(hostOf).filter((host) => !!host);
|
|
76325
|
-
return [...new Set(hosts)];
|
|
76326
|
-
}
|
|
76327
|
-
var SHARED_AUTH_SUFFIXES;
|
|
76328
|
-
var init_google_app_site = __esm({
|
|
76329
|
-
"../shared/dist/google-app-site.js"() {
|
|
76330
|
-
"use strict";
|
|
76331
|
-
init_origin_domain();
|
|
76332
|
-
SHARED_AUTH_SUFFIXES = [
|
|
76333
|
-
"auth0.com",
|
|
76334
|
-
"clerk.accounts.dev",
|
|
76335
|
-
"supabase.co",
|
|
76336
|
-
"firebaseapp.com",
|
|
76337
|
-
"web.app",
|
|
76338
|
-
"amazoncognito.com",
|
|
76339
|
-
"stytch.com",
|
|
76340
|
-
"kinde.com"
|
|
76341
|
-
];
|
|
76342
|
-
}
|
|
76343
|
-
});
|
|
76344
|
-
|
|
76345
|
-
// ../shared/dist/google-broker-lines.js
|
|
76346
|
-
function googleBrokerUnavailableLine(lines, testError) {
|
|
76347
|
-
if (!TIMEOUT_ERROR.test(testError ?? ""))
|
|
76348
|
-
return null;
|
|
76349
|
-
let last = null;
|
|
76350
|
-
for (const raw of lines ?? []) {
|
|
76351
|
-
for (const line of String(raw).split("\n")) {
|
|
76352
|
-
const text = line.trim();
|
|
76353
|
-
if (GOOGLE_BROKER_UNAVAILABLE.test(text) || GOOGLE_BROKER_ASKED.test(text))
|
|
76354
|
-
last = text;
|
|
76355
|
-
else if (GOOGLE_SIGNED_IN.test(text) || text.startsWith("[google-sign-in] "))
|
|
76356
|
-
last = null;
|
|
76357
|
-
}
|
|
76358
|
-
}
|
|
76359
|
-
return last;
|
|
76360
|
-
}
|
|
76361
|
-
function stepConsoleLines(result) {
|
|
76362
|
-
const steps = Array.isArray(result) ? result : result && typeof result === "object" && Array.isArray(result.stepResults) ? result.stepResults : [];
|
|
76363
|
-
return steps.flatMap((step) => {
|
|
76364
|
-
const logs = step && typeof step === "object" ? step.consoleLogs : null;
|
|
76365
|
-
return Array.isArray(logs) ? logs.filter((line) => typeof line === "string") : [];
|
|
76366
|
-
});
|
|
76367
|
-
}
|
|
76368
|
-
var GOOGLE_BROKER_UNAVAILABLE, GOOGLE_BROKER_ASKED, GOOGLE_SIGNED_IN, TIMEOUT_ERROR;
|
|
76369
|
-
var init_google_broker_lines = __esm({
|
|
76370
|
-
"../shared/dist/google-broker-lines.js"() {
|
|
76371
|
-
"use strict";
|
|
76372
|
-
GOOGLE_BROKER_UNAVAILABLE = /^\[google-sign-in\] (?:(?:busy|rate_limited|timeout|offline): |failed: Google sign-in service (?:answered 50[234]\b|unreachable))/;
|
|
76373
|
-
GOOGLE_BROKER_ASKED = /^\[google-sign-in\] the app started Google sign-in; asking the broker/;
|
|
76374
|
-
GOOGLE_SIGNED_IN = /^\[google-sign-in\] returned to the app with Google sign-in/;
|
|
76375
|
-
TIMEOUT_ERROR = /Test timeout of \d+ms exceeded|TimeoutError|Timeout:? \d+ ?ms/i;
|
|
76376
|
-
}
|
|
76377
|
-
});
|
|
76378
|
-
|
|
76379
|
-
// ../shared/dist/admin-view-return-to.js
|
|
76380
|
-
function sanitizeAdminViewReturnTo(value) {
|
|
76381
|
-
if (typeof value !== "string")
|
|
76382
|
-
return ADMIN_VIEW_DEFAULT_RETURN_TO;
|
|
76383
|
-
const trimmed = value.trim();
|
|
76384
|
-
if (!trimmed || trimmed.length > MAX_RETURN_TO_LENGTH)
|
|
76385
|
-
return ADMIN_VIEW_DEFAULT_RETURN_TO;
|
|
76386
|
-
if (!trimmed.startsWith("/") || trimmed.startsWith("//"))
|
|
76387
|
-
return ADMIN_VIEW_DEFAULT_RETURN_TO;
|
|
76388
|
-
if (trimmed.includes("\\") || /[\s\u0000-\u001f\u007f]/.test(trimmed))
|
|
76389
|
-
return ADMIN_VIEW_DEFAULT_RETURN_TO;
|
|
76390
|
-
let url;
|
|
76391
|
-
try {
|
|
76392
|
-
url = new URL(trimmed, PLACEHOLDER_ORIGIN);
|
|
76393
|
-
} catch {
|
|
76394
|
-
return ADMIN_VIEW_DEFAULT_RETURN_TO;
|
|
76395
|
-
}
|
|
76396
|
-
if (url.origin !== PLACEHOLDER_ORIGIN)
|
|
76397
|
-
return ADMIN_VIEW_DEFAULT_RETURN_TO;
|
|
76398
|
-
if (BLOCKED_PATH_RE.test(url.pathname))
|
|
76399
|
-
return ADMIN_VIEW_DEFAULT_RETURN_TO;
|
|
76400
|
-
const out = `${url.pathname}${url.search}${url.hash}`;
|
|
76401
|
-
if (out.startsWith("//") || out.includes("\\"))
|
|
76402
|
-
return ADMIN_VIEW_DEFAULT_RETURN_TO;
|
|
76403
|
-
return out;
|
|
76404
|
-
}
|
|
76405
|
-
var ADMIN_VIEW_DEFAULT_RETURN_TO, MAX_RETURN_TO_LENGTH, PLACEHOLDER_ORIGIN, BLOCKED_PATH_RE;
|
|
76406
|
-
var init_admin_view_return_to = __esm({
|
|
76407
|
-
"../shared/dist/admin-view-return-to.js"() {
|
|
76408
|
-
"use strict";
|
|
76409
|
-
ADMIN_VIEW_DEFAULT_RETURN_TO = "/sessions";
|
|
76410
|
-
MAX_RETURN_TO_LENGTH = 2048;
|
|
76411
|
-
PLACEHOLDER_ORIGIN = "https://admin-view.invalid";
|
|
76412
|
-
BLOCKED_PATH_RE = /^\/(?:login|admin-view)/i;
|
|
76413
|
-
}
|
|
76414
|
-
});
|
|
76415
|
-
|
|
76416
|
-
// ../shared/dist/auth-plan.js
|
|
76417
|
-
function hasInlineLoginSteps(playwrightCode) {
|
|
76418
|
-
if (!playwrightCode)
|
|
76419
|
-
return false;
|
|
76420
|
-
return /process\.env\.TEST_USER_EMAIL!?/.test(playwrightCode) && /process\.env\.TEST_USER_PASSWORD!?/.test(playwrightCode);
|
|
76421
|
-
}
|
|
76422
|
-
function hasGeneratedAuthGuard(playwrightCode) {
|
|
76423
|
-
if (!playwrightCode)
|
|
76424
|
-
return false;
|
|
76425
|
-
return /\/\/ >>> VALIDATE_QA_AUTH v(\d+)\b[\s\S]*?process\.env\.AUTH_FILE[\s\S]*?\/\/ <<< VALIDATE_QA_AUTH v\1\b/.test(playwrightCode);
|
|
76426
|
-
}
|
|
76427
|
-
function legacyNeedsCookieState(tags, code, sharedAuthInjectEnabled) {
|
|
76428
|
-
if (!sharedAuthInjectEnabled)
|
|
76429
|
-
return false;
|
|
76430
|
-
if (tags.includes("@auth"))
|
|
76431
|
-
return false;
|
|
76432
|
-
if (tags.includes("@api"))
|
|
76433
|
-
return true;
|
|
76434
|
-
if (!tags.includes("@needs-auth"))
|
|
76435
|
-
return false;
|
|
76436
|
-
if (sharedAuthInjectEnabled && tags.includes("@auth-guarded") && hasGeneratedAuthGuard(code))
|
|
76437
|
-
return true;
|
|
76438
|
-
const isGeneratedVariant = tags.includes("@edge") || tags.includes("@bug");
|
|
76439
|
-
const hasLegacyInlineLogin = tags.includes("@discovered") && !isGeneratedVariant && hasInlineLoginSteps(code);
|
|
76440
|
-
return !tags.includes("@inline-login") && !hasLegacyInlineLogin;
|
|
76441
|
-
}
|
|
76442
|
-
function codeReadsStoredCredentials(code) {
|
|
76443
|
-
if (!code)
|
|
76444
|
-
return false;
|
|
76445
|
-
if (/__vqaLogin\b/.test(code))
|
|
76446
|
-
return true;
|
|
76447
|
-
for (const m of code.matchAll(/TEST_[A-Z0-9_]+/g)) {
|
|
76448
|
-
if (/_(?:EMAIL|PASSWORD)/.test(m[0]))
|
|
76449
|
-
return true;
|
|
76450
|
-
}
|
|
76451
|
-
for (const m of code.matchAll(/process\.env\s*\[([^\]]*)\]?/g)) {
|
|
76452
|
-
if (!/^\s*(['"])[^'"`]*\1\s*$/.test(m[1]))
|
|
76453
|
-
return true;
|
|
76454
|
-
}
|
|
76455
|
-
return false;
|
|
76456
|
-
}
|
|
76457
|
-
function explicitAuthTypeTags(t) {
|
|
76458
|
-
const found = /* @__PURE__ */ new Set();
|
|
76459
|
-
for (const tag of t) {
|
|
76460
|
-
if (AUTH_TYPE_TAGS.includes(tag))
|
|
76461
|
-
found.add(tag);
|
|
76462
|
-
else if (Object.hasOwn(AUTH_TAG_ALIASES, tag))
|
|
76463
|
-
found.add(AUTH_TAG_ALIASES[tag]);
|
|
76464
|
-
}
|
|
76465
|
-
return [...found];
|
|
76466
|
-
}
|
|
76467
|
-
function invalidPlan(configurationError) {
|
|
76468
|
-
return {
|
|
76469
|
-
version: 1,
|
|
76470
|
-
source: "invalid",
|
|
76471
|
-
acquisition: "unsupported",
|
|
76472
|
-
presentation: "none",
|
|
76473
|
-
needsCookieState: false,
|
|
76474
|
-
needsStandingHeaders: false,
|
|
76475
|
-
standingHeadersMode: "none",
|
|
76476
|
-
needsLoginCreds: false,
|
|
76477
|
-
requiredEnvKeys: [],
|
|
76478
|
-
configurationError
|
|
76479
|
-
};
|
|
76480
|
-
}
|
|
76481
|
-
function explicitPlan(authTypeTag2, acquisition, presentation, opts) {
|
|
76482
|
-
return {
|
|
76483
|
-
version: 1,
|
|
76484
|
-
source: "explicit",
|
|
76485
|
-
authTypeTag: authTypeTag2,
|
|
76486
|
-
acquisition,
|
|
76487
|
-
presentation,
|
|
76488
|
-
needsCookieState: opts.cookie,
|
|
76489
|
-
needsStandingHeaders: opts.standingMode === "required",
|
|
76490
|
-
standingHeadersMode: opts.standingMode,
|
|
76491
|
-
needsLoginCreds: TEST_USER_ENV_KEYS.every((k) => opts.requiredEnvKeys.includes(k)),
|
|
76492
|
-
requiredEnvKeys: opts.requiredEnvKeys
|
|
76493
|
-
};
|
|
76494
|
-
}
|
|
76495
|
-
function deriveAuthPlan(tags, code, opts) {
|
|
76496
|
-
const t = Array.isArray(tags) ? tags : [];
|
|
76497
|
-
const sharedFlag = opts?.sharedAuthInjectEnabled ?? false;
|
|
76498
|
-
const isApi = t.includes("@api");
|
|
76499
|
-
const explicit = isApi ? explicitAuthTypeTags(t) : [];
|
|
76500
|
-
if (explicit.length > 0) {
|
|
76501
|
-
if (t.includes("@auth")) {
|
|
76502
|
-
return invalidPlan("@auth (self-login UI) cannot be combined with an explicit @api auth-type tag");
|
|
76503
|
-
}
|
|
76504
|
-
const loginCompose = explicit.filter((e) => e === AUTH_TAG_COOKIE_STATE || e === AUTH_TAG_LOGIN_COOKIE || e === AUTH_TAG_LOGIN_BEARER);
|
|
76505
|
-
if (explicit.length === 2 && explicit.includes(AUTH_TAG_STANDING) && loginCompose.length === 1) {
|
|
76506
|
-
const composedKeys = [...TEST_USER_ENV_KEYS, API_AUTH_HEADERS_ENV_KEY];
|
|
76507
|
-
switch (loginCompose[0]) {
|
|
76508
|
-
case AUTH_TAG_COOKIE_STATE:
|
|
76509
|
-
return explicitPlan(AUTH_TAG_COOKIE_STATE, "browser-bootstrap", "cookie", { cookie: sharedFlag, standingMode: "required", requiredEnvKeys: composedKeys });
|
|
76510
|
-
case AUTH_TAG_LOGIN_COOKIE:
|
|
76511
|
-
return explicitPlan(AUTH_TAG_LOGIN_COOKIE, "request-login", "cookie", { cookie: false, standingMode: "required", requiredEnvKeys: composedKeys });
|
|
76512
|
-
case AUTH_TAG_LOGIN_BEARER:
|
|
76513
|
-
return explicitPlan(AUTH_TAG_LOGIN_BEARER, "request-login", "bearer", { cookie: false, standingMode: "required", requiredEnvKeys: composedKeys });
|
|
76514
|
-
}
|
|
76515
|
-
}
|
|
76516
|
-
if (explicit.length > 1) {
|
|
76517
|
-
return invalidPlan(`conflicting auth-type tags: ${explicit.join(", ")}`);
|
|
76518
|
-
}
|
|
76519
|
-
switch (explicit[0]) {
|
|
76520
|
-
case AUTH_TAG_UNSUPPORTED:
|
|
76521
|
-
return {
|
|
76522
|
-
...invalidPlan("auth scheme not yet drivable (e.g. HMAC / mTLS / provider-replay) \u2014 needs manual configuration")
|
|
76523
|
-
};
|
|
76524
|
-
case AUTH_TAG_NONE:
|
|
76525
|
-
return explicitPlan(AUTH_TAG_NONE, "none", "none", { cookie: false, standingMode: "none", requiredEnvKeys: [] });
|
|
76526
|
-
case AUTH_TAG_STANDING:
|
|
76527
|
-
return explicitPlan(AUTH_TAG_STANDING, "standing-secret", "standing-header", { cookie: false, standingMode: "required", requiredEnvKeys: [API_AUTH_HEADERS_ENV_KEY] });
|
|
76528
|
-
case AUTH_TAG_LOGIN_BEARER:
|
|
76529
|
-
return explicitPlan(AUTH_TAG_LOGIN_BEARER, "request-login", "bearer", { cookie: false, standingMode: "none", requiredEnvKeys: [...TEST_USER_ENV_KEYS] });
|
|
76530
|
-
case AUTH_TAG_LOGIN_COOKIE:
|
|
76531
|
-
return explicitPlan(AUTH_TAG_LOGIN_COOKIE, "request-login", "cookie", { cookie: false, standingMode: "legacy-if-configured", requiredEnvKeys: [...TEST_USER_ENV_KEYS] });
|
|
76532
|
-
case AUTH_TAG_COOKIE_STATE:
|
|
76533
|
-
return explicitPlan(AUTH_TAG_COOKIE_STATE, "browser-bootstrap", "cookie", { cookie: sharedFlag, standingMode: "legacy-if-configured", requiredEnvKeys: [...TEST_USER_ENV_KEYS] });
|
|
76713
|
+
function projectAppHosts(baseUrls) {
|
|
76714
|
+
const hosts = baseUrls.map(hostOf).filter((host) => !!host);
|
|
76715
|
+
return [...new Set(hosts)];
|
|
76716
|
+
}
|
|
76717
|
+
var SHARED_AUTH_SUFFIXES;
|
|
76718
|
+
var init_google_app_site = __esm({
|
|
76719
|
+
"../shared/dist/google-app-site.js"() {
|
|
76720
|
+
"use strict";
|
|
76721
|
+
init_origin_domain();
|
|
76722
|
+
SHARED_AUTH_SUFFIXES = [
|
|
76723
|
+
"auth0.com",
|
|
76724
|
+
"clerk.accounts.dev",
|
|
76725
|
+
"supabase.co",
|
|
76726
|
+
"firebaseapp.com",
|
|
76727
|
+
"web.app",
|
|
76728
|
+
"amazoncognito.com",
|
|
76729
|
+
"stytch.com",
|
|
76730
|
+
"kinde.com"
|
|
76731
|
+
];
|
|
76732
|
+
}
|
|
76733
|
+
});
|
|
76734
|
+
|
|
76735
|
+
// ../shared/dist/google-broker-lines.js
|
|
76736
|
+
function googleBrokerUnavailableLine(lines, testError) {
|
|
76737
|
+
if (!TIMEOUT_ERROR.test(testError ?? ""))
|
|
76738
|
+
return null;
|
|
76739
|
+
let last = null;
|
|
76740
|
+
for (const raw of lines ?? []) {
|
|
76741
|
+
for (const line of String(raw).split("\n")) {
|
|
76742
|
+
const text = line.trim();
|
|
76743
|
+
if (GOOGLE_BROKER_UNAVAILABLE.test(text) || GOOGLE_BROKER_ASKED.test(text))
|
|
76744
|
+
last = text;
|
|
76745
|
+
else if (GOOGLE_SIGNED_IN.test(text) || text.startsWith("[google-sign-in] "))
|
|
76746
|
+
last = null;
|
|
76534
76747
|
}
|
|
76535
76748
|
}
|
|
76536
|
-
|
|
76537
|
-
const authedLegacy = t.includes("@auth") || t.includes("@needs-auth") || isApi;
|
|
76538
|
-
const selfLoginWithoutStoredCreds = t.includes("@auth") && !t.includes("@needs-auth") && !isApi && !!code?.trim() && !/TEST_USER_EMAIL|TEST_USER_PASSWORD|__vqaLogin\b/.test(code);
|
|
76539
|
-
const apiWithoutStoredCreds = isApi && !t.includes("@auth") && !t.includes("@needs-auth") && !!code?.trim() && !codeReadsStoredCredentials(code);
|
|
76540
|
-
const needsLoginCreds = authedLegacy && !selfLoginWithoutStoredCreds && !apiWithoutStoredCreds;
|
|
76541
|
-
return {
|
|
76542
|
-
version: 1,
|
|
76543
|
-
source: "legacy",
|
|
76544
|
-
acquisition: cookie ? "browser-bootstrap" : authedLegacy ? "request-login" : "none",
|
|
76545
|
-
presentation: authedLegacy ? "cookie" : "none",
|
|
76546
|
-
needsCookieState: cookie,
|
|
76547
|
-
needsStandingHeaders: false,
|
|
76548
|
-
// A legacy bare-@api test keeps injecting standing headers IF the project configured them
|
|
76549
|
-
// (preserving today's behavior) — but does not require them. Non-@api legacy tests never inject.
|
|
76550
|
-
standingHeadersMode: isApi ? "legacy-if-configured" : "none",
|
|
76551
|
-
needsLoginCreds,
|
|
76552
|
-
requiredEnvKeys: needsLoginCreds ? [...TEST_USER_ENV_KEYS] : []
|
|
76553
|
-
};
|
|
76749
|
+
return last;
|
|
76554
76750
|
}
|
|
76555
|
-
function
|
|
76556
|
-
const
|
|
76557
|
-
|
|
76558
|
-
|
|
76751
|
+
function stepConsoleLines(result) {
|
|
76752
|
+
const steps = Array.isArray(result) ? result : result && typeof result === "object" && Array.isArray(result.stepResults) ? result.stepResults : [];
|
|
76753
|
+
return steps.flatMap((step) => {
|
|
76754
|
+
const logs = step && typeof step === "object" ? step.consoleLogs : null;
|
|
76755
|
+
return Array.isArray(logs) ? logs.filter((line) => typeof line === "string") : [];
|
|
76756
|
+
});
|
|
76559
76757
|
}
|
|
76560
|
-
var
|
|
76561
|
-
var
|
|
76562
|
-
"../shared/dist/
|
|
76758
|
+
var GOOGLE_BROKER_UNAVAILABLE, GOOGLE_BROKER_ASKED, GOOGLE_SIGNED_IN, TIMEOUT_ERROR;
|
|
76759
|
+
var init_google_broker_lines = __esm({
|
|
76760
|
+
"../shared/dist/google-broker-lines.js"() {
|
|
76563
76761
|
"use strict";
|
|
76564
|
-
|
|
76565
|
-
|
|
76566
|
-
|
|
76567
|
-
|
|
76568
|
-
|
|
76569
|
-
|
|
76570
|
-
|
|
76571
|
-
|
|
76572
|
-
|
|
76573
|
-
|
|
76574
|
-
|
|
76575
|
-
|
|
76576
|
-
|
|
76577
|
-
|
|
76578
|
-
|
|
76579
|
-
|
|
76580
|
-
|
|
76581
|
-
|
|
76582
|
-
|
|
76583
|
-
|
|
76584
|
-
|
|
76585
|
-
|
|
76586
|
-
|
|
76762
|
+
GOOGLE_BROKER_UNAVAILABLE = /^\[google-sign-in\] (?:(?:busy|rate_limited|timeout|offline): |failed: Google sign-in service (?:answered 50[234]\b|unreachable))/;
|
|
76763
|
+
GOOGLE_BROKER_ASKED = /^\[google-sign-in\] the app started Google sign-in; asking the broker/;
|
|
76764
|
+
GOOGLE_SIGNED_IN = /^\[google-sign-in\] returned to the app with Google sign-in/;
|
|
76765
|
+
TIMEOUT_ERROR = /Test timeout of \d+ms exceeded|TimeoutError|Timeout:? \d+ ?ms/i;
|
|
76766
|
+
}
|
|
76767
|
+
});
|
|
76768
|
+
|
|
76769
|
+
// ../shared/dist/admin-view-return-to.js
|
|
76770
|
+
function sanitizeAdminViewReturnTo(value) {
|
|
76771
|
+
if (typeof value !== "string")
|
|
76772
|
+
return ADMIN_VIEW_DEFAULT_RETURN_TO;
|
|
76773
|
+
const trimmed = value.trim();
|
|
76774
|
+
if (!trimmed || trimmed.length > MAX_RETURN_TO_LENGTH)
|
|
76775
|
+
return ADMIN_VIEW_DEFAULT_RETURN_TO;
|
|
76776
|
+
if (!trimmed.startsWith("/") || trimmed.startsWith("//"))
|
|
76777
|
+
return ADMIN_VIEW_DEFAULT_RETURN_TO;
|
|
76778
|
+
if (trimmed.includes("\\") || /[\s\u0000-\u001f\u007f]/.test(trimmed))
|
|
76779
|
+
return ADMIN_VIEW_DEFAULT_RETURN_TO;
|
|
76780
|
+
let url;
|
|
76781
|
+
try {
|
|
76782
|
+
url = new URL(trimmed, PLACEHOLDER_ORIGIN);
|
|
76783
|
+
} catch {
|
|
76784
|
+
return ADMIN_VIEW_DEFAULT_RETURN_TO;
|
|
76785
|
+
}
|
|
76786
|
+
if (url.origin !== PLACEHOLDER_ORIGIN)
|
|
76787
|
+
return ADMIN_VIEW_DEFAULT_RETURN_TO;
|
|
76788
|
+
if (BLOCKED_PATH_RE.test(url.pathname))
|
|
76789
|
+
return ADMIN_VIEW_DEFAULT_RETURN_TO;
|
|
76790
|
+
const out = `${url.pathname}${url.search}${url.hash}`;
|
|
76791
|
+
if (out.startsWith("//") || out.includes("\\"))
|
|
76792
|
+
return ADMIN_VIEW_DEFAULT_RETURN_TO;
|
|
76793
|
+
return out;
|
|
76794
|
+
}
|
|
76795
|
+
var ADMIN_VIEW_DEFAULT_RETURN_TO, MAX_RETURN_TO_LENGTH, PLACEHOLDER_ORIGIN, BLOCKED_PATH_RE;
|
|
76796
|
+
var init_admin_view_return_to = __esm({
|
|
76797
|
+
"../shared/dist/admin-view-return-to.js"() {
|
|
76798
|
+
"use strict";
|
|
76799
|
+
ADMIN_VIEW_DEFAULT_RETURN_TO = "/sessions";
|
|
76800
|
+
MAX_RETURN_TO_LENGTH = 2048;
|
|
76801
|
+
PLACEHOLDER_ORIGIN = "https://admin-view.invalid";
|
|
76802
|
+
BLOCKED_PATH_RE = /^\/(?:login|admin-view)/i;
|
|
76587
76803
|
}
|
|
76588
76804
|
});
|
|
76589
76805
|
|
|
@@ -76594,13 +76810,16 @@ function stripEchoLines(text) {
|
|
|
76594
76810
|
function matchesAny(text, patterns) {
|
|
76595
76811
|
return patterns.some((p) => p.test(text));
|
|
76596
76812
|
}
|
|
76813
|
+
function isIntentionalNegativeAuthTest(input) {
|
|
76814
|
+
const meta = [input.testName, input.description].filter(Boolean).join(" ");
|
|
76815
|
+
return matchesAny(meta, INTENTIONAL_NEGATIVE_AUTH);
|
|
76816
|
+
}
|
|
76597
76817
|
function detectAuthBlock(input) {
|
|
76598
76818
|
const tags = input.tags ?? [];
|
|
76599
76819
|
const isAuthed = tags.some((t) => AUTHED_TAGS.includes(t));
|
|
76600
76820
|
if (!isAuthed)
|
|
76601
76821
|
return NO_DETECTION;
|
|
76602
|
-
|
|
76603
|
-
if (matchesAny(meta, INTENTIONAL_NEGATIVE_AUTH))
|
|
76822
|
+
if (isIntentionalNegativeAuthTest(input))
|
|
76604
76823
|
return NO_DETECTION;
|
|
76605
76824
|
const sources = [];
|
|
76606
76825
|
if (input.error)
|
|
@@ -76703,7 +76922,7 @@ var init_auth_block_detector = __esm({
|
|
|
76703
76922
|
/\b(reject|deny|denied|block(ed)?)\b[^\n]{0,20}\b(login|sign[\s-]?in|auth|credential|password)\b/i
|
|
76704
76923
|
];
|
|
76705
76924
|
ECHO_LINE_RE = /^\s*(?:(?:📋|🎭|🌐|⚙️?)|(?:stderr:\s*|stdout:\s*)?Locator:)/u;
|
|
76706
|
-
UNAUTHORIZED_TEXT_RE = /(?:return(?:s|ed|ing)?|respond(?:s|ed|ing)?|got|receiv(?:e|ed|ing)|gives?|sends?|yield(?:s|ed|ing)?|results?\s+in)\s+(?:a\s+|an\s+|the\s+)?(?:401|403)\b|\bstatus(?:\s+code)?\s
|
|
76925
|
+
UNAUTHORIZED_TEXT_RE = /(?:return(?:s|ed|ing)?|respond(?:s|ed|ing)?|got|receiv(?:e|ed|ing)|gives?|sends?|yield(?:s|ed|ing)?|results?\s+in)\s+(?:a\s+|an\s+|the\s+)?(?:401|403)\b|\bstatus(?:\s+code)?\s*(?::\s*)?(?:401|403)\b|\bHTTP\/[\d.]+\s+(?:401|403)\b|(?:401|403)['’]d\b|(?:[→⇒]|->)\s*(?:401|403)\b|(?:return(?:s|ed|ing)?|respond(?:s|ed|ing)?|got|receiv(?:e|ed|ing)|threw|throws?)\s+(?:a\s+|an\s+)?(?:unauthorized|forbidden)\b|\bnot\s+authenticated\b/i;
|
|
76707
76926
|
}
|
|
76708
76927
|
});
|
|
76709
76928
|
|
|
@@ -77644,12 +77863,70 @@ function isSharedAuthInjectEnabled(value = process.env.SHARED_AUTH_INJECT) {
|
|
|
77644
77863
|
function isAuthReadinessGuardEnabled(value = process.env.AUTH_READINESS_GUARD) {
|
|
77645
77864
|
return value?.trim().toLowerCase() !== "false";
|
|
77646
77865
|
}
|
|
77866
|
+
function visualBaselinesEnabled(projectId, raw = process.env.VISUAL_BASELINES_PROJECTS) {
|
|
77867
|
+
if (typeof projectId !== "string" || projectId.trim() === "")
|
|
77868
|
+
return false;
|
|
77869
|
+
const listed = (raw ?? "").split(",").map((entry) => entry.trim()).filter(Boolean);
|
|
77870
|
+
return listed.includes("*") || listed.includes(projectId);
|
|
77871
|
+
}
|
|
77647
77872
|
var init_feature_flags = __esm({
|
|
77648
77873
|
"../shared/dist/feature-flags.js"() {
|
|
77649
77874
|
"use strict";
|
|
77650
77875
|
}
|
|
77651
77876
|
});
|
|
77652
77877
|
|
|
77878
|
+
// ../shared/dist/visual-compare-limits.js
|
|
77879
|
+
function isSafeMaskSelector(selector) {
|
|
77880
|
+
if (typeof selector !== "string")
|
|
77881
|
+
return false;
|
|
77882
|
+
if (selector.trim().length === 0)
|
|
77883
|
+
return false;
|
|
77884
|
+
if (selector.length > VISUAL_MASK_SELECTOR_MAX_LENGTH)
|
|
77885
|
+
return false;
|
|
77886
|
+
return !VISUAL_MASK_SELECTOR_FORBIDDEN.test(selector);
|
|
77887
|
+
}
|
|
77888
|
+
var VISUAL_MASK_SELECTORS_MAX, VISUAL_MASK_SELECTOR_MAX_LENGTH, VISUAL_MASK_SELECTOR_FORBIDDEN;
|
|
77889
|
+
var init_visual_compare_limits = __esm({
|
|
77890
|
+
"../shared/dist/visual-compare-limits.js"() {
|
|
77891
|
+
"use strict";
|
|
77892
|
+
VISUAL_MASK_SELECTORS_MAX = 50;
|
|
77893
|
+
VISUAL_MASK_SELECTOR_MAX_LENGTH = 300;
|
|
77894
|
+
VISUAL_MASK_SELECTOR_FORBIDDEN = /[{};@<\r\n]/;
|
|
77895
|
+
}
|
|
77896
|
+
});
|
|
77897
|
+
|
|
77898
|
+
// ../shared/dist/visual-baseline-identity.js
|
|
77899
|
+
function isBrowserVersion(value) {
|
|
77900
|
+
return typeof value === "string" && value.length <= 32 && BROWSER_VERSION.test(value);
|
|
77901
|
+
}
|
|
77902
|
+
function renderIdentity(flavour, version, image) {
|
|
77903
|
+
if (!/^[a-z][a-z-]{0,31}$/.test(flavour) || !/^[a-z][a-z-]{0,31}$/.test(image) || !isBrowserVersion(version))
|
|
77904
|
+
return null;
|
|
77905
|
+
const identity = `${flavour}/${version}/${image}`;
|
|
77906
|
+
return identity.length <= RENDER_IDENTITY_MAX_LENGTH ? identity : null;
|
|
77907
|
+
}
|
|
77908
|
+
function v1RenderIdentity(version) {
|
|
77909
|
+
return renderIdentity(VISUAL_V1_IDENTITY.flavour, version, VISUAL_V1_IDENTITY.image);
|
|
77910
|
+
}
|
|
77911
|
+
function parseRenderIdentity(value) {
|
|
77912
|
+
if (typeof value !== "string" || value.length > RENDER_IDENTITY_MAX_LENGTH)
|
|
77913
|
+
return null;
|
|
77914
|
+
const parts = value.split("/");
|
|
77915
|
+
if (parts.length !== 3)
|
|
77916
|
+
return null;
|
|
77917
|
+
const [flavour, version, image] = parts;
|
|
77918
|
+
return renderIdentity(flavour, version, image) === value ? { flavour, version, image } : null;
|
|
77919
|
+
}
|
|
77920
|
+
var VISUAL_V1_IDENTITY, RENDER_IDENTITY_MAX_LENGTH, BROWSER_VERSION;
|
|
77921
|
+
var init_visual_baseline_identity = __esm({
|
|
77922
|
+
"../shared/dist/visual-baseline-identity.js"() {
|
|
77923
|
+
"use strict";
|
|
77924
|
+
VISUAL_V1_IDENTITY = { platform: "linux", image: "runner-fast", flavour: "headless-shell" };
|
|
77925
|
+
RENDER_IDENTITY_MAX_LENGTH = 64;
|
|
77926
|
+
BROWSER_VERSION = /^\d{1,4}(\.\d{1,6}){0,3}$/;
|
|
77927
|
+
}
|
|
77928
|
+
});
|
|
77929
|
+
|
|
77653
77930
|
// ../shared/dist/analytics-url.js
|
|
77654
77931
|
function isSensitiveQueryKey(key) {
|
|
77655
77932
|
return SENSITIVE_QUERY_KEY_RE.test(key);
|
|
@@ -78003,14 +78280,9 @@ function isOpenCodeGoModelId(id) {
|
|
|
78003
78280
|
function hasOpenCodeGoPrefix(id) {
|
|
78004
78281
|
return (id?.trim() ?? "").startsWith(OPENCODE_GO_PREFIX);
|
|
78005
78282
|
}
|
|
78006
|
-
function hasOpenCodeGo2Prefix(id) {
|
|
78007
|
-
return (id?.trim() ?? "").startsWith(OPENCODE_GO_2_PREFIX);
|
|
78008
|
-
}
|
|
78009
78283
|
function openCodeGoWireModel(id) {
|
|
78010
78284
|
const trimmed = id?.trim() ?? "";
|
|
78011
|
-
|
|
78012
|
-
return null;
|
|
78013
|
-
return trimmed.slice((hasOpenCodeGo2Prefix(trimmed) ? OPENCODE_GO_2_PREFIX : OPENCODE_GO_PREFIX).length);
|
|
78285
|
+
return isOpenCodeGoModelId(trimmed) ? trimmed.slice(OPENCODE_GO_PREFIX.length) : null;
|
|
78014
78286
|
}
|
|
78015
78287
|
function isZaiModelId(id) {
|
|
78016
78288
|
const trimmed = id?.trim() ?? "";
|
|
@@ -78119,7 +78391,7 @@ function museCliContributorMode(env = process.env) {
|
|
|
78119
78391
|
const raw = (env.MUSE_CLI_CONTRIBUTOR_MODE ?? "").trim().toLowerCase();
|
|
78120
78392
|
return raw === "off" || raw === "false" || raw === "0" || raw === "no" ? "off" : "on";
|
|
78121
78393
|
}
|
|
78122
|
-
var CLI_ENGINE_MODEL_IDS, BROWSER_CLI_ENGINE_IDS, PIPELINE_STEPS, CLI_ENGINE_RULES, ENGINE_NAMES, OPENROUTER_PREFIX, OPENROUTER_MODEL_PATTERN, OPENCODE_GO_PREFIX,
|
|
78394
|
+
var CLI_ENGINE_MODEL_IDS, BROWSER_CLI_ENGINE_IDS, PIPELINE_STEPS, CLI_ENGINE_RULES, ENGINE_NAMES, OPENROUTER_PREFIX, OPENROUTER_MODEL_PATTERN, OPENCODE_GO_PREFIX, OPENCODE_GO_MODEL_PATTERN, ZAI_PREFIX, ZAI_MODEL_PATTERN;
|
|
78123
78395
|
var init_engine_spec = __esm({
|
|
78124
78396
|
"../shared/dist/engine-spec.js"() {
|
|
78125
78397
|
"use strict";
|
|
@@ -78178,8 +78450,7 @@ var init_engine_spec = __esm({
|
|
|
78178
78450
|
OPENROUTER_PREFIX = "openrouter:";
|
|
78179
78451
|
OPENROUTER_MODEL_PATTERN = /^openrouter:[a-z0-9][a-z0-9._-]{0,40}\/[A-Za-z0-9._:-]{1,100}$/;
|
|
78180
78452
|
OPENCODE_GO_PREFIX = "opencode-go:";
|
|
78181
|
-
|
|
78182
|
-
OPENCODE_GO_MODEL_PATTERN = /^opencode-go(?:-2)?:[a-z0-9][a-z0-9._-]{0,100}$/;
|
|
78453
|
+
OPENCODE_GO_MODEL_PATTERN = /^opencode-go:[a-z0-9][a-z0-9._-]{0,100}$/;
|
|
78183
78454
|
ZAI_PREFIX = "zai:";
|
|
78184
78455
|
ZAI_MODEL_PATTERN = /^zai:glm-[a-z0-9][a-z0-9._-]{0,60}$/;
|
|
78185
78456
|
}
|
|
@@ -78504,14 +78775,19 @@ function has(map2, key) {
|
|
|
78504
78775
|
}
|
|
78505
78776
|
function providerChainFor(modelId) {
|
|
78506
78777
|
const key = chainKey(modelId);
|
|
78778
|
+
if (key && has(_overrideHops, key))
|
|
78779
|
+
return _overrideHops[key];
|
|
78507
78780
|
return key && has(PROVIDER_CHAINS, key) ? PROVIDER_CHAINS[key] : [];
|
|
78508
78781
|
}
|
|
78509
78782
|
function providerChainLeadsFor(modelId) {
|
|
78510
78783
|
const key = chainKey(modelId);
|
|
78784
|
+
if (key && has(_overrideLeads, key))
|
|
78785
|
+
return _overrideLeads[key];
|
|
78511
78786
|
return key && has(PROVIDER_CHAIN_LEADS, key) ? PROVIDER_CHAIN_LEADS[key] : [];
|
|
78512
78787
|
}
|
|
78513
78788
|
function allChains() {
|
|
78514
|
-
|
|
78789
|
+
const ordered = (map2, override) => [...Object.entries(map2).filter(([key]) => !has(override, key)), ...Object.entries(override)];
|
|
78790
|
+
return [...ordered(PROVIDER_CHAINS, _overrideHops), ...ordered(PROVIDER_CHAIN_LEADS, _overrideLeads)];
|
|
78515
78791
|
}
|
|
78516
78792
|
function isProviderChainHopId(modelId) {
|
|
78517
78793
|
const id = modelId ?? "";
|
|
@@ -78528,14 +78804,24 @@ function providerChainHostOf(value, modelValue) {
|
|
|
78528
78804
|
return "own";
|
|
78529
78805
|
if (hasZaiPrefix(value))
|
|
78530
78806
|
return "zai";
|
|
78531
|
-
if (hasOpenCodeGo2Prefix(value))
|
|
78532
|
-
return "opencode-go-2";
|
|
78533
78807
|
if (hasOpenCodeGoPrefix(value))
|
|
78534
78808
|
return "opencode-go";
|
|
78535
78809
|
if (hasOpenRouterPrefix(value))
|
|
78536
78810
|
return "openrouter";
|
|
78537
78811
|
return "own";
|
|
78538
78812
|
}
|
|
78813
|
+
function providerChainHostProvider(value) {
|
|
78814
|
+
if (typeof value !== "string" || !value)
|
|
78815
|
+
return null;
|
|
78816
|
+
if (hasOpenRouterPrefix(value))
|
|
78817
|
+
return "openrouter";
|
|
78818
|
+
if (hasOpenCodeGoPrefix(value))
|
|
78819
|
+
return "opencode-go";
|
|
78820
|
+
if (hasZaiPrefix(value))
|
|
78821
|
+
return "zai";
|
|
78822
|
+
const key = chainKey(value);
|
|
78823
|
+
return API_MODEL_CATALOG.find((m) => m.id === key)?.provider ?? GEMINI_ASSISTANT_MODELS.find((m) => m.id === key)?.provider ?? null;
|
|
78824
|
+
}
|
|
78539
78825
|
function providerHostPlan(modelId) {
|
|
78540
78826
|
const key = chainKey(modelId);
|
|
78541
78827
|
if (!key)
|
|
@@ -78553,7 +78839,140 @@ function providerHostPlan(modelId) {
|
|
|
78553
78839
|
}
|
|
78554
78840
|
return steps;
|
|
78555
78841
|
}
|
|
78556
|
-
|
|
78842
|
+
function providerChainModelKey(modelId) {
|
|
78843
|
+
return chainKey(modelId);
|
|
78844
|
+
}
|
|
78845
|
+
function hasProviderChainLeadsByDefault(modelId) {
|
|
78846
|
+
const key = chainKey(modelId);
|
|
78847
|
+
return key !== null && has(PROVIDER_CHAIN_LEADS, key);
|
|
78848
|
+
}
|
|
78849
|
+
function isChainablePrimary(id) {
|
|
78850
|
+
return typeof id === "string" && id !== "" && (has(PROVIDER_CHAINS, id) || has(PROVIDER_CHAIN_LEADS, id));
|
|
78851
|
+
}
|
|
78852
|
+
function defaultProviderChainEntries(primary) {
|
|
78853
|
+
if (!isChainablePrimary(primary))
|
|
78854
|
+
return [];
|
|
78855
|
+
const leads = has(PROVIDER_CHAIN_LEADS, primary) ? PROVIDER_CHAIN_LEADS[primary] : [];
|
|
78856
|
+
const hops = has(PROVIDER_CHAINS, primary) ? PROVIDER_CHAINS[primary] : [];
|
|
78857
|
+
return [...leads, primary, ...hops].map((hop) => ({ hop, enabled: true }));
|
|
78858
|
+
}
|
|
78859
|
+
function allowedProviderChainHosts(primary) {
|
|
78860
|
+
return defaultProviderChainEntries(primary).map((entry) => entry.hop);
|
|
78861
|
+
}
|
|
78862
|
+
function isPlainObject2(value) {
|
|
78863
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype;
|
|
78864
|
+
}
|
|
78865
|
+
function validateProviderChainEntries(primary, entries) {
|
|
78866
|
+
if (!isChainablePrimary(primary))
|
|
78867
|
+
return `${String(primary).slice(0, 80)} has no provider chain to order`;
|
|
78868
|
+
if (!Array.isArray(entries))
|
|
78869
|
+
return `${primary}: the chain must be a list`;
|
|
78870
|
+
if (entries.length > PROVIDER_CHAIN_MAX_ENTRIES)
|
|
78871
|
+
return `${primary}: at most ${PROVIDER_CHAIN_MAX_ENTRIES} hosts`;
|
|
78872
|
+
const allowed = allowedProviderChainHosts(primary);
|
|
78873
|
+
const seen = /* @__PURE__ */ new Set();
|
|
78874
|
+
for (const entry of entries) {
|
|
78875
|
+
if (!isPlainObject2(entry))
|
|
78876
|
+
return `${primary}: each host must be { hop, enabled }`;
|
|
78877
|
+
const keys = Object.keys(entry);
|
|
78878
|
+
if (keys.length !== 2 || !keys.includes("hop") || !keys.includes("enabled"))
|
|
78879
|
+
return `${primary}: each host must be { hop, enabled } and nothing else`;
|
|
78880
|
+
const { hop, enabled } = entry;
|
|
78881
|
+
if (typeof enabled !== "boolean")
|
|
78882
|
+
return `${primary}: enabled must be true or false`;
|
|
78883
|
+
if (typeof hop !== "string" || !hop)
|
|
78884
|
+
return `${primary}: hop must be a model value`;
|
|
78885
|
+
if (!allowed.includes(hop))
|
|
78886
|
+
return `${primary}: ${hop.slice(0, 80)} is not a host of this model`;
|
|
78887
|
+
if (seen.has(hop))
|
|
78888
|
+
return `${primary}: ${hop} is listed twice`;
|
|
78889
|
+
if (hop === primary && !enabled)
|
|
78890
|
+
return `${primary}: the model's own value stays on (pick another model on AI Models instead)`;
|
|
78891
|
+
seen.add(hop);
|
|
78892
|
+
}
|
|
78893
|
+
if (!seen.has(primary))
|
|
78894
|
+
return `${primary}: list the model's own value once, where its own host sits`;
|
|
78895
|
+
return null;
|
|
78896
|
+
}
|
|
78897
|
+
function decodeProviderChains(raw) {
|
|
78898
|
+
let value = raw;
|
|
78899
|
+
if (typeof raw === "string") {
|
|
78900
|
+
if (raw.length > PROVIDER_CHAINS_SETTING_MAX_CHARS)
|
|
78901
|
+
return { ok: false, error: `AI_PROVIDER_CHAINS is too long (at most ${PROVIDER_CHAINS_SETTING_MAX_CHARS} characters)` };
|
|
78902
|
+
try {
|
|
78903
|
+
value = JSON.parse(raw);
|
|
78904
|
+
} catch {
|
|
78905
|
+
return { ok: false, error: "AI_PROVIDER_CHAINS must be valid JSON" };
|
|
78906
|
+
}
|
|
78907
|
+
} else if (JSON.stringify(raw ?? null).length > PROVIDER_CHAINS_SETTING_MAX_CHARS) {
|
|
78908
|
+
return { ok: false, error: `AI_PROVIDER_CHAINS is too long (at most ${PROVIDER_CHAINS_SETTING_MAX_CHARS} characters)` };
|
|
78909
|
+
}
|
|
78910
|
+
if (!isPlainObject2(value))
|
|
78911
|
+
return { ok: false, error: 'AI_PROVIDER_CHAINS must be an object: { "<model>": [ { "hop": "<model value>", "enabled": true } ] }' };
|
|
78912
|
+
if (Object.keys(value).length > PROVIDER_CHAIN_MAX_PRIMARIES)
|
|
78913
|
+
return { ok: false, error: `AI_PROVIDER_CHAINS names at most ${PROVIDER_CHAIN_MAX_PRIMARIES} models` };
|
|
78914
|
+
return { ok: true, value };
|
|
78915
|
+
}
|
|
78916
|
+
function checkedProviderChains(value) {
|
|
78917
|
+
const out = {};
|
|
78918
|
+
for (const [primary, entries] of Object.entries(value)) {
|
|
78919
|
+
const problem = validateProviderChainEntries(primary, entries);
|
|
78920
|
+
if (problem)
|
|
78921
|
+
return { ok: false, error: problem };
|
|
78922
|
+
out[primary] = entries.map(({ hop, enabled }) => ({ hop, enabled }));
|
|
78923
|
+
}
|
|
78924
|
+
return { ok: true, value: out };
|
|
78925
|
+
}
|
|
78926
|
+
function parseProviderChainOverrides(raw) {
|
|
78927
|
+
const decoded = decodeProviderChains(raw);
|
|
78928
|
+
return decoded.ok ? checkedProviderChains(decoded.value) : decoded;
|
|
78929
|
+
}
|
|
78930
|
+
function parseStoredProviderChainOverrides(raw) {
|
|
78931
|
+
const decoded = decodeProviderChains(raw);
|
|
78932
|
+
if (!decoded.ok)
|
|
78933
|
+
return decoded;
|
|
78934
|
+
const dropped = [];
|
|
78935
|
+
const kept = {};
|
|
78936
|
+
for (const [primary, entries] of Object.entries(decoded.value)) {
|
|
78937
|
+
if (!isChainablePrimary(primary) || !Array.isArray(entries)) {
|
|
78938
|
+
kept[primary] = entries;
|
|
78939
|
+
continue;
|
|
78940
|
+
}
|
|
78941
|
+
const allowed = allowedProviderChainHosts(primary);
|
|
78942
|
+
kept[primary] = entries.filter((entry) => {
|
|
78943
|
+
const hop = isPlainObject2(entry) ? entry.hop : void 0;
|
|
78944
|
+
if (typeof hop !== "string" || hop === "" || allowed.includes(hop))
|
|
78945
|
+
return true;
|
|
78946
|
+
dropped.push({ primary, hop: hop.slice(0, 80) });
|
|
78947
|
+
return false;
|
|
78948
|
+
});
|
|
78949
|
+
}
|
|
78950
|
+
const checked = checkedProviderChains(kept);
|
|
78951
|
+
return checked.ok ? { ...checked, dropped } : checked;
|
|
78952
|
+
}
|
|
78953
|
+
function validateProviderChainsSetting(raw) {
|
|
78954
|
+
const parsed = parseProviderChainOverrides(raw);
|
|
78955
|
+
return parsed.ok ? null : parsed.error;
|
|
78956
|
+
}
|
|
78957
|
+
function setProviderChainOverrides(value, onDropped) {
|
|
78958
|
+
const parsed = value === null || value === void 0 || value === "" ? null : parseStoredProviderChainOverrides(value);
|
|
78959
|
+
if (parsed?.ok && parsed.dropped.length > 0)
|
|
78960
|
+
onDropped?.(parsed.dropped);
|
|
78961
|
+
_overrides = parsed?.ok ? parsed.value : null;
|
|
78962
|
+
_overrideLeads = {};
|
|
78963
|
+
_overrideHops = {};
|
|
78964
|
+
for (const [primary, entries] of Object.entries(_overrides ?? {})) {
|
|
78965
|
+
const at = entries.findIndex((entry) => entry.hop === primary);
|
|
78966
|
+
const on = (list) => list.filter((entry) => entry.enabled).map((entry) => entry.hop);
|
|
78967
|
+
_overrideLeads[primary] = on(entries.slice(0, at));
|
|
78968
|
+
_overrideHops[primary] = on(entries.slice(at + 1));
|
|
78969
|
+
}
|
|
78970
|
+
return parsed === null || parsed.ok;
|
|
78971
|
+
}
|
|
78972
|
+
function getProviderChainOverrides() {
|
|
78973
|
+
return _overrides;
|
|
78974
|
+
}
|
|
78975
|
+
var PROVIDER_CHAINS, PROVIDER_CHAIN_LEADS, PROVIDER_HOST_NOT_OFFERED, PROVIDER_CHAIN_MAX_ENTRIES, PROVIDER_CHAINS_SETTING_MAX_CHARS, PROVIDER_CHAIN_MAX_PRIMARIES, ALLOWED_PROVIDER_CHAIN_HOPS, _overrides, _overrideLeads, _overrideHops;
|
|
78557
78976
|
var init_provider_chains = __esm({
|
|
78558
78977
|
"../shared/dist/provider-chains.js"() {
|
|
78559
78978
|
"use strict";
|
|
@@ -78565,18 +78984,120 @@ var init_provider_chains = __esm({
|
|
|
78565
78984
|
"muse-spark-1.3-contributor": ["openrouter:meta/muse-spark-1.3-contributor"],
|
|
78566
78985
|
"claude-haiku-5-5": ["opencode-go:claude-haiku-5-5", "openrouter:anthropic/claude-haiku-5.5"],
|
|
78567
78986
|
"gemini-3.1-pro-preview": ["openrouter:google/gemini-3.1-pro-preview"],
|
|
78568
|
-
"deepseek-flash": ["opencode-go
|
|
78569
|
-
"deepseek-v4-pro": ["opencode-go
|
|
78987
|
+
"deepseek-flash": ["opencode-go:deepseek-v4.1-flash", "openrouter:deepseek/deepseek-v4.1-flash"],
|
|
78988
|
+
"deepseek-v4-pro": ["opencode-go:deepseek-v4-pro", "openrouter:deepseek/deepseek-v4-pro"]
|
|
78570
78989
|
};
|
|
78571
78990
|
PROVIDER_CHAIN_LEADS = {
|
|
78572
|
-
"openrouter:z-ai/glm-5.3-flash": ["zai:glm-5.3-flash", "opencode-go
|
|
78573
|
-
"openrouter:z-ai/glm-5.3": ["zai:glm-5.3", "opencode-go
|
|
78574
|
-
"openrouter:z-ai/glm-5.2": ["zai:glm-5.2", "opencode-go
|
|
78991
|
+
"openrouter:z-ai/glm-5.3-flash": ["zai:glm-5.3-flash", "opencode-go:glm-5.3-flash"],
|
|
78992
|
+
"openrouter:z-ai/glm-5.3": ["zai:glm-5.3", "opencode-go:glm-5.3"],
|
|
78993
|
+
"openrouter:z-ai/glm-5.2": ["zai:glm-5.2", "opencode-go:glm-5.2"]
|
|
78575
78994
|
};
|
|
78576
78995
|
PROVIDER_HOST_NOT_OFFERED = {
|
|
78577
78996
|
"muse-spark-1.3-contributor": { "opencode-go": "OpenCode Go serves Muse only on its Responses API" },
|
|
78578
78997
|
"gemini-3.1-pro-preview": { "opencode-go": "OpenCode Go does not serve Gemini" }
|
|
78579
78998
|
};
|
|
78999
|
+
PROVIDER_CHAIN_MAX_ENTRIES = 8;
|
|
79000
|
+
PROVIDER_CHAINS_SETTING_MAX_CHARS = 16e3;
|
|
79001
|
+
PROVIDER_CHAIN_MAX_PRIMARIES = 32;
|
|
79002
|
+
ALLOWED_PROVIDER_CHAIN_HOPS = /* @__PURE__ */ new Set([
|
|
79003
|
+
...Object.values(PROVIDER_CHAINS).flat(),
|
|
79004
|
+
...Object.values(PROVIDER_CHAIN_LEADS).flat()
|
|
79005
|
+
]);
|
|
79006
|
+
_overrides = null;
|
|
79007
|
+
_overrideLeads = {};
|
|
79008
|
+
_overrideHops = {};
|
|
79009
|
+
}
|
|
79010
|
+
});
|
|
79011
|
+
|
|
79012
|
+
// ../shared/dist/provider-accounts.js
|
|
79013
|
+
function modelNames(modelId) {
|
|
79014
|
+
const value = modelId.trim();
|
|
79015
|
+
const names = /* @__PURE__ */ new Set([value]);
|
|
79016
|
+
for (const prefix of HOST_PREFIXES) {
|
|
79017
|
+
if (!value.startsWith(prefix))
|
|
79018
|
+
continue;
|
|
79019
|
+
const bare = value.slice(prefix.length);
|
|
79020
|
+
names.add(bare);
|
|
79021
|
+
const slash = bare.lastIndexOf("/");
|
|
79022
|
+
if (slash >= 0)
|
|
79023
|
+
names.add(bare.slice(slash + 1));
|
|
79024
|
+
}
|
|
79025
|
+
const canonical = canonicalModelId(value);
|
|
79026
|
+
if (canonical) {
|
|
79027
|
+
names.add(canonical);
|
|
79028
|
+
const entry = API_MODEL_CATALOG.find((m) => m.id === canonical || m.apiModel === canonical);
|
|
79029
|
+
if (entry) {
|
|
79030
|
+
names.add(entry.id);
|
|
79031
|
+
if (entry.apiModel)
|
|
79032
|
+
names.add(entry.apiModel);
|
|
79033
|
+
}
|
|
79034
|
+
}
|
|
79035
|
+
return names;
|
|
79036
|
+
}
|
|
79037
|
+
function accountServesModel(models, modelId) {
|
|
79038
|
+
if (!models || models.length === 0)
|
|
79039
|
+
return true;
|
|
79040
|
+
if (!modelId)
|
|
79041
|
+
return false;
|
|
79042
|
+
const names = modelNames(modelId);
|
|
79043
|
+
return models.some((model) => names.has(model.trim()));
|
|
79044
|
+
}
|
|
79045
|
+
function normalizeProviderAccountModels(models) {
|
|
79046
|
+
if (!Array.isArray(models))
|
|
79047
|
+
return null;
|
|
79048
|
+
const out = [];
|
|
79049
|
+
for (const model of models) {
|
|
79050
|
+
if (typeof model !== "string")
|
|
79051
|
+
return null;
|
|
79052
|
+
const trimmed = model.trim();
|
|
79053
|
+
if (!PROVIDER_ACCOUNT_MODEL_PATTERN.test(trimmed) || trimmed.includes(".."))
|
|
79054
|
+
return null;
|
|
79055
|
+
if (!out.includes(trimmed))
|
|
79056
|
+
out.push(trimmed);
|
|
79057
|
+
}
|
|
79058
|
+
return out.length > MAX_PROVIDER_ACCOUNT_MODELS ? null : out;
|
|
79059
|
+
}
|
|
79060
|
+
function parseProviderAccountLists(value, providers) {
|
|
79061
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
79062
|
+
return null;
|
|
79063
|
+
const parsed = {};
|
|
79064
|
+
for (const provider of providers) {
|
|
79065
|
+
const list = value[provider];
|
|
79066
|
+
if (!Array.isArray(list))
|
|
79067
|
+
continue;
|
|
79068
|
+
const accounts = [];
|
|
79069
|
+
for (const raw of list) {
|
|
79070
|
+
if (!raw || typeof raw !== "object")
|
|
79071
|
+
continue;
|
|
79072
|
+
const { id, label, key, models } = raw;
|
|
79073
|
+
if (typeof id !== "string" || !id.trim() || typeof key !== "string" || !key.trim())
|
|
79074
|
+
continue;
|
|
79075
|
+
const modelList = Array.isArray(models) ? models.filter((m) => typeof m === "string" && m.trim() !== "").map((m) => m.trim()) : [];
|
|
79076
|
+
accounts.push({ id: id.trim(), label: typeof label === "string" && label.trim() ? label.trim() : null, key: key.trim(), models: modelList });
|
|
79077
|
+
}
|
|
79078
|
+
if (accounts.length > 0)
|
|
79079
|
+
parsed[provider] = accounts;
|
|
79080
|
+
}
|
|
79081
|
+
return parsed;
|
|
79082
|
+
}
|
|
79083
|
+
var DEFAULT_PROVIDER_ACCOUNT_ID, PROVIDER_ACCOUNT_ID_PATTERN, MAX_PROVIDER_ACCOUNTS, MAX_PROVIDER_ACCOUNT_MODELS, PROVIDER_ACCOUNT_MODEL_PATTERN, OPENCODE_GO_DEEPSEEK_GLM_MODELS, HOST_PREFIXES;
|
|
79084
|
+
var init_provider_accounts = __esm({
|
|
79085
|
+
"../shared/dist/provider-accounts.js"() {
|
|
79086
|
+
"use strict";
|
|
79087
|
+
init_api_model_catalog();
|
|
79088
|
+
DEFAULT_PROVIDER_ACCOUNT_ID = "primary";
|
|
79089
|
+
PROVIDER_ACCOUNT_ID_PATTERN = /^[a-z0-9][a-z0-9-]{0,39}$/;
|
|
79090
|
+
MAX_PROVIDER_ACCOUNTS = 10;
|
|
79091
|
+
MAX_PROVIDER_ACCOUNT_MODELS = 50;
|
|
79092
|
+
PROVIDER_ACCOUNT_MODEL_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:/-]{0,120}$/;
|
|
79093
|
+
OPENCODE_GO_DEEPSEEK_GLM_MODELS = [
|
|
79094
|
+
"deepseek-v4.1-flash",
|
|
79095
|
+
"deepseek-v4-pro",
|
|
79096
|
+
"glm-5.3-flash",
|
|
79097
|
+
"glm-5.3",
|
|
79098
|
+
"glm-5.2"
|
|
79099
|
+
];
|
|
79100
|
+
HOST_PREFIXES = ["opencode-go:", "zai:", "openrouter:"];
|
|
78580
79101
|
}
|
|
78581
79102
|
});
|
|
78582
79103
|
|
|
@@ -78695,6 +79216,25 @@ var init_project_engine_overrides = __esm({
|
|
|
78695
79216
|
}
|
|
78696
79217
|
});
|
|
78697
79218
|
|
|
79219
|
+
// ../shared/dist/trailing-slashes.js
|
|
79220
|
+
function stripTrailingSlashes(value) {
|
|
79221
|
+
let end = value.length;
|
|
79222
|
+
while (end > 0 && value.charCodeAt(end - 1) === 47)
|
|
79223
|
+
end--;
|
|
79224
|
+
return end === value.length ? value : value.slice(0, end);
|
|
79225
|
+
}
|
|
79226
|
+
function stripTrailingChars(value, isTrailing) {
|
|
79227
|
+
let end = value.length;
|
|
79228
|
+
while (end > 0 && isTrailing.test(value[end - 1]))
|
|
79229
|
+
end--;
|
|
79230
|
+
return end === value.length ? value : value.slice(0, end);
|
|
79231
|
+
}
|
|
79232
|
+
var init_trailing_slashes = __esm({
|
|
79233
|
+
"../shared/dist/trailing-slashes.js"() {
|
|
79234
|
+
"use strict";
|
|
79235
|
+
}
|
|
79236
|
+
});
|
|
79237
|
+
|
|
78698
79238
|
// ../shared/dist/gemini-visual.js
|
|
78699
79239
|
function visualProDailyBudget(raw) {
|
|
78700
79240
|
const parsed = raw && /^\s*\d{1,6}\s*$/.test(raw) ? Number(raw.trim()) : NaN;
|
|
@@ -78708,7 +79248,7 @@ function isRetiredGeminiModel(id) {
|
|
|
78708
79248
|
}
|
|
78709
79249
|
function geminiNativeModelsUrl(base2 = process.env.GEMINI_API_BASE) {
|
|
78710
79250
|
const raw = base2 && base2.trim() || GEMINI_OPENAI_BASE;
|
|
78711
|
-
const native = raw.replace(/\/openai\/?$/, "/")
|
|
79251
|
+
const native = stripTrailingSlashes(raw.replace(/\/openai\/?$/, "/"));
|
|
78712
79252
|
return `${native}/models?pageSize=1000`;
|
|
78713
79253
|
}
|
|
78714
79254
|
function asRecord(value) {
|
|
@@ -78828,6 +79368,7 @@ var KNOWN_INPUT_USD_PER_M, GEMINI_OPENAI_BASE, DEFAULT_GEMINI_SCREEN_MODEL, DEFA
|
|
|
78828
79368
|
var init_gemini_visual = __esm({
|
|
78829
79369
|
"../shared/dist/gemini-visual.js"() {
|
|
78830
79370
|
"use strict";
|
|
79371
|
+
init_trailing_slashes();
|
|
78831
79372
|
KNOWN_INPUT_USD_PER_M = {
|
|
78832
79373
|
"gemini-2.5-flash-lite": 0.1,
|
|
78833
79374
|
"gemini-3.1-flash-lite": 0.25,
|
|
@@ -80191,12 +80732,13 @@ function truncateAtWord(text, max) {
|
|
|
80191
80732
|
const slice = trimmed.slice(0, room + 1);
|
|
80192
80733
|
const lastSpace = slice.lastIndexOf(" ");
|
|
80193
80734
|
const cut = lastSpace > room * 0.5 ? slice.slice(0, lastSpace) : trimmed.slice(0, room);
|
|
80194
|
-
return `${cut
|
|
80735
|
+
return `${stripTrailingChars(cut, TRAILING_PUNCTUATION)}\u2026`;
|
|
80195
80736
|
}
|
|
80196
|
-
var CANVAS_UNSUPPORTED_CODE, CANVAS_UNSUPPORTED_TITLE, CANVAS_UNSUPPORTED_BODY, CANVAS_UNSUPPORTED_NOT_CHARGED, CANVAS_UNSUPPORTED_OVERRIDE_HINT, GAME_ENGINES, RENDERER_ENGINES, ENGINE_TEXT_SIGNATURES, GAME_LIBRARY_TEXT_PATTERNS, ENGINE_PACKAGES, GAME_HINT_PACKAGES, MAX_TAG_CHARS, MAX_CSS_SELECTOR_CHARS, MAX_CSS_BLOCK_CHARS, TAG_NAME_RE, ATTR_RE, INTERACTIVE_TAGS, INTERACTIVE_ROLES, ROOT_SELECTOR_RE, OVERFLOW_HIDDEN_RE, TOUCH_NONE_RE, CODE_TAGS, STATIC_STANDARD_MIN_INTERACTIVE;
|
|
80737
|
+
var CANVAS_UNSUPPORTED_CODE, CANVAS_UNSUPPORTED_TITLE, CANVAS_UNSUPPORTED_BODY, CANVAS_UNSUPPORTED_NOT_CHARGED, CANVAS_UNSUPPORTED_OVERRIDE_HINT, GAME_ENGINES, RENDERER_ENGINES, ENGINE_TEXT_SIGNATURES, GAME_LIBRARY_TEXT_PATTERNS, ENGINE_PACKAGES, GAME_HINT_PACKAGES, MAX_TAG_CHARS, MAX_CSS_SELECTOR_CHARS, MAX_CSS_BLOCK_CHARS, TAG_NAME_RE, ATTR_RE, INTERACTIVE_TAGS, INTERACTIVE_ROLES, ROOT_SELECTOR_RE, OVERFLOW_HIDDEN_RE, TOUCH_NONE_RE, CODE_TAGS, STATIC_STANDARD_MIN_INTERACTIVE, TRAILING_PUNCTUATION;
|
|
80197
80738
|
var init_canvas_support = __esm({
|
|
80198
80739
|
"../shared/dist/canvas-support.js"() {
|
|
80199
80740
|
"use strict";
|
|
80741
|
+
init_trailing_slashes();
|
|
80200
80742
|
CANVAS_UNSUPPORTED_CODE = "canvas_unsupported";
|
|
80201
80743
|
CANVAS_UNSUPPORTED_TITLE = "Games and canvas apps aren't supported yet";
|
|
80202
80744
|
CANVAS_UNSUPPORTED_BODY = "This app draws its screen on a canvas (like a game), so there are no page elements for Validate.QA to read and test. Support for games and canvas apps is coming.";
|
|
@@ -80321,6 +80863,7 @@ var init_canvas_support = __esm({
|
|
|
80321
80863
|
TOUCH_NONE_RE = /touch-action\s{0,8}:\s{0,8}none/;
|
|
80322
80864
|
CODE_TAGS = /* @__PURE__ */ new Set(["script", "link", "flt-glass-pane", "flutter-view", "flt-scene-host"]);
|
|
80323
80865
|
STATIC_STANDARD_MIN_INTERACTIVE = 3;
|
|
80866
|
+
TRAILING_PUNCTUATION = /[\s,;:.\-–—]/u;
|
|
80324
80867
|
}
|
|
80325
80868
|
});
|
|
80326
80869
|
|
|
@@ -80503,22 +81046,22 @@ function joinChainedLines(code) {
|
|
|
80503
81046
|
const trimmed = lines[i].trimStart();
|
|
80504
81047
|
if (last !== -1 && trimmed.startsWith(".") && !trimmed.startsWith("...")) {
|
|
80505
81048
|
if (!lastStripped) {
|
|
80506
|
-
lines[last] =
|
|
81049
|
+
lines[last] = stripLineComment3(lines[last]).trimEnd();
|
|
80507
81050
|
lastStripped = true;
|
|
80508
81051
|
}
|
|
80509
81052
|
if (lines[last].length <= MAX_LINE_CHARS)
|
|
80510
|
-
lines[last] = `${lines[last]} ${
|
|
81053
|
+
lines[last] = `${lines[last]} ${stripLineComment3(trimmed).trimEnd()}`;
|
|
80511
81054
|
lines[i] = "";
|
|
80512
81055
|
continue;
|
|
80513
81056
|
}
|
|
80514
|
-
if (
|
|
81057
|
+
if (stripLineComment3(lines[i]).trim()) {
|
|
80515
81058
|
last = i;
|
|
80516
81059
|
lastStripped = false;
|
|
80517
81060
|
}
|
|
80518
81061
|
}
|
|
80519
81062
|
return lines.join("\n");
|
|
80520
81063
|
}
|
|
80521
|
-
function
|
|
81064
|
+
function stripLineComment3(rawLine) {
|
|
80522
81065
|
if (rawLine.trimStart().startsWith("//"))
|
|
80523
81066
|
return "";
|
|
80524
81067
|
const at = rawLine.indexOf(" // ");
|
|
@@ -80567,7 +81110,7 @@ function analyzeReadinessPolling(rawCode) {
|
|
|
80567
81110
|
offset += rawLine.length + 1;
|
|
80568
81111
|
if (rawLine.length > MAX_LINE_CHARS)
|
|
80569
81112
|
continue;
|
|
80570
|
-
const line =
|
|
81113
|
+
const line = stripLineComment3(rawLine);
|
|
80571
81114
|
if (!line.trim())
|
|
80572
81115
|
continue;
|
|
80573
81116
|
const literals = literalsOf(line);
|
|
@@ -80679,7 +81222,7 @@ function blankBlockComments2(code) {
|
|
|
80679
81222
|
from = close + 2;
|
|
80680
81223
|
}
|
|
80681
81224
|
}
|
|
80682
|
-
function
|
|
81225
|
+
function stripLineComment4(rawLine) {
|
|
80683
81226
|
if (rawLine.trimStart().startsWith("//"))
|
|
80684
81227
|
return "";
|
|
80685
81228
|
const at = rawLine.indexOf(" // ");
|
|
@@ -80690,7 +81233,7 @@ function logicalLines(code) {
|
|
|
80690
81233
|
for (const raw of code.split("\n")) {
|
|
80691
81234
|
if (raw.length > MAX_LINE_CHARS2)
|
|
80692
81235
|
continue;
|
|
80693
|
-
const line =
|
|
81236
|
+
const line = stripLineComment4(raw).trimEnd();
|
|
80694
81237
|
if (!line.trim())
|
|
80695
81238
|
continue;
|
|
80696
81239
|
const trimmed = line.trimStart();
|
|
@@ -81052,8 +81595,19 @@ function short4(text, max) {
|
|
|
81052
81595
|
const flat = text.replace(/\s+/g, " ").trim();
|
|
81053
81596
|
return flat.length > max ? `${flat.slice(0, max - 1)}\u2026` : flat;
|
|
81054
81597
|
}
|
|
81598
|
+
function stripFractionZeros(s) {
|
|
81599
|
+
let end = s.length;
|
|
81600
|
+
while (end > 0 && s[end - 1] === "0")
|
|
81601
|
+
end--;
|
|
81602
|
+
if (end === s.length)
|
|
81603
|
+
return s;
|
|
81604
|
+
const dot = s.lastIndexOf(".");
|
|
81605
|
+
if (dot < 0)
|
|
81606
|
+
return s;
|
|
81607
|
+
return s.slice(0, end === dot + 1 ? dot : end);
|
|
81608
|
+
}
|
|
81055
81609
|
function digitsOf(token) {
|
|
81056
|
-
return token.replace(/[^\d.]/g, "")
|
|
81610
|
+
return stripFractionZeros(token.replace(/[^\d.]/g, "")).replace(/^0+(?=\d)/, "");
|
|
81057
81611
|
}
|
|
81058
81612
|
function computes(line) {
|
|
81059
81613
|
const code = line.replace(STRING_RE, '""').replace(REGEX_LITERAL_RE, "$1RX").replace(LITERAL_ARITH_RE, "N");
|
|
@@ -81271,7 +81825,7 @@ function findExpectCalls(code) {
|
|
|
81271
81825
|
if (!subj)
|
|
81272
81826
|
continue;
|
|
81273
81827
|
const rest = code.slice(subj.end + 1, subj.end + 1 + 80);
|
|
81274
|
-
const mm = /^\s*((?:\.\s*not)
|
|
81828
|
+
const mm = /^\s*((?:\.\s*not\s*)?\.\s*(\w+))\s{0,20}\(/.exec(rest);
|
|
81275
81829
|
if (!mm)
|
|
81276
81830
|
continue;
|
|
81277
81831
|
const argStart = subj.end + 1 + mm[0].length;
|
|
@@ -83221,6 +83775,28 @@ function startsWithRegexLiteral(text) {
|
|
|
83221
83775
|
const t = text.trimStart();
|
|
83222
83776
|
return t[0] === "/" && t[1] !== "/" && t[1] !== "*" && regexLiteralEnd4(t, 0) !== -1;
|
|
83223
83777
|
}
|
|
83778
|
+
function isBareRegexLiteral(text) {
|
|
83779
|
+
const t = text.trimStart();
|
|
83780
|
+
if (t[0] !== "/" || t[1] === "/" || t[1] === "*")
|
|
83781
|
+
return false;
|
|
83782
|
+
const end = regexLiteralEnd4(t, 0);
|
|
83783
|
+
if (end === -1)
|
|
83784
|
+
return false;
|
|
83785
|
+
let i = end;
|
|
83786
|
+
while (i < t.length && /[a-z]/.test(t[i]))
|
|
83787
|
+
i++;
|
|
83788
|
+
while (i < t.length && /\s/.test(t[i]))
|
|
83789
|
+
i++;
|
|
83790
|
+
return i >= t.length || t[i] === ",";
|
|
83791
|
+
}
|
|
83792
|
+
function regexDeclaredNames(code) {
|
|
83793
|
+
const names = /* @__PURE__ */ new Set();
|
|
83794
|
+
const decl = /\b(?:const|let|var)\s{1,20}([A-Za-z_$][\w$]{0,80})\s{0,20}=\s{0,20}(?:\/(?![/*])|new\s{1,20}RegExp\b)/g;
|
|
83795
|
+
let m;
|
|
83796
|
+
while ((m = decl.exec(code)) !== null)
|
|
83797
|
+
names.add(m[1]);
|
|
83798
|
+
return names;
|
|
83799
|
+
}
|
|
83224
83800
|
function afterFirstArg(args) {
|
|
83225
83801
|
let depth = 0;
|
|
83226
83802
|
let quote = null;
|
|
@@ -83258,6 +83834,7 @@ function analyzeRegexMatchers(rawCode) {
|
|
|
83258
83834
|
let examined = 0;
|
|
83259
83835
|
let line = 1;
|
|
83260
83836
|
let lineAt2 = 0;
|
|
83837
|
+
let regexNames;
|
|
83261
83838
|
while ((m = re.exec(code)) !== null && examined++ < MAX_CALLS && out.length < MAX_REGEX_MATCHER_FINDINGS) {
|
|
83262
83839
|
const subj = readBalanced(code, m.index + m[0].length);
|
|
83263
83840
|
if (!subj)
|
|
@@ -83269,10 +83846,18 @@ function analyzeRegexMatchers(rawCode) {
|
|
|
83269
83846
|
if (!args)
|
|
83270
83847
|
continue;
|
|
83271
83848
|
const expected = mm[2] === "toHaveJSProperty" ? afterFirstArg(args.text) : args.text;
|
|
83272
|
-
if (!
|
|
83273
|
-
continue;
|
|
83274
|
-
if (mm[2] !== "toHaveJSProperty" && mm[2] !== "toContain" && (startsWithRegexLiteral(subj.text) || /^new\s+RegExp\b/.test(subj.text.trim())))
|
|
83849
|
+
if (!isBareRegexLiteral(expected))
|
|
83275
83850
|
continue;
|
|
83851
|
+
if (mm[2] !== "toHaveJSProperty" && mm[2] !== "toContain") {
|
|
83852
|
+
const subject = subj.text.trim();
|
|
83853
|
+
if (startsWithRegexLiteral(subject) || /^new\s+RegExp\b/.test(subject))
|
|
83854
|
+
continue;
|
|
83855
|
+
if (/^[A-Za-z_$][\w$]{0,80}$/.test(subject)) {
|
|
83856
|
+
regexNames ??= regexDeclaredNames(code);
|
|
83857
|
+
if (regexNames.has(subject))
|
|
83858
|
+
continue;
|
|
83859
|
+
}
|
|
83860
|
+
}
|
|
83276
83861
|
for (let i = code.indexOf("\n", lineAt2); i !== -1 && i < m.index; i = code.indexOf("\n", i + 1)) {
|
|
83277
83862
|
line++;
|
|
83278
83863
|
lineAt2 = i + 1;
|
|
@@ -83282,9 +83867,12 @@ function analyzeRegexMatchers(rawCode) {
|
|
|
83282
83867
|
return out;
|
|
83283
83868
|
}
|
|
83284
83869
|
function formatRegexMatcherNote(findings) {
|
|
83285
|
-
const lines = findings.map((f) =>
|
|
83870
|
+
const lines = findings.map((f) => {
|
|
83871
|
+
const negated = f.matcher === "toContain" ? "throws on a string and otherwise always passes (a regex never equals an item), so it checks nothing" : "always passes (a regex never equals the value), so it checks nothing";
|
|
83872
|
+
return `Line ${f.line}: .${f.negated ? "not." : ""}${f.matcher}(\u2026 /regex/ \u2026) ${f.negated ? negated : "can never pass: this matcher compares by equality and a regex never equals a value"}.`;
|
|
83873
|
+
});
|
|
83286
83874
|
return `${lines.join("\n")}
|
|
83287
|
-
A regex only works in toMatch, toHaveText, toContainText, toHaveValue and similar text matchers. For
|
|
83875
|
+
A regex only works in toMatch, toHaveText, toContainText, toHaveValue and similar text matchers. For the \`value\` of an input, textarea or select, use await expect(loc).toHaveValue(/re/). For any other DOM property (or element), poll it so the check still retries: await expect.poll(() => loc.evaluate((n) => n.<prop>)).toMatch(/re/). Never read it once with expect(await loc.evaluate(\u2026)), which sees the value before the page updates it. Or give toHaveJSProperty the exact string (or boolean) the page shows. Keep every other line as-is.`;
|
|
83288
83876
|
}
|
|
83289
83877
|
function lintTestQuality(rawCode, opts = {}) {
|
|
83290
83878
|
if (!rawCode || typeof rawCode !== "string")
|
|
@@ -84033,19 +84621,6 @@ var init_fence_runs = __esm({
|
|
|
84033
84621
|
}
|
|
84034
84622
|
});
|
|
84035
84623
|
|
|
84036
|
-
// ../shared/dist/trailing-slashes.js
|
|
84037
|
-
function stripTrailingSlashes(value) {
|
|
84038
|
-
let end = value.length;
|
|
84039
|
-
while (end > 0 && value.charCodeAt(end - 1) === 47)
|
|
84040
|
-
end--;
|
|
84041
|
-
return end === value.length ? value : value.slice(0, end);
|
|
84042
|
-
}
|
|
84043
|
-
var init_trailing_slashes = __esm({
|
|
84044
|
-
"../shared/dist/trailing-slashes.js"() {
|
|
84045
|
-
"use strict";
|
|
84046
|
-
}
|
|
84047
|
-
});
|
|
84048
|
-
|
|
84049
84624
|
// ../shared/dist/survey-bug-signature.js
|
|
84050
84625
|
function normalizeWords(text) {
|
|
84051
84626
|
return text.toLowerCase().replace(UUID, " id ").replace(PREFIXED_ID, " id ").replace(HEX_RUN, (run) => /\d/.test(run) ? " id " : run).replace(NUMBER_RUN, " # ").replace(/[^\p{L}\p{N}#]+/gu, " ").replace(/\s+/g, " ").trim();
|
|
@@ -84069,14 +84644,17 @@ function requestSignatures(text) {
|
|
|
84069
84644
|
const statuses = [...text.matchAll(HTTP_STATUS)].map((m) => ({ status: m[1], at: m.index ?? 0, end: (m.index ?? 0) + m[0].length }));
|
|
84070
84645
|
if (statuses.length === 0)
|
|
84071
84646
|
return [];
|
|
84072
|
-
const paths = [...text.matchAll(PATH_IN_TEXT)].map((m) =>
|
|
84073
|
-
|
|
84074
|
-
|
|
84075
|
-
|
|
84076
|
-
|
|
84077
|
-
|
|
84078
|
-
|
|
84079
|
-
|
|
84647
|
+
const paths = [...text.matchAll(PATH_IN_TEXT)].map((m) => {
|
|
84648
|
+
const rawPath = stripTrailingChars(m[2] ?? m[3] ?? "", PATH_TRAILING_PUNCTUATION);
|
|
84649
|
+
return {
|
|
84650
|
+
method: m[1] ?? null,
|
|
84651
|
+
path: normalizeBugPath(rawPath),
|
|
84652
|
+
// Before normalisation, which turns a segment with a digit (favicon-32x32.png) into :id.
|
|
84653
|
+
incidental: isIncidentalAssetPath(rawPath.split(/[?#]/, 1)[0].toLowerCase()),
|
|
84654
|
+
at: m.index ?? 0,
|
|
84655
|
+
end: (m.index ?? 0) + m[0].length
|
|
84656
|
+
};
|
|
84657
|
+
}).filter((p) => p.path.length > 1);
|
|
84080
84658
|
const out = /* @__PURE__ */ new Map();
|
|
84081
84659
|
for (const { status, at, end } of statuses) {
|
|
84082
84660
|
const lead = STATUS_TO_PATH.exec(text.slice(end, end + 40));
|
|
@@ -84186,11 +84764,12 @@ function dedupeSiteWideSuspectedBugs(drafts) {
|
|
|
84186
84764
|
delete plans.suspectedBugs;
|
|
84187
84765
|
}
|
|
84188
84766
|
}
|
|
84189
|
-
var SIGNATURE_SOURCE_MAX_CHARS, UUID, PREFIXED_ID, HEX_RUN, NUMBER_RUN, GENERIC_JS_MESSAGES, GENERIC_JS_PREFIXES, JS_ERROR, MESSAGE_CLAUSE_END, HTTP_STATUS, PATH_IN_TEXT, STATUS_TO_PATH, INCIDENTAL_ASSET;
|
|
84767
|
+
var PATH_TRAILING_PUNCTUATION, SIGNATURE_SOURCE_MAX_CHARS, UUID, PREFIXED_ID, HEX_RUN, NUMBER_RUN, GENERIC_JS_MESSAGES, GENERIC_JS_PREFIXES, JS_ERROR, MESSAGE_CLAUSE_END, HTTP_STATUS, PATH_IN_TEXT, STATUS_TO_PATH, INCIDENTAL_ASSET;
|
|
84190
84768
|
var init_survey_bug_signature = __esm({
|
|
84191
84769
|
"../shared/dist/survey-bug-signature.js"() {
|
|
84192
84770
|
"use strict";
|
|
84193
84771
|
init_trailing_slashes();
|
|
84772
|
+
PATH_TRAILING_PUNCTUATION = /[.,;:]/;
|
|
84194
84773
|
SIGNATURE_SOURCE_MAX_CHARS = 800;
|
|
84195
84774
|
UUID = /\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/g;
|
|
84196
84775
|
PREFIXED_ID = /\b[a-z]{1,8}[-_]\d+\b/g;
|
|
@@ -85521,7 +86100,7 @@ function pathIdsIn(text) {
|
|
|
85521
86100
|
function findCounterIdPins(code) {
|
|
85522
86101
|
if (code.length > CLOCK_MAX_CODE_CHARS)
|
|
85523
86102
|
return [];
|
|
85524
|
-
const
|
|
86103
|
+
const clean3 = stripLineComments(blankBlockComments3(code));
|
|
85525
86104
|
const fillValues = [];
|
|
85526
86105
|
const candidates = [];
|
|
85527
86106
|
let seenWrite = false;
|
|
@@ -85529,24 +86108,24 @@ function findCounterIdPins(code) {
|
|
|
85529
86108
|
CALL_RE.lastIndex = 0;
|
|
85530
86109
|
let m;
|
|
85531
86110
|
let calls = 0;
|
|
85532
|
-
while (calls++ < MAX_CALLS2 && (m = CALL_RE.exec(
|
|
86111
|
+
while (calls++ < MAX_CALLS2 && (m = CALL_RE.exec(clean3)) !== null) {
|
|
85533
86112
|
const name = m[1];
|
|
85534
86113
|
const open = m.index + m[0].length - 1;
|
|
85535
86114
|
if (VALUE_WRITES.has(name)) {
|
|
85536
86115
|
seenWrite = true;
|
|
85537
|
-
const args2 = argsAt(
|
|
86116
|
+
const args2 = argsAt(clean3, open);
|
|
85538
86117
|
if (args2 !== null)
|
|
85539
86118
|
fillValues.push(...staticStrings(args2));
|
|
85540
86119
|
continue;
|
|
85541
86120
|
}
|
|
85542
86121
|
if (createIndex === -1) {
|
|
85543
|
-
if (name === "click" && seenWrite && isCreateClick(
|
|
86122
|
+
if (name === "click" && seenWrite && isCreateClick(clean3, m.index))
|
|
85544
86123
|
createIndex = m.index;
|
|
85545
86124
|
continue;
|
|
85546
86125
|
}
|
|
85547
86126
|
if (name === "click")
|
|
85548
86127
|
continue;
|
|
85549
|
-
const args = argsAt(
|
|
86128
|
+
const args = argsAt(clean3, open);
|
|
85550
86129
|
if (args === null)
|
|
85551
86130
|
continue;
|
|
85552
86131
|
const isUrl = URL_SINKS.has(name);
|
|
@@ -85565,7 +86144,7 @@ function findCounterIdPins(code) {
|
|
|
85565
86144
|
}
|
|
85566
86145
|
if (createIndex === -1)
|
|
85567
86146
|
return [];
|
|
85568
|
-
const before =
|
|
86147
|
+
const before = clean3.slice(0, createIndex);
|
|
85569
86148
|
let pathIdsBefore = null;
|
|
85570
86149
|
const findings = [];
|
|
85571
86150
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -85589,7 +86168,7 @@ function findCounterIdPins(code) {
|
|
|
85589
86168
|
continue;
|
|
85590
86169
|
}
|
|
85591
86170
|
}
|
|
85592
|
-
findings.push({ kind: c.kind, literal: c.literal, line: lineAt(
|
|
86171
|
+
findings.push({ kind: c.kind, literal: c.literal, line: lineAt(clean3, c.index) });
|
|
85593
86172
|
}
|
|
85594
86173
|
return findings;
|
|
85595
86174
|
}
|
|
@@ -85884,7 +86463,7 @@ var init_suspicious_expectation = __esm({
|
|
|
85884
86463
|
NOT_STUCK_RE = /\b(?:not|never|no longer|isn't|doesn't|don't|without)\s+(?:\w+\s+){0,2}?(?:stuck|hang|hangs|hung|freeze|freezes|frozen|spin|spins|spinning)\b/i;
|
|
85885
86464
|
LISTS_STUCK_RE = /\b(?:appears? in (?:the )?[\w ]{0,25}(?:report|list|dashboard|queue)|(?:lists?|monitors?|shows?|reports?) (?:\w+ ){0,2}(?:that|which|whose) (?:are |is )?(?:stuck|hangs?|hung|frozen)|can (?:retry|re-?run) (?:\w+ ){0,2}(?:that (?:are )?)?stuck)\b/i;
|
|
85886
86465
|
STUCK_VETO_RE = new RegExp(`${NOT_STUCK_RE.source}|${LISTS_STUCK_RE.source}`, "i");
|
|
85887
|
-
NOT_SILENT_RE = /\b(?:not|never|\w+n't|instead of|rather than|avoids?|prevents?)\s+(?:\w+\s+){0,1}?(?:fail(?:s|ing|ed)?|ignor\w*)
|
|
86466
|
+
NOT_SILENT_RE = /\b(?:not|never|\w+n't|instead of|rather than|avoids?|prevents?)\s+(?:\w+\s+){0,1}?(?:(?:fail(?:s|ing|ed)?|ignor\w*)\s*)?silent(?:ly)?\b/i;
|
|
85888
86467
|
PENDING_WORD = "(?:sending|loading|saving|searching|checking(?!\\s+(?:account|balance|out|in)\\b)|syncing|refreshing|fetching|validating|processing|submitting|uploading|posting|publishing|creating|updating|deleting|connecting|verifying|signing in|logging in)";
|
|
85889
86468
|
ELLIPSIS = "(?:\\.{3}|\u2026)";
|
|
85890
86469
|
NOT_STAY_RE = /\b(?:not|never|no longer|without|n't|cannot)\s+(?:\w+\s+){0,2}?(?:stay|stays|stayed|remain|remains|remained|leave|leaves|left)\b/i;
|
|
@@ -86040,7 +86619,7 @@ function outcomeNamedByAssertion(outcome, code) {
|
|
|
86040
86619
|
function namedByStatements(outcome, statements) {
|
|
86041
86620
|
const text = outcomeText(outcome);
|
|
86042
86621
|
if (outcome.type === "url") {
|
|
86043
|
-
const routes = (text.match(ROUTE_TERM) ?? []).map((r) => r
|
|
86622
|
+
const routes = (text.match(ROUTE_TERM) ?? []).map((r) => stripTrailingChars(r, ROUTE_TRAILING_PUNCTUATION)).filter((r) => r.length > 1);
|
|
86044
86623
|
return statements.some((stmt) => {
|
|
86045
86624
|
if (!/\.(?:waitForURL|toHaveURL)\s{0,20}\(/.test(stmt))
|
|
86046
86625
|
return false;
|
|
@@ -86212,7 +86791,7 @@ function evaluatePromotionGate(input, checks = PROMOTION_QUALITY_CHECKS) {
|
|
|
86212
86791
|
...suspiciousTagged ? { suspiciousPass: { mode: suspicious, covered: suspiciousCovered, wouldHold: suspiciousHold } } : {}
|
|
86213
86792
|
};
|
|
86214
86793
|
}
|
|
86215
|
-
var SOURCE_RANK, strengthCheck, STRING_CONST, TYPED_VALUE, TYPED_CONSTANT, MAX_STATEMENTS, MAX_STATEMENT_CHARS, LITERAL_OR_IDENTIFIER, MUTATING_ACTION, FEEDBACK_REGION, ONE_SHOT_MESSAGE_REASON, FEEDBACK_REGION_ALL, dynamicAssertionCheck, OUTCOME_KIND_MATCHER, ROUTE_TERM, QUOTED_LITERAL, GENERIC_LITERAL, MAX_OUTCOME_STATEMENTS, MAX_OUTCOMES, MAX_OUTCOME_TEXT_CHARS, expectedOutcomeCheck, testDataCheck, sharedAccountCheck, clockLiteralCheck, readinessPollCheck, knownBugTestCheck, bugClaimContractCheck, suspiciousExpectationCheck, bugCandidateCheck, conventionOutcomesCheck, pendingHook, locatorFragmentCheck, FILTER_STEP, NEXT_ACTION, REDUCTION_PROOF, MAX_FILTER_LINES, MAX_FILTER_LINE_CHARS, filterPositiveOnlyCheck, PROMOTION_QUALITY_CHECKS, PROMOTION_GATE_MAX_CODE_CHARS, NOT_EVALUATED, SUSPICIOUS_PASS_TAG, NOT_CONTENT_MATCHER, CONTENT_PROOF, NAMED_ELEMENT, NEEDS_REVIEW_TAG, count2, RECHECKED_NOTES, EVIDENCE_NOTE_PREFIXES, PENDING_RECHECK_NOTE_PREFIXES, STRENGTH_RANK;
|
|
86794
|
+
var SOURCE_RANK, strengthCheck, STRING_CONST, TYPED_VALUE, TYPED_CONSTANT, MAX_STATEMENTS, MAX_STATEMENT_CHARS, LITERAL_OR_IDENTIFIER, MUTATING_ACTION, FEEDBACK_REGION, ONE_SHOT_MESSAGE_REASON, FEEDBACK_REGION_ALL, dynamicAssertionCheck, OUTCOME_KIND_MATCHER, ROUTE_TERM, ROUTE_TRAILING_PUNCTUATION, QUOTED_LITERAL, GENERIC_LITERAL, MAX_OUTCOME_STATEMENTS, MAX_OUTCOMES, MAX_OUTCOME_TEXT_CHARS, expectedOutcomeCheck, testDataCheck, sharedAccountCheck, clockLiteralCheck, readinessPollCheck, knownBugTestCheck, bugClaimContractCheck, suspiciousExpectationCheck, bugCandidateCheck, conventionOutcomesCheck, pendingHook, locatorFragmentCheck, FILTER_STEP, NEXT_ACTION, REDUCTION_PROOF, MAX_FILTER_LINES, MAX_FILTER_LINE_CHARS, filterPositiveOnlyCheck, PROMOTION_QUALITY_CHECKS, PROMOTION_GATE_MAX_CODE_CHARS, NOT_EVALUATED, SUSPICIOUS_PASS_TAG, NOT_CONTENT_MATCHER, CONTENT_PROOF, NAMED_ELEMENT, NEEDS_REVIEW_TAG, count2, RECHECKED_NOTES, EVIDENCE_NOTE_PREFIXES, PENDING_RECHECK_NOTE_PREFIXES, STRENGTH_RANK;
|
|
86216
86795
|
var init_promotion_quality_gate = __esm({
|
|
86217
86796
|
"../shared/dist/promotion-quality-gate.js"() {
|
|
86218
86797
|
"use strict";
|
|
@@ -86227,11 +86806,12 @@ var init_promotion_quality_gate = __esm({
|
|
|
86227
86806
|
init_run_classification();
|
|
86228
86807
|
init_expected_outcome_coverage();
|
|
86229
86808
|
init_expect_call();
|
|
86809
|
+
init_trailing_slashes();
|
|
86230
86810
|
SOURCE_RANK = { generator: 0, classifier: 0, healer: 1, human: 2 };
|
|
86231
86811
|
strengthCheck = {
|
|
86232
86812
|
id: "assertion-strength",
|
|
86233
|
-
run({ code, tags, strengthGate, flagContradictedAdditions }) {
|
|
86234
|
-
const verdict = validateAssertionStrength(code, { flagContradictedAdditions: flagContradictedAdditions === true });
|
|
86813
|
+
run({ code, tags, strengthGate, flagContradictedAdditions, lastActionProof }) {
|
|
86814
|
+
const verdict = validateAssertionStrength(code, { flagContradictedAdditions: flagContradictedAdditions === true, lastActionProof });
|
|
86235
86815
|
if (verdict.severity === "route-bug")
|
|
86236
86816
|
return [{ check: "route-bug" }];
|
|
86237
86817
|
const authDowngrade = verdict.severity === "downgrade" && tags.some((t) => t.toLowerCase() === "@auth");
|
|
@@ -86249,7 +86829,7 @@ var init_promotion_quality_gate = __esm({
|
|
|
86249
86829
|
MAX_STATEMENTS = 500;
|
|
86250
86830
|
MAX_STATEMENT_CHARS = 400;
|
|
86251
86831
|
LITERAL_OR_IDENTIFIER = /'(?:[^'\\\n]|\\.){0,500}'|"(?:[^"\\\n]|\\.){0,500}"|`(?:[^`\\]|\\.){0,2000}`|(?<![\w$.])[A-Za-z_$][\w$]{0,60}/g;
|
|
86252
|
-
MUTATING_ACTION = /\.(?:click|dblclick|tap|fill|type|pressSequentially|press|check|uncheck|selectOption|setInputFiles|dragTo|clear)\s{0,20}\(|\brequest\s{0,20}\.\s{0,20}(?:post|put|patch|delete|fetch)\s{0,20}\(/;
|
|
86832
|
+
MUTATING_ACTION = /\.(?:click|dblclick|tap|fill|type|pressSequentially|press|check|uncheck|setChecked|selectOption|setInputFiles|dragTo|dragAndDrop|clear)\s{0,20}\(|\brequest\s{0,20}\.\s{0,20}(?:post|put|patch|delete|fetch)\s{0,20}\(/;
|
|
86253
86833
|
FEEDBACK_REGION = /getByRole\s{0,20}\(\s{0,20}['"`](?:alert|status)['"`]|\baria-live\b|\btoast|\bsnackbar\b|\bflash.?message\b/i;
|
|
86254
86834
|
ONE_SHOT_MESSAGE_REASON = "one-shot success/error banner text";
|
|
86255
86835
|
FEEDBACK_REGION_ALL = /getByRole\s{0,20}\(\s{0,20}['"`](?:alert|status)['"`]|\baria-live\b|\btoast|\bsnackbar\b|\bflash.?message\b/gi;
|
|
@@ -86308,6 +86888,7 @@ var init_promotion_quality_gate = __esm({
|
|
|
86308
86888
|
"element-hidden": /\.(?:toBeHidden|not\s{0,20}\.\s{0,20}toBeVisible|not\s{0,20}\.\s{0,20}toBeAttached|not\s{0,20}\.\s{0,20}toContainText)\s{0,20}\(|\.toHaveCount\s{0,20}\(\s{0,20}0\s{0,20}\)/
|
|
86309
86889
|
};
|
|
86310
86890
|
ROUTE_TERM = /\/[A-Za-z0-9_./?&=#-]{1,200}/g;
|
|
86891
|
+
ROUTE_TRAILING_PUNCTUATION = /[.,;:!?)]/;
|
|
86311
86892
|
QUOTED_LITERAL = /'([^'\\\n]{3,200})'|"([^"\\\n]{3,200})"|`([^`\\$\n]{3,200})`/g;
|
|
86312
86893
|
GENERIC_LITERAL = /^(?:true|false|button|link|heading|dialog|alertdialog|article|main|region|status|alert|textbox|combobox|checkbox|radio|tab|tabpanel|option|list|listitem|row|cell|img|navigation|banner|complementary|contentinfo|form|search|menu|menuitem|visible|hidden|attached|detached|domcontentloaded|load|networkidle)$/i;
|
|
86313
86894
|
MAX_OUTCOME_STATEMENTS = 300;
|
|
@@ -86427,8 +87008,8 @@ ${goalText}`);
|
|
|
86427
87008
|
return count3 > 0 ? [{ check: "locator-fragment", detail: String(count3), soft: true }] : [];
|
|
86428
87009
|
}
|
|
86429
87010
|
};
|
|
86430
|
-
FILTER_STEP = /\.(?:getByLabel|getByPlaceholder|getByRole|getByTitle)\s*\([^)\n]{0,200}?\b(?:filter|sort|search|status|delete|remove|dismiss|archive|clear)\b[^)\n]{0,200}\)[^\n]{0,200}\.(?:selectOption|fill|type|pressSequentially|click|check|uncheck|press)\s*\(/i;
|
|
86431
|
-
NEXT_ACTION = /\.(?:goto|reload|click|dblclick|tap|fill|type|pressSequentially|press|check|uncheck|selectOption|setInputFiles|dragTo|clear)\s*\(/;
|
|
87011
|
+
FILTER_STEP = /\.(?:getByLabel|getByPlaceholder|getByRole|getByTitle)\s*\([^)\n]{0,200}?\b(?:filter|sort|search|status|delete|remove|dismiss|archive|clear)\b[^)\n]{0,200}\)[^\n]{0,200}\.(?:selectOption|fill|type|pressSequentially|click|check|uncheck|setChecked|press)\s*\(/i;
|
|
87012
|
+
NEXT_ACTION = /\.(?:goto|reload|click|dblclick|tap|fill|type|pressSequentially|press|check|uncheck|setChecked|selectOption|setInputFiles|dragTo|dragAndDrop|clear)\s*\(/;
|
|
86432
87013
|
REDUCTION_PROOF = /\.toHaveCount\s*\(|\.not\s*\.\s*(?:toBeVisible|toBeAttached|toContainText|toHaveText)\s*\(|\.toBeHidden\s*\(|\bShowing\b|\bof \d+\b|\b\d+ (?:results?|rows?|items?|candidates?|entries|matches|records)\b|\bNo (?:[\w'-]+ ){0,3}(?:match|matches|results?|found|left|remain|yet)\b|\bNothing (?:to show|found|matches)\b|\bis empty\b|\btoHaveURL\b/i;
|
|
86433
87014
|
MAX_FILTER_LINES = 2e3;
|
|
86434
87015
|
MAX_FILTER_LINE_CHARS = 600;
|
|
@@ -86543,7 +87124,7 @@ ${goalText}`);
|
|
|
86543
87124
|
});
|
|
86544
87125
|
|
|
86545
87126
|
// ../shared/dist/regex-alternation.js
|
|
86546
|
-
function
|
|
87127
|
+
function closingParens2(source) {
|
|
86547
87128
|
const close = new Int32Array(source.length).fill(-1);
|
|
86548
87129
|
const open = [];
|
|
86549
87130
|
let inClass = false;
|
|
@@ -86568,7 +87149,7 @@ function closingParens(source) {
|
|
|
86568
87149
|
return close;
|
|
86569
87150
|
}
|
|
86570
87151
|
function alternatesAtTop(source) {
|
|
86571
|
-
const close =
|
|
87152
|
+
const close = closingParens2(source);
|
|
86572
87153
|
let start = source.startsWith("^") ? 1 : 0;
|
|
86573
87154
|
let end = source.endsWith("$") ? source.length - 1 : source.length;
|
|
86574
87155
|
while (start < end && source[start] === "(" && close[start] === end - 1) {
|
|
@@ -86617,6 +87198,124 @@ var init_page_evidence = __esm({
|
|
|
86617
87198
|
}
|
|
86618
87199
|
});
|
|
86619
87200
|
|
|
87201
|
+
// ../shared/dist/stated-limits.js
|
|
87202
|
+
function validDate(v) {
|
|
87203
|
+
const [y, m, d] = v.split("-").map(Number);
|
|
87204
|
+
const t = new Date(Date.UTC(y, m - 1, d));
|
|
87205
|
+
return t.getUTCFullYear() === y && t.getUTCMonth() === m - 1 && t.getUTCDate() === d;
|
|
87206
|
+
}
|
|
87207
|
+
function isoFor(type, v) {
|
|
87208
|
+
const re = DATE_RE[type];
|
|
87209
|
+
if (!re || !re.test(v))
|
|
87210
|
+
return false;
|
|
87211
|
+
if (type === "date")
|
|
87212
|
+
return validDate(v);
|
|
87213
|
+
if (type === "datetime-local")
|
|
87214
|
+
return validDate(v.slice(0, 10)) && Number(v.slice(11, 13)) < 24 && Number(v.slice(14, 16)) < 60;
|
|
87215
|
+
if (type === "time")
|
|
87216
|
+
return Number(v.slice(0, 2)) < 24 && Number(v.slice(3, 5)) < 60;
|
|
87217
|
+
if (type === "month")
|
|
87218
|
+
return Number(v.slice(5, 7)) >= 1 && Number(v.slice(5, 7)) <= 12;
|
|
87219
|
+
return Number(v.slice(6, 8)) >= 1 && Number(v.slice(6, 8)) <= 53;
|
|
87220
|
+
}
|
|
87221
|
+
function clean2(raw) {
|
|
87222
|
+
return typeof raw === "string" ? raw.trim() : "";
|
|
87223
|
+
}
|
|
87224
|
+
function statedLimitsFromAttrs(attrs, inputType) {
|
|
87225
|
+
const type = (inputType ?? "").trim().toLowerCase();
|
|
87226
|
+
const limits = [];
|
|
87227
|
+
const add = (k, v) => {
|
|
87228
|
+
limits.push({ k, v });
|
|
87229
|
+
};
|
|
87230
|
+
if (NUMBER_TYPES.has(type)) {
|
|
87231
|
+
for (const [attr, k] of [["min", "min"], ["max", "max"]]) {
|
|
87232
|
+
const v = clean2(attrs[attr]);
|
|
87233
|
+
if (NUMBER_RE.test(v))
|
|
87234
|
+
add(k, v);
|
|
87235
|
+
}
|
|
87236
|
+
const step = clean2(attrs.step);
|
|
87237
|
+
if (NUMBER_RE.test(step) && Number(step) > 0)
|
|
87238
|
+
add("step", step);
|
|
87239
|
+
} else if (type in DATE_RE) {
|
|
87240
|
+
for (const [attr, k] of [["min", "min"], ["max", "max"]]) {
|
|
87241
|
+
const v = clean2(attrs[attr]);
|
|
87242
|
+
if (isoFor(type, v))
|
|
87243
|
+
add(k, v);
|
|
87244
|
+
}
|
|
87245
|
+
} else if (TEXT_TYPES.has(type)) {
|
|
87246
|
+
for (const [attr, k] of [["minlength", "minLength"], ["maxlength", "maxLength"]]) {
|
|
87247
|
+
const v = clean2(attrs[attr]);
|
|
87248
|
+
if (LENGTH_RE.test(v))
|
|
87249
|
+
add(k, String(Number(v)));
|
|
87250
|
+
}
|
|
87251
|
+
const pattern = cleanPattern(clean2(attrs.pattern).slice(0, STATED_PATTERN_MAX));
|
|
87252
|
+
if (pattern)
|
|
87253
|
+
add("pattern", pattern);
|
|
87254
|
+
}
|
|
87255
|
+
return limits.length > 0 ? { v: STATED_LIMITS_VERSION, limits } : null;
|
|
87256
|
+
}
|
|
87257
|
+
function cleanPattern(text) {
|
|
87258
|
+
return text.replace(/[\u0000-\u001f\u007f]/g, "").replace(/[\ud800-\udbff](?![\udc00-\udfff])|(?<![\ud800-\udbff])[\udc00-\udfff]/g, "");
|
|
87259
|
+
}
|
|
87260
|
+
function readStatedLimits(stored) {
|
|
87261
|
+
if (!stored || typeof stored !== "object" || Array.isArray(stored))
|
|
87262
|
+
return [];
|
|
87263
|
+
const rec = stored;
|
|
87264
|
+
if (rec.v !== STATED_LIMITS_VERSION || !Array.isArray(rec.limits))
|
|
87265
|
+
return [];
|
|
87266
|
+
const out = [];
|
|
87267
|
+
const seen = /* @__PURE__ */ new Set();
|
|
87268
|
+
for (const item of rec.limits.slice(0, MAX_LIMITS * 2)) {
|
|
87269
|
+
if (!item || typeof item !== "object")
|
|
87270
|
+
continue;
|
|
87271
|
+
const { k, v } = item;
|
|
87272
|
+
if (typeof k !== "string" || typeof v !== "string" || !KINDS.includes(k) || seen.has(k))
|
|
87273
|
+
continue;
|
|
87274
|
+
if (v.length === 0 || v.length > STATED_PATTERN_MAX)
|
|
87275
|
+
continue;
|
|
87276
|
+
const text = k === "pattern" ? cleanPattern(v) : v;
|
|
87277
|
+
if (text === "")
|
|
87278
|
+
continue;
|
|
87279
|
+
if (k === "minLength" || k === "maxLength") {
|
|
87280
|
+
if (!LENGTH_RE.test(v))
|
|
87281
|
+
continue;
|
|
87282
|
+
} else if (k === "step") {
|
|
87283
|
+
if (!NUMBER_RE.test(v))
|
|
87284
|
+
continue;
|
|
87285
|
+
} else if (k === "min" || k === "max") {
|
|
87286
|
+
if (!NUMBER_RE.test(v) && !Object.values(DATE_RE).some((re) => re.test(v)))
|
|
87287
|
+
continue;
|
|
87288
|
+
}
|
|
87289
|
+
seen.add(k);
|
|
87290
|
+
out.push({ k, v: text });
|
|
87291
|
+
}
|
|
87292
|
+
return out;
|
|
87293
|
+
}
|
|
87294
|
+
function statedLimitsRecord(limits) {
|
|
87295
|
+
return limits.length > 0 ? { v: STATED_LIMITS_VERSION, limits } : null;
|
|
87296
|
+
}
|
|
87297
|
+
var STATED_LIMITS_VERSION, STATED_PATTERN_MAX, KINDS, MAX_LIMITS, TEXT_TYPES, NUMBER_TYPES, DATE_RE, NUMBER_RE, LENGTH_RE;
|
|
87298
|
+
var init_stated_limits = __esm({
|
|
87299
|
+
"../shared/dist/stated-limits.js"() {
|
|
87300
|
+
"use strict";
|
|
87301
|
+
STATED_LIMITS_VERSION = 1;
|
|
87302
|
+
STATED_PATTERN_MAX = 200;
|
|
87303
|
+
KINDS = ["min", "max", "minLength", "maxLength", "step", "pattern"];
|
|
87304
|
+
MAX_LIMITS = KINDS.length;
|
|
87305
|
+
TEXT_TYPES = /* @__PURE__ */ new Set(["text", "search", "email", "url", "tel", "password", "textarea", ""]);
|
|
87306
|
+
NUMBER_TYPES = /* @__PURE__ */ new Set(["number", "range"]);
|
|
87307
|
+
DATE_RE = {
|
|
87308
|
+
date: /^\d{4}-\d{2}-\d{2}$/,
|
|
87309
|
+
"datetime-local": /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2})?$/,
|
|
87310
|
+
time: /^\d{2}:\d{2}(?::\d{2})?$/,
|
|
87311
|
+
month: /^\d{4}-\d{2}$/,
|
|
87312
|
+
week: /^\d{4}-W\d{2}$/
|
|
87313
|
+
};
|
|
87314
|
+
NUMBER_RE = /^-?\d{1,15}(?:\.\d{1,10})?$/;
|
|
87315
|
+
LENGTH_RE = /^\d{1,7}$/;
|
|
87316
|
+
}
|
|
87317
|
+
});
|
|
87318
|
+
|
|
86620
87319
|
// ../shared/dist/index.js
|
|
86621
87320
|
var dist_exports = {};
|
|
86622
87321
|
__export(dist_exports, {
|
|
@@ -86624,9 +87323,11 @@ __export(dist_exports, {
|
|
|
86624
87323
|
ACTION_BATCH_MAX_SIZE: () => ACTION_BATCH_MAX_SIZE,
|
|
86625
87324
|
ADDON_DEFINITIONS: () => ADDON_DEFINITIONS,
|
|
86626
87325
|
ADMIN_EMAIL_LIMITS: () => ADMIN_EMAIL_LIMITS,
|
|
87326
|
+
ADMIN_FORCE_CANCELLED_RUN_ERROR: () => ADMIN_FORCE_CANCELLED_RUN_ERROR,
|
|
86627
87327
|
ADMIN_VIEW_DEFAULT_RETURN_TO: () => ADMIN_VIEW_DEFAULT_RETURN_TO,
|
|
86628
87328
|
AGENT_AI_PROVIDER_PREFIXES: () => AGENT_AI_PROVIDER_PREFIXES,
|
|
86629
87329
|
AI_CREDIT_MARGIN: () => AI_CREDIT_MARGIN,
|
|
87330
|
+
ALLOWED_PROVIDER_CHAIN_HOPS: () => ALLOWED_PROVIDER_CHAIN_HOPS,
|
|
86630
87331
|
API_AUTH_HEADERS_ENV_KEY: () => API_AUTH_HEADERS_ENV_KEY,
|
|
86631
87332
|
API_MODEL_CATALOG: () => API_MODEL_CATALOG,
|
|
86632
87333
|
API_MODEL_FIELDS: () => API_MODEL_FIELDS,
|
|
@@ -86666,12 +87367,14 @@ __export(dist_exports, {
|
|
|
86666
87367
|
BUG_TEST_BROKEN_REASON: () => BUG_TEST_BROKEN_REASON,
|
|
86667
87368
|
BUG_TEST_BROKEN_TAG: () => BUG_TEST_BROKEN_TAG,
|
|
86668
87369
|
CACHE_PRICE_PER_M: () => CACHE_PRICE_PER_M,
|
|
87370
|
+
CANCELLED_REASON_PREFIXES: () => CANCELLED_REASON_PREFIXES,
|
|
86669
87371
|
CANVAS_UNSUPPORTED_BODY: () => CANVAS_UNSUPPORTED_BODY,
|
|
86670
87372
|
CANVAS_UNSUPPORTED_CODE: () => CANVAS_UNSUPPORTED_CODE,
|
|
86671
87373
|
CANVAS_UNSUPPORTED_NOT_CHARGED: () => CANVAS_UNSUPPORTED_NOT_CHARGED,
|
|
86672
87374
|
CANVAS_UNSUPPORTED_OVERRIDE_HINT: () => CANVAS_UNSUPPORTED_OVERRIDE_HINT,
|
|
86673
87375
|
CANVAS_UNSUPPORTED_TITLE: () => CANVAS_UNSUPPORTED_TITLE,
|
|
86674
87376
|
CAPTURE_JSON_STRUCTURE_LIMITS: () => CAPTURE_JSON_STRUCTURE_LIMITS,
|
|
87377
|
+
CHAIN_CANCELLED_RUN_ERROR: () => CHAIN_CANCELLED_RUN_ERROR,
|
|
86675
87378
|
CHAT_FAILOVER_KEY: () => CHAT_FAILOVER_KEY,
|
|
86676
87379
|
CLAUDE_CLI_DEFAULT_EFFORT: () => CLAUDE_CLI_DEFAULT_EFFORT,
|
|
86677
87380
|
CLAUDE_CLI_DEFAULT_MODEL: () => CLAUDE_CLI_DEFAULT_MODEL,
|
|
@@ -86708,6 +87411,7 @@ __export(dist_exports, {
|
|
|
86708
87411
|
DEFAULT_GEMINI_SCREEN_MODEL: () => DEFAULT_GEMINI_SCREEN_MODEL,
|
|
86709
87412
|
DEFAULT_JSON_STRUCTURE_LIMITS: () => DEFAULT_JSON_STRUCTURE_LIMITS,
|
|
86710
87413
|
DEFAULT_PLATFORM_DB_POOL_SIZE: () => DEFAULT_PLATFORM_DB_POOL_SIZE,
|
|
87414
|
+
DEFAULT_PROVIDER_ACCOUNT_ID: () => DEFAULT_PROVIDER_ACCOUNT_ID,
|
|
86711
87415
|
DEFAULT_SHARED_DB_POOL_SIZE: () => DEFAULT_SHARED_DB_POOL_SIZE,
|
|
86712
87416
|
DEFAULT_STT_MODEL: () => DEFAULT_STT_MODEL,
|
|
86713
87417
|
DEFAULT_STT_MODEL_BY_PROVIDER: () => DEFAULT_STT_MODEL_BY_PROVIDER,
|
|
@@ -86724,6 +87428,7 @@ __export(dist_exports, {
|
|
|
86724
87428
|
ENVIRONMENTAL_ERROR_STORED_PREFIXES: () => ENVIRONMENTAL_ERROR_STORED_PREFIXES,
|
|
86725
87429
|
EVIDENCE_NOTE_PREFIXES: () => EVIDENCE_NOTE_PREFIXES,
|
|
86726
87430
|
EXPECT_CALL_RE: () => EXPECT_CALL_RE,
|
|
87431
|
+
FEATURE_ROW_RUN_WINDOW: () => FEATURE_ROW_RUN_WINDOW,
|
|
86727
87432
|
FLOW_PHASE_LABELS: () => FLOW_PHASE_LABELS,
|
|
86728
87433
|
FLOW_PHASE_TYPES: () => FLOW_PHASE_TYPES,
|
|
86729
87434
|
FLOW_SERVER_TYPES: () => FLOW_SERVER_TYPES,
|
|
@@ -86791,6 +87496,8 @@ __export(dist_exports, {
|
|
|
86791
87496
|
MAX_ORG_NAME_LENGTH: () => MAX_ORG_NAME_LENGTH,
|
|
86792
87497
|
MAX_PASSWORD_BYTES: () => MAX_PASSWORD_BYTES,
|
|
86793
87498
|
MAX_PLAYWRIGHT_CODE_LENGTH: () => MAX_PLAYWRIGHT_CODE_LENGTH,
|
|
87499
|
+
MAX_PROVIDER_ACCOUNTS: () => MAX_PROVIDER_ACCOUNTS,
|
|
87500
|
+
MAX_PROVIDER_ACCOUNT_MODELS: () => MAX_PROVIDER_ACCOUNT_MODELS,
|
|
86794
87501
|
MAX_SURVEY_ENTRY_URLS: () => MAX_SURVEY_ENTRY_URLS,
|
|
86795
87502
|
MAX_SURVEY_ENTRY_URL_LENGTH: () => MAX_SURVEY_ENTRY_URL_LENGTH,
|
|
86796
87503
|
MCP_ARMY_LIMITS: () => MCP_ARMY_LIMITS,
|
|
@@ -86826,7 +87533,7 @@ __export(dist_exports, {
|
|
|
86826
87533
|
MUSE_ENGINE_DEFAULT_MODEL: () => MUSE_ENGINE_DEFAULT_MODEL,
|
|
86827
87534
|
MUSE_ENGINE_MODELS: () => MUSE_ENGINE_MODELS,
|
|
86828
87535
|
NOREPLY_EMAIL: () => NOREPLY_EMAIL,
|
|
86829
|
-
|
|
87536
|
+
OPENCODE_GO_DEEPSEEK_GLM_MODELS: () => OPENCODE_GO_DEEPSEEK_GLM_MODELS,
|
|
86830
87537
|
OPENCODE_GO_MODEL_PATTERN: () => OPENCODE_GO_MODEL_PATTERN,
|
|
86831
87538
|
OPENCODE_GO_PREFIX: () => OPENCODE_GO_PREFIX,
|
|
86832
87539
|
OPENROUTER_MAX_CALL_COST_USD: () => OPENROUTER_MAX_CALL_COST_USD,
|
|
@@ -86846,10 +87553,12 @@ __export(dist_exports, {
|
|
|
86846
87553
|
PLAN_FEATURES: () => PLAN_FEATURES,
|
|
86847
87554
|
PLAN_FEATURE_LOCKED_CODE: () => PLAN_FEATURE_LOCKED_CODE,
|
|
86848
87555
|
PLAN_ORDER: () => PLAN_ORDER,
|
|
87556
|
+
PLATFORM_ADMIN_CANCELLED_RUN_ERROR: () => PLATFORM_ADMIN_CANCELLED_RUN_ERROR,
|
|
86849
87557
|
PLATFORM_ADMIN_EMAIL: () => PLATFORM_ADMIN_EMAIL,
|
|
86850
87558
|
PLATFORM_DEFAULT_PROVIDER: () => PLATFORM_DEFAULT_PROVIDER,
|
|
86851
87559
|
PLATFORM_PLAN_BILLING: () => PLATFORM_PLAN_BILLING,
|
|
86852
87560
|
PLATFORM_SERVER_APPLICATION_NAME: () => PLATFORM_SERVER_APPLICATION_NAME,
|
|
87561
|
+
PLATFORM_SUPPORT_CANCELLED_RUN_ERROR: () => PLATFORM_SUPPORT_CANCELLED_RUN_ERROR,
|
|
86853
87562
|
POST_SPECIAL_TRIAL_DAYS: () => POST_SPECIAL_TRIAL_DAYS,
|
|
86854
87563
|
PRESET_DIRECT_FALLBACK: () => PRESET_DIRECT_FALLBACK,
|
|
86855
87564
|
PRODUCTION_READ_ONLY_GUARD_TEMPLATE: () => PRODUCTION_READ_ONLY_GUARD_TEMPLATE,
|
|
@@ -86861,8 +87570,12 @@ __export(dist_exports, {
|
|
|
86861
87570
|
PROJECT_OVERRIDE_FIELDS: () => PROJECT_OVERRIDE_FIELDS,
|
|
86862
87571
|
PROMOTION_GATE_MAX_CODE_CHARS: () => PROMOTION_GATE_MAX_CODE_CHARS,
|
|
86863
87572
|
PROMOTION_QUALITY_CHECKS: () => PROMOTION_QUALITY_CHECKS,
|
|
87573
|
+
PROVIDER_ACCOUNT_ID_PATTERN: () => PROVIDER_ACCOUNT_ID_PATTERN,
|
|
87574
|
+
PROVIDER_ACCOUNT_MODEL_PATTERN: () => PROVIDER_ACCOUNT_MODEL_PATTERN,
|
|
86864
87575
|
PROVIDER_CHAINS: () => PROVIDER_CHAINS,
|
|
87576
|
+
PROVIDER_CHAINS_SETTING_MAX_CHARS: () => PROVIDER_CHAINS_SETTING_MAX_CHARS,
|
|
86865
87577
|
PROVIDER_CHAIN_LEADS: () => PROVIDER_CHAIN_LEADS,
|
|
87578
|
+
PROVIDER_CHAIN_MAX_ENTRIES: () => PROVIDER_CHAIN_MAX_ENTRIES,
|
|
86866
87579
|
PROVIDER_HOST_NOT_OFFERED: () => PROVIDER_HOST_NOT_OFFERED,
|
|
86867
87580
|
PUBLIC_PLANS: () => PUBLIC_PLANS,
|
|
86868
87581
|
QUARANTINE_CLOSE_TAGS: () => QUARANTINE_CLOSE_TAGS,
|
|
@@ -86870,10 +87583,12 @@ __export(dist_exports, {
|
|
|
86870
87583
|
READ_ONLY_TAGS: () => READ_ONLY_TAGS,
|
|
86871
87584
|
RECHECKED_NOTES: () => RECHECKED_NOTES,
|
|
86872
87585
|
RECORDING_VALUE_PLACEHOLDERS: () => RECORDING_VALUE_PLACEHOLDERS,
|
|
87586
|
+
RENDER_IDENTITY_MAX_LENGTH: () => RENDER_IDENTITY_MAX_LENGTH,
|
|
86873
87587
|
REPOSITORY_CLIS: () => REPOSITORY_CLIS,
|
|
86874
87588
|
RESERVED_PROJECT_KEYS: () => RESERVED_PROJECT_KEYS,
|
|
86875
87589
|
RESULT_STRUCTURE_TOO_COSTLY_CODE: () => RESULT_STRUCTURE_TOO_COSTLY_CODE,
|
|
86876
87590
|
RETRIED_ATTEMPTS_KEY: () => RETRIED_ATTEMPTS_KEY,
|
|
87591
|
+
RETRY_HELD_RUN_ERROR: () => RETRY_HELD_RUN_ERROR,
|
|
86877
87592
|
RUNNER_INTERRUPT_ERROR_PREFIX: () => RUNNER_INTERRUPT_ERROR_PREFIX,
|
|
86878
87593
|
RUN_INTERRUPTED_ERROR_PREFIXES: () => RUN_INTERRUPTED_ERROR_PREFIXES,
|
|
86879
87594
|
RUN_INTERRUPTION_NOT_RETRIED_MARKERS: () => RUN_INTERRUPTION_NOT_RETRIED_MARKERS,
|
|
@@ -86886,6 +87601,8 @@ __export(dist_exports, {
|
|
|
86886
87601
|
SHARED_SERVER_APPLICATION_NAME: () => SHARED_SERVER_APPLICATION_NAME,
|
|
86887
87602
|
SPEND_SOURCE_KEY: () => SPEND_SOURCE_KEY,
|
|
86888
87603
|
SPEND_SOURCE_SERVER: () => SPEND_SOURCE_SERVER,
|
|
87604
|
+
STATED_LIMITS_VERSION: () => STATED_LIMITS_VERSION,
|
|
87605
|
+
STATED_PATTERN_MAX: () => STATED_PATTERN_MAX,
|
|
86889
87606
|
STATIC_STANDARD_MIN_INTERACTIVE: () => STATIC_STANDARD_MIN_INTERACTIVE,
|
|
86890
87607
|
STT_MODEL_OPTIONS: () => STT_MODEL_OPTIONS,
|
|
86891
87608
|
SUCCESS_NOTICE_TEXT: () => SUCCESS_NOTICE_TEXT,
|
|
@@ -86915,14 +87632,20 @@ __export(dist_exports, {
|
|
|
86915
87632
|
UI_VARIANTS: () => UI_VARIANTS,
|
|
86916
87633
|
UNEXPECTED_PASS_ERROR_PREFIX: () => UNEXPECTED_PASS_ERROR_PREFIX,
|
|
86917
87634
|
USER_CANCELLED_RUN_ERROR: () => USER_CANCELLED_RUN_ERROR,
|
|
87635
|
+
VISUAL_MASK_SELECTORS_MAX: () => VISUAL_MASK_SELECTORS_MAX,
|
|
87636
|
+
VISUAL_MASK_SELECTOR_FORBIDDEN: () => VISUAL_MASK_SELECTOR_FORBIDDEN,
|
|
87637
|
+
VISUAL_MASK_SELECTOR_MAX_LENGTH: () => VISUAL_MASK_SELECTOR_MAX_LENGTH,
|
|
87638
|
+
VISUAL_V1_IDENTITY: () => VISUAL_V1_IDENTITY,
|
|
86918
87639
|
VOICE_PREVIEW_SAMPLE: () => VOICE_PREVIEW_SAMPLE,
|
|
86919
87640
|
WEB_PROXY_CHAIN_HEADER: () => WEB_PROXY_CHAIN_HEADER,
|
|
86920
87641
|
WITHHELD_CREDENTIAL_TEXT: () => WITHHELD_CREDENTIAL_TEXT,
|
|
86921
87642
|
ZAI_MODEL_PATTERN: () => ZAI_MODEL_PATTERN,
|
|
86922
87643
|
ZAI_PREFIX: () => ZAI_PREFIX,
|
|
87644
|
+
accountServesModel: () => accountServesModel,
|
|
86923
87645
|
accumulateStatements: () => accumulateStatements,
|
|
86924
87646
|
adoptBrokerFailover: () => adoptBrokerFailover,
|
|
86925
87647
|
aiCostToCreditCents: () => aiCostToCreditCents,
|
|
87648
|
+
allowedProviderChainHosts: () => allowedProviderChainHosts,
|
|
86926
87649
|
alternatesAtTop: () => alternatesAtTop,
|
|
86927
87650
|
analyzeDerivedValues: () => analyzeDerivedValues,
|
|
86928
87651
|
analyzeMobileSelectorQuality: () => analyzeMobileSelectorQuality,
|
|
@@ -86935,6 +87658,7 @@ __export(dist_exports, {
|
|
|
86935
87658
|
analyzeUnreachedUrlWaits: () => analyzeUnreachedUrlWaits,
|
|
86936
87659
|
analyzeUrlWaits: () => analyzeUrlWaits,
|
|
86937
87660
|
analyzeWriteResponse: () => analyzeWriteResponse,
|
|
87661
|
+
androidResourceOwners: () => androidResourceOwners,
|
|
86938
87662
|
apiModelCardsFromConfig: () => apiModelCardsFromConfig,
|
|
86939
87663
|
apiModelsForProvider: () => apiModelsForProvider,
|
|
86940
87664
|
apiProviderModelLabel: () => apiProviderModelLabel,
|
|
@@ -86945,6 +87669,7 @@ __export(dist_exports, {
|
|
|
86945
87669
|
applyLaunchSpecialPlan: () => applyLaunchSpecialPlan,
|
|
86946
87670
|
asPlainExpect: () => asPlainExpect,
|
|
86947
87671
|
assertionOnlyCode: () => assertionOnlyCode,
|
|
87672
|
+
assertionStrengthHoistedReadsOn: () => assertionStrengthHoistedReadsOn,
|
|
86948
87673
|
assertionsReadVisibleContent: () => assertionsReadVisibleContent,
|
|
86949
87674
|
assessCodeOutcomeCoverage: () => assessCodeOutcomeCoverage,
|
|
86950
87675
|
assessTitleCoverage: () => assessTitleCoverage,
|
|
@@ -87028,6 +87753,7 @@ __export(dist_exports, {
|
|
|
87028
87753
|
deepgramSpeak: () => deepgramSpeak,
|
|
87029
87754
|
deepgramTranscribe: () => deepgramTranscribe,
|
|
87030
87755
|
defaultConfirmModel: () => defaultConfirmModel,
|
|
87756
|
+
defaultProviderChainEntries: () => defaultProviderChainEntries,
|
|
87031
87757
|
defaultScreenModel: () => defaultScreenModel,
|
|
87032
87758
|
defaultVoiceForTtsModel: () => defaultVoiceForTtsModel,
|
|
87033
87759
|
deriveAuthPlan: () => deriveAuthPlan,
|
|
@@ -87070,6 +87796,7 @@ __export(dist_exports, {
|
|
|
87070
87796
|
extractOutcomeSearchTerms: () => extractOutcomeSearchTerms,
|
|
87071
87797
|
featureForAiCallType: () => featureForAiCallType,
|
|
87072
87798
|
featureForMcpTool: () => featureForMcpTool,
|
|
87799
|
+
featureRowRunStatus: () => featureRowRunStatus,
|
|
87073
87800
|
findBracedClause: () => findBracedClause,
|
|
87074
87801
|
findCounterIdPins: () => findCounterIdPins,
|
|
87075
87802
|
findCredentialTextLeftover: () => findCredentialTextLeftover,
|
|
@@ -87118,6 +87845,7 @@ __export(dist_exports, {
|
|
|
87118
87845
|
getPlanChangeType: () => getPlanChangeType,
|
|
87119
87846
|
getPlanDefinition: () => getPlanDefinition,
|
|
87120
87847
|
getPlanLabel: () => getPlanLabel,
|
|
87848
|
+
getProviderChainOverrides: () => getProviderChainOverrides,
|
|
87121
87849
|
getTrialDaysRemaining: () => getTrialDaysRemaining,
|
|
87122
87850
|
googleBrokerNavigationUrl: () => googleBrokerNavigationUrl,
|
|
87123
87851
|
googleBrokerUnavailableLine: () => googleBrokerUnavailableLine,
|
|
@@ -87131,10 +87859,10 @@ __export(dist_exports, {
|
|
|
87131
87859
|
hasEncodedRequestBody: () => hasEncodedRequestBody,
|
|
87132
87860
|
hasEngineSpecParts: () => hasEngineSpecParts,
|
|
87133
87861
|
hasOnlyConstantAssertions: () => hasOnlyConstantAssertions,
|
|
87134
|
-
hasOpenCodeGo2Prefix: () => hasOpenCodeGo2Prefix,
|
|
87135
87862
|
hasOpenCodeGoPrefix: () => hasOpenCodeGoPrefix,
|
|
87136
87863
|
hasOpenRouterPrefix: () => hasOpenRouterPrefix,
|
|
87137
87864
|
hasPlatformLocator: () => hasPlatformLocator,
|
|
87865
|
+
hasProviderChainLeadsByDefault: () => hasProviderChainLeadsByDefault,
|
|
87138
87866
|
hasReadOnlyMarker: () => hasReadOnlyMarker,
|
|
87139
87867
|
hasSurveyNotes: () => hasSurveyNotes,
|
|
87140
87868
|
hasTestFailContract: () => hasTestFailContract,
|
|
@@ -87160,8 +87888,11 @@ __export(dist_exports, {
|
|
|
87160
87888
|
isAuthTokenName: () => isAuthTokenName,
|
|
87161
87889
|
isBlockedEnvVar: () => isBlockedEnvVar,
|
|
87162
87890
|
isBrowserCliEngine: () => isBrowserCliEngine,
|
|
87891
|
+
isBrowserVersion: () => isBrowserVersion,
|
|
87163
87892
|
isBugTestBrokenError: () => isBugTestBrokenError,
|
|
87893
|
+
isCancelledReason: () => isCancelledReason,
|
|
87164
87894
|
isCanvasUnsupportedMessage: () => isCanvasUnsupportedMessage,
|
|
87895
|
+
isChainablePrimary: () => isChainablePrimary,
|
|
87165
87896
|
isCliEngineModelId: () => isCliEngineModelId,
|
|
87166
87897
|
isCliEngineSpec: () => isCliEngineSpec,
|
|
87167
87898
|
isCodeFactNote: () => isCodeFactNote,
|
|
@@ -87185,6 +87916,7 @@ __export(dist_exports, {
|
|
|
87185
87916
|
isIdentityMobileXpath: () => isIdentityMobileXpath,
|
|
87186
87917
|
isIdentityProviderSurface: () => isIdentityProviderSurface,
|
|
87187
87918
|
isIncidentalAssetPath: () => isIncidentalAssetPath,
|
|
87919
|
+
isIntentionalNegativeAuthTest: () => isIntentionalNegativeAuthTest,
|
|
87188
87920
|
isIpOrLocalhost: () => isIpOrLocalhost,
|
|
87189
87921
|
isKnownPageType: () => isKnownPageType,
|
|
87190
87922
|
isLaunchSpecialActive: () => isLaunchSpecialActive,
|
|
@@ -87212,6 +87944,7 @@ __export(dist_exports, {
|
|
|
87212
87944
|
isRunInterruptedError: () => isRunInterruptedError,
|
|
87213
87945
|
isRunnableStep: () => isRunnableStep,
|
|
87214
87946
|
isSafeDeepLink: () => isSafeDeepLink,
|
|
87947
|
+
isSafeMaskSelector: () => isSafeMaskSelector,
|
|
87215
87948
|
isSameRegistrableDomainHost: () => isSameRegistrableDomainHost,
|
|
87216
87949
|
isSelectableApiModel: () => isSelectableApiModel,
|
|
87217
87950
|
isSelfServePlan: () => isSelfServePlan,
|
|
@@ -87275,6 +88008,7 @@ __export(dist_exports, {
|
|
|
87275
88008
|
normalizeFinishReason: () => normalizeFinishReason,
|
|
87276
88009
|
normalizeNoteText: () => normalizeNoteText,
|
|
87277
88010
|
normalizePageType: () => normalizePageType,
|
|
88011
|
+
normalizeProviderAccountModels: () => normalizeProviderAccountModels,
|
|
87278
88012
|
normalizeTtsModel: () => normalizeTtsModel,
|
|
87279
88013
|
normalizeTtsVoiceId: () => normalizeTtsVoiceId,
|
|
87280
88014
|
noteChatFailover: () => noteChatFailover,
|
|
@@ -87299,13 +88033,18 @@ __export(dist_exports, {
|
|
|
87299
88033
|
parseGeminiModelsPayload: () => parseGeminiModelsPayload,
|
|
87300
88034
|
parseGoogleAuthorizeUrl: () => parseGoogleAuthorizeUrl,
|
|
87301
88035
|
parseGoogleGisRequestUrl: () => parseGoogleGisRequestUrl,
|
|
88036
|
+
parseLastActionProofMode: () => parseLastActionProofMode,
|
|
87302
88037
|
parseLimitParam: () => parseLimitParam,
|
|
87303
88038
|
parseOffsetParam: () => parseOffsetParam,
|
|
87304
88039
|
parsePageParam: () => parsePageParam,
|
|
87305
88040
|
parsePgIntSetting: () => parsePgIntSetting,
|
|
87306
88041
|
parseProjectEngineOverrides: () => parseProjectEngineOverrides,
|
|
87307
88042
|
parsePromotionGateMode: () => parsePromotionGateMode,
|
|
88043
|
+
parseProviderAccountLists: () => parseProviderAccountLists,
|
|
88044
|
+
parseProviderChainOverrides: () => parseProviderChainOverrides,
|
|
87308
88045
|
parseRecheckClearMode: () => parseRecheckClearMode,
|
|
88046
|
+
parseRenderIdentity: () => parseRenderIdentity,
|
|
88047
|
+
parseStoredProviderChainOverrides: () => parseStoredProviderChainOverrides,
|
|
87309
88048
|
parseSurveyEntryUrls: () => parseSurveyEntryUrls,
|
|
87310
88049
|
parseSuspiciousPassMode: () => parseSuspiciousPassMode,
|
|
87311
88050
|
parseTaskModelUpdate: () => parseTaskModelUpdate,
|
|
@@ -87336,7 +88075,9 @@ __export(dist_exports, {
|
|
|
87336
88075
|
projectAppHosts: () => projectAppHosts,
|
|
87337
88076
|
providerChainFor: () => providerChainFor,
|
|
87338
88077
|
providerChainHostOf: () => providerChainHostOf,
|
|
88078
|
+
providerChainHostProvider: () => providerChainHostProvider,
|
|
87339
88079
|
providerChainLeadsFor: () => providerChainLeadsFor,
|
|
88080
|
+
providerChainModelKey: () => providerChainModelKey,
|
|
87340
88081
|
providerChainPrimariesForHop: () => providerChainPrimariesForHop,
|
|
87341
88082
|
providerHostPlan: () => providerHostPlan,
|
|
87342
88083
|
readBalanced: () => readBalanced,
|
|
@@ -87346,6 +88087,7 @@ __export(dist_exports, {
|
|
|
87346
88087
|
readEnabledEngines: () => readEnabledEngines,
|
|
87347
88088
|
readProjectEngineOverrides: () => readProjectEngineOverrides,
|
|
87348
88089
|
readRetriedAttempts: () => readRetriedAttempts,
|
|
88090
|
+
readStatedLimits: () => readStatedLimits,
|
|
87349
88091
|
readStaticPageCanvasSignals: () => readStaticPageCanvasSignals,
|
|
87350
88092
|
readSurveyEntryUrls: () => readSurveyEntryUrls,
|
|
87351
88093
|
readSurveyNotes: () => readSurveyNotes,
|
|
@@ -87358,6 +88100,7 @@ __export(dist_exports, {
|
|
|
87358
88100
|
regexLiteralEnd: () => regexLiteralEnd2,
|
|
87359
88101
|
regexOpensAfter: () => regexOpensAfter,
|
|
87360
88102
|
registrableDomain: () => registrableDomain,
|
|
88103
|
+
renderIdentity: () => renderIdentity,
|
|
87361
88104
|
renderSurveyNotesForPrompt: () => renderSurveyNotesForPrompt,
|
|
87362
88105
|
repairPageType: () => repairPageType,
|
|
87363
88106
|
replaceBlockComments: () => replaceBlockComments,
|
|
@@ -87405,11 +88148,14 @@ __export(dist_exports, {
|
|
|
87405
88148
|
selectorCandidatesForStep: () => selectorCandidatesForStep,
|
|
87406
88149
|
selectorForValue: () => selectorForValue,
|
|
87407
88150
|
setAgenticCliRuntime: () => setAgenticCliRuntime,
|
|
88151
|
+
setProviderChainOverrides: () => setProviderChainOverrides,
|
|
87408
88152
|
signupPlanFor: () => signupPlanFor,
|
|
87409
88153
|
simplifyMobileWanderingInPlace: () => simplifyMobileWanderingInPlace,
|
|
87410
88154
|
siteOf: () => siteOf,
|
|
87411
88155
|
specItemsFromTestPlans: () => specItemsFromTestPlans,
|
|
87412
88156
|
splitAnswerLines: () => splitAnswerLines,
|
|
88157
|
+
statedLimitsFromAttrs: () => statedLimitsFromAttrs,
|
|
88158
|
+
statedLimitsRecord: () => statedLimitsRecord,
|
|
87413
88159
|
stepAppliesToPlatform: () => stepAppliesToPlatform,
|
|
87414
88160
|
stepConsoleLines: () => stepConsoleLines,
|
|
87415
88161
|
stepIsDivergentForPlatform: () => stepIsDivergentForPlatform,
|
|
@@ -87421,7 +88167,10 @@ __export(dist_exports, {
|
|
|
87421
88167
|
stripCodeFactPrefix: () => stripCodeFactPrefix,
|
|
87422
88168
|
stripCoverageComments: () => stripCoverageComments,
|
|
87423
88169
|
stripEnvironmentalPrefix: () => stripEnvironmentalPrefix,
|
|
88170
|
+
stripFractionZeros: () => stripFractionZeros,
|
|
88171
|
+
stripLineComment: () => stripLineComment,
|
|
87424
88172
|
stripLoginScaffolding: () => stripLoginScaffolding,
|
|
88173
|
+
stripTrailingChars: () => stripTrailingChars,
|
|
87425
88174
|
stripTrailingSlashes: () => stripTrailingSlashes,
|
|
87426
88175
|
strongerNeedsReviewSource: () => strongerNeedsReviewSource,
|
|
87427
88176
|
sttModelsForProvider: () => sttModelsForProvider,
|
|
@@ -87439,10 +88188,14 @@ __export(dist_exports, {
|
|
|
87439
88188
|
ttsFallbackModel: () => ttsFallbackModel,
|
|
87440
88189
|
ttsProviderForModel: () => ttsProviderForModel,
|
|
87441
88190
|
unexpectedPassError: () => unexpectedPassError,
|
|
88191
|
+
v1RenderIdentity: () => v1RenderIdentity,
|
|
87442
88192
|
validateAppMapDocument: () => validateAppMapDocument,
|
|
87443
88193
|
validateAssertionStrength: () => validateAssertionStrength,
|
|
87444
88194
|
validateEngineSpec: () => validateEngineSpec,
|
|
88195
|
+
validateProviderChainEntries: () => validateProviderChainEntries,
|
|
88196
|
+
validateProviderChainsSetting: () => validateProviderChainsSetting,
|
|
87445
88197
|
validateTaskModelId: () => validateTaskModelId,
|
|
88198
|
+
visualBaselinesEnabled: () => visualBaselinesEnabled,
|
|
87446
88199
|
visualProDailyBudget: () => visualProDailyBudget,
|
|
87447
88200
|
voiceMatchesTtsModel: () => voiceMatchesTtsModel,
|
|
87448
88201
|
voicesForTtsModel: () => voicesForTtsModel,
|
|
@@ -87505,11 +88258,14 @@ var init_dist = __esm({
|
|
|
87505
88258
|
init_deepgram_voices();
|
|
87506
88259
|
init_feature_flags();
|
|
87507
88260
|
init_env_flags();
|
|
88261
|
+
init_visual_compare_limits();
|
|
88262
|
+
init_visual_baseline_identity();
|
|
87508
88263
|
init_analytics_url();
|
|
87509
88264
|
init_agentic_cli_runtime();
|
|
87510
88265
|
init_api_model_catalog();
|
|
87511
88266
|
init_engine_spec();
|
|
87512
88267
|
init_provider_chains();
|
|
88268
|
+
init_provider_accounts();
|
|
87513
88269
|
init_project_engine_overrides();
|
|
87514
88270
|
init_ai_profiles();
|
|
87515
88271
|
init_openrouter_usage();
|
|
@@ -87551,6 +88307,224 @@ var init_dist = __esm({
|
|
|
87551
88307
|
init_regex_alternation();
|
|
87552
88308
|
init_page_evidence();
|
|
87553
88309
|
init_trailing_slashes();
|
|
88310
|
+
init_stated_limits();
|
|
88311
|
+
}
|
|
88312
|
+
});
|
|
88313
|
+
|
|
88314
|
+
// ../runner-core/dist/services/harness-init-script.js
|
|
88315
|
+
var require_harness_init_script = __commonJS({
|
|
88316
|
+
"../runner-core/dist/services/harness-init-script.js"(exports2) {
|
|
88317
|
+
"use strict";
|
|
88318
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
88319
|
+
exports2.HARNESS_INIT_SOURCE_URL = void 0;
|
|
88320
|
+
exports2.withHarnessSourceUrl = withHarnessSourceUrl;
|
|
88321
|
+
exports2.buildAnimationDisablingSource = buildAnimationDisablingSource;
|
|
88322
|
+
exports2.isHarnessInitLocation = isHarnessInitLocation;
|
|
88323
|
+
exports2.isHarnessInitErrorStack = isHarnessInitErrorStack;
|
|
88324
|
+
exports2.isHarnessInitConsoleLine = isHarnessInitConsoleLine;
|
|
88325
|
+
exports2.stripHarnessConsoleEntries = stripHarnessConsoleEntries;
|
|
88326
|
+
var node_crypto_1 = require("crypto");
|
|
88327
|
+
var shared_1 = (init_dist(), __toCommonJS(dist_exports));
|
|
88328
|
+
exports2.HARNESS_INIT_SOURCE_URL = `vqa-harness-init-${(0, node_crypto_1.randomBytes)(4).toString("hex")}.js`;
|
|
88329
|
+
var TRANSITION_LOOP_LIMIT = 8;
|
|
88330
|
+
var TRANSITION_LOOP_WINDOW_MS = 1e3;
|
|
88331
|
+
function withHarnessSourceUrl(content) {
|
|
88332
|
+
return `${content}
|
|
88333
|
+
//# sourceURL=${exports2.HARNESS_INIT_SOURCE_URL}`;
|
|
88334
|
+
}
|
|
88335
|
+
function buildAnimationDisablingSource(opts) {
|
|
88336
|
+
const finishTransitions = opts.finishTransitions ?? (0, shared_1.parseBoolFlag)(process.env.HARNESS_FINISH_CSS_TRANSITIONS);
|
|
88337
|
+
const css = finishTransitions ? "*, *::before, *::after { animation-duration: 0s !important; animation-delay: 0s !important; }" : "*, *::before, *::after { transition-duration: 0s !important; animation-duration: 0s !important; transition-delay: 0s !important; animation-delay: 0s !important; }";
|
|
88338
|
+
return withHarnessSourceUrl(`(() => {
|
|
88339
|
+
// Layer 1: CSS transitions and animations - instant, not removed
|
|
88340
|
+
// (duration 0s preserves final state; 'none' would prevent keyframes from completing)
|
|
88341
|
+
// The rule goes in a constructed stylesheet on document.adoptedStyleSheets, which adds no node to the DOM:
|
|
88342
|
+
// a <style> element changed what the test sees (locator('style') and 'head > *' counts, document.styleSheets,
|
|
88343
|
+
// an iframe's empty head), so a spec stock Playwright passes failed. The <style> is the fallback for a
|
|
88344
|
+
// browser with no constructable stylesheets.
|
|
88345
|
+
let adopted = false;
|
|
88346
|
+
try {
|
|
88347
|
+
if (typeof CSSStyleSheet === 'function' && typeof Document === 'function' && 'adoptedStyleSheets' in Document.prototype) {
|
|
88348
|
+
const sheet = new CSSStyleSheet();
|
|
88349
|
+
sheet.replaceSync(${JSON.stringify(css)});
|
|
88350
|
+
document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];
|
|
88351
|
+
adopted = true;
|
|
88352
|
+
}
|
|
88353
|
+
} catch (e) {}
|
|
88354
|
+
if (!adopted) try {
|
|
88355
|
+
let applied = false;
|
|
88356
|
+
const apply = () => {
|
|
88357
|
+
if (applied) return true;
|
|
88358
|
+
const root = document.head || document.documentElement;
|
|
88359
|
+
if (!root) return false;
|
|
88360
|
+
const style = document.createElement('style');
|
|
88361
|
+
style.textContent = ${JSON.stringify(css)};
|
|
88362
|
+
root.appendChild(style);
|
|
88363
|
+
applied = true;
|
|
88364
|
+
return true;
|
|
88365
|
+
};
|
|
88366
|
+
if (!apply()) {
|
|
88367
|
+
// The document has no root element yet (iframe, about:blank, empty document): wait for it.
|
|
88368
|
+
let observer = null;
|
|
88369
|
+
const stop = () => { try { if (observer) observer.disconnect(); } catch (e) {} };
|
|
88370
|
+
const retry = () => { try { if (apply()) stop(); } catch (e) { stop(); } };
|
|
88371
|
+
try {
|
|
88372
|
+
observer = new MutationObserver(retry);
|
|
88373
|
+
observer.observe(document, { childList: true });
|
|
88374
|
+
} catch (e) {}
|
|
88375
|
+
document.addEventListener('readystatechange', retry);
|
|
88376
|
+
document.addEventListener('DOMContentLoaded', () => { retry(); stop(); }, { once: true });
|
|
88377
|
+
}
|
|
88378
|
+
} catch (e) {}
|
|
88379
|
+
${opts.hideWebdriver ? `
|
|
88380
|
+
try {
|
|
88381
|
+
Object.defineProperty(navigator, 'webdriver', { get: () => undefined });
|
|
88382
|
+
} catch (e) {}
|
|
88383
|
+
` : ""}
|
|
88384
|
+
${finishTransitions ? `
|
|
88385
|
+
// Layer 1b: CSS transitions run, and are finished as they start, so transitionend fires.
|
|
88386
|
+
// - finish() is deferred to a task: called inside the transitionrun dispatch (or a microtask of it) after a
|
|
88387
|
+
// real input event, Chromium finishes the transition but never fires its transitionstart/transitionend.
|
|
88388
|
+
// - setTimeout and performance.now are the ones present when this script runs, before the page's own
|
|
88389
|
+
// scripts: fake timers the page installs later cannot hold a finish back.
|
|
88390
|
+
// - The subtree is walked only for a pseudo-element's transition (its animations hang off the element).
|
|
88391
|
+
// - An element whose same transition restarts more than ${TRANSITION_LOOP_LIMIT} times within ${TRANSITION_LOOP_WINDOW_MS} ms (an app that starts it again on
|
|
88392
|
+
// each transitionend: carousel, pulse) is left to run at its own pace from then on, instead of cycling at
|
|
88393
|
+
// frame rate for the rest of the run.
|
|
88394
|
+
try {
|
|
88395
|
+
const st = setTimeout;
|
|
88396
|
+
const perf = typeof performance === 'object' && performance && typeof performance.now === 'function' ? performance : null;
|
|
88397
|
+
const now = perf ? perf.now.bind(perf) : Date.now;
|
|
88398
|
+
const seen = new WeakMap();
|
|
88399
|
+
const looping = (el, key) => {
|
|
88400
|
+
let byKey = seen.get(el);
|
|
88401
|
+
if (!byKey) { byKey = new Map(); seen.set(el, byKey); }
|
|
88402
|
+
const t = now();
|
|
88403
|
+
let s = byKey.get(key);
|
|
88404
|
+
if (s && s.loop) return true;
|
|
88405
|
+
if (!s || t - s.since > ${TRANSITION_LOOP_WINDOW_MS}) { s = { n: 0, since: t, loop: false }; byKey.set(key, s); }
|
|
88406
|
+
s.n += 1;
|
|
88407
|
+
if (s.n > ${TRANSITION_LOOP_LIMIT}) s.loop = true;
|
|
88408
|
+
return s.loop;
|
|
88409
|
+
};
|
|
88410
|
+
window.addEventListener('transitionrun', (ev) => {
|
|
88411
|
+
try {
|
|
88412
|
+
const el = ev && ev.target;
|
|
88413
|
+
if (!el || typeof el.getAnimations !== 'function' || typeof CSSTransition !== 'function') return;
|
|
88414
|
+
const pseudo = ev.pseudoElement || '';
|
|
88415
|
+
if (looping(el, ev.propertyName + '|' + pseudo)) return;
|
|
88416
|
+
for (const a of (pseudo ? el.getAnimations({ subtree: true }) : el.getAnimations())) {
|
|
88417
|
+
if (a instanceof CSSTransition && a.transitionProperty === ev.propertyName && a.effect
|
|
88418
|
+
&& a.effect.target === el && (a.effect.pseudoElement || '') === pseudo) {
|
|
88419
|
+
st(() => { try { a.finish(); } catch (e) {} }, 0);
|
|
88420
|
+
}
|
|
88421
|
+
}
|
|
88422
|
+
} catch (e) {}
|
|
88423
|
+
}, true);
|
|
88424
|
+
} catch (e) {}
|
|
88425
|
+
` : ""}
|
|
88426
|
+
// Layer 2: Web Animations API - make instant instead of no-op
|
|
88427
|
+
// (preserves animation completion callbacks that app code may depend on)
|
|
88428
|
+
try {
|
|
88429
|
+
const origAnimate = Element.prototype.animate;
|
|
88430
|
+
if (typeof origAnimate === 'function') {
|
|
88431
|
+
Element.prototype.animate = function (keyframes, options) {
|
|
88432
|
+
if (typeof options === 'object' && options !== null) {
|
|
88433
|
+
options = Object.assign({}, options, { duration: 0, delay: 0 });
|
|
88434
|
+
} else {
|
|
88435
|
+
options = 0; // covers number, undefined, and any other type
|
|
88436
|
+
}
|
|
88437
|
+
return origAnimate.call(this, keyframes, options);
|
|
88438
|
+
};
|
|
88439
|
+
}
|
|
88440
|
+
} catch (e) {}
|
|
88441
|
+
})();`);
|
|
88442
|
+
}
|
|
88443
|
+
function isHarnessInitLocation(url) {
|
|
88444
|
+
return url === exports2.HARNESS_INIT_SOURCE_URL;
|
|
88445
|
+
}
|
|
88446
|
+
var MAX_MATCHED_LINE_CHARS = 2048;
|
|
88447
|
+
var MAX_SCANNED_LINES = 200;
|
|
88448
|
+
var STACK_FRAME_RE = /^\s*at\s+(?:[^()\s][^()]*\()?([^()\s]+):\d+:\d+\)?\s*$/;
|
|
88449
|
+
function isHarnessInitErrorStack(stack) {
|
|
88450
|
+
if (!stack)
|
|
88451
|
+
return false;
|
|
88452
|
+
const lines = stack.split("\n", MAX_SCANNED_LINES);
|
|
88453
|
+
for (const line of lines) {
|
|
88454
|
+
if (line.length > MAX_MATCHED_LINE_CHARS)
|
|
88455
|
+
continue;
|
|
88456
|
+
const match = STACK_FRAME_RE.exec(line);
|
|
88457
|
+
if (match)
|
|
88458
|
+
return match[1] === exports2.HARNESS_INIT_SOURCE_URL;
|
|
88459
|
+
}
|
|
88460
|
+
return false;
|
|
88461
|
+
}
|
|
88462
|
+
var MCP_CONSOLE_LINE_LOCATION_RE = / @ ([^\s@]+):\d+$/;
|
|
88463
|
+
function isHarnessInitConsoleLine(line) {
|
|
88464
|
+
const trimmed = line.trim();
|
|
88465
|
+
if (trimmed.length > MAX_MATCHED_LINE_CHARS)
|
|
88466
|
+
return false;
|
|
88467
|
+
const match = MCP_CONSOLE_LINE_LOCATION_RE.exec(trimmed);
|
|
88468
|
+
return match !== null && match[1] === exports2.HARNESS_INIT_SOURCE_URL;
|
|
88469
|
+
}
|
|
88470
|
+
var MCP_LEVEL_LINE_RE = /^\s*(?:-\s+)?\[([A-Za-z]+)\]/;
|
|
88471
|
+
var MCP_FRAME_LINE_RE = /^\s+at\s/;
|
|
88472
|
+
var MCP_TOTALS_RE = /^(\s*Total messages:\s*)(\d+)(\s*\(Errors:\s*)(\d+)(,\s*Warnings:\s*)(\d+)(\).*)$/;
|
|
88473
|
+
var MCP_RETURNING_RE = /^(\s*Returning\s+)(\d+)(\s+messages\b.*)$/;
|
|
88474
|
+
function stripHarnessConsoleEntries(text) {
|
|
88475
|
+
if (!text.includes(exports2.HARNESS_INIT_SOURCE_URL))
|
|
88476
|
+
return text;
|
|
88477
|
+
const lines = text.split("\n");
|
|
88478
|
+
const out = [];
|
|
88479
|
+
let removed = 0;
|
|
88480
|
+
let removedErrors = 0;
|
|
88481
|
+
let removedWarnings = 0;
|
|
88482
|
+
let i = 0;
|
|
88483
|
+
while (i < lines.length) {
|
|
88484
|
+
const line = lines[i];
|
|
88485
|
+
const level = MCP_LEVEL_LINE_RE.exec(line);
|
|
88486
|
+
if (level && isHarnessInitConsoleLine(line.replace(/^\s*-\s+/, ""))) {
|
|
88487
|
+
removed++;
|
|
88488
|
+
const kind = level[1].toLowerCase();
|
|
88489
|
+
if (kind === "error")
|
|
88490
|
+
removedErrors++;
|
|
88491
|
+
else if (kind === "warning" || kind === "warn")
|
|
88492
|
+
removedWarnings++;
|
|
88493
|
+
i++;
|
|
88494
|
+
continue;
|
|
88495
|
+
}
|
|
88496
|
+
if (MCP_FRAME_LINE_RE.test(line)) {
|
|
88497
|
+
let end = i;
|
|
88498
|
+
while (end < lines.length && MCP_FRAME_LINE_RE.test(lines[end]))
|
|
88499
|
+
end++;
|
|
88500
|
+
const frames = lines.slice(i, end);
|
|
88501
|
+
if (isHarnessInitErrorStack(frames.join("\n"))) {
|
|
88502
|
+
const previous = out[out.length - 1];
|
|
88503
|
+
if (previous !== void 0 && previous.trim() !== "" && !/^\s*(?:#|Total messages|Returning)/.test(previous) && !MCP_LEVEL_LINE_RE.test(previous))
|
|
88504
|
+
out.pop();
|
|
88505
|
+
removed++;
|
|
88506
|
+
removedErrors++;
|
|
88507
|
+
} else {
|
|
88508
|
+
out.push(...frames);
|
|
88509
|
+
}
|
|
88510
|
+
i = end;
|
|
88511
|
+
continue;
|
|
88512
|
+
}
|
|
88513
|
+
out.push(line);
|
|
88514
|
+
i++;
|
|
88515
|
+
}
|
|
88516
|
+
if (removed === 0)
|
|
88517
|
+
return text;
|
|
88518
|
+
return out.map((line) => {
|
|
88519
|
+
const totals = MCP_TOTALS_RE.exec(line);
|
|
88520
|
+
if (totals) {
|
|
88521
|
+
const [, a, total, b, errors2, c, warnings, d] = totals;
|
|
88522
|
+
return `${a}${Math.max(0, +total - removed)}${b}${Math.max(0, +errors2 - removedErrors)}${c}${Math.max(0, +warnings - removedWarnings)}${d}`;
|
|
88523
|
+
}
|
|
88524
|
+
const returning = MCP_RETURNING_RE.exec(line);
|
|
88525
|
+
return returning ? `${returning[1]}${Math.max(0, +returning[2] - removed)}${returning[3]}` : line;
|
|
88526
|
+
}).join("\n");
|
|
88527
|
+
}
|
|
87554
88528
|
}
|
|
87555
88529
|
});
|
|
87556
88530
|
|