@validate.qa/runner 1.0.103 → 1.0.104
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 +7 -2
- package/dist/{chunk-YI3ZC2XI.mjs → chunk-6N4QCCEH.mjs} +2 -2
- package/dist/{chunk-CMM4DOXC.mjs → chunk-EBWZ7NGU.mjs} +11 -8
- package/dist/{chunk-OTKJZIOD.mjs → chunk-EKY6CN4Y.mjs} +659 -122
- package/dist/{chunk-CG75I3ZZ.mjs → chunk-MEE4DXRX.mjs} +13437 -1386
- package/dist/{chunk-WVLBQDFP.mjs → chunk-OXDU6ARE.mjs} +8 -2
- package/dist/{chunk-AAUHXGDS.mjs → chunk-PUMRAFJS.mjs} +37 -13
- package/dist/{chunk-BECCGMU4.mjs → chunk-TGVKABFN.mjs} +45 -3
- package/dist/{chunk-YIM746WO.mjs → chunk-TS4OUJVT.mjs} +1 -1
- package/dist/{chunk-NNJYKR3O.mjs → chunk-UR7KDOTP.mjs} +29 -6
- package/dist/{chunk-36AWDKPL.mjs → chunk-UZ67UBXH.mjs} +14 -3
- package/dist/{chunk-7SH3COMQ.mjs → chunk-VWE3SQ2Z.mjs} +1 -1
- package/dist/{chunk-TK5KEGNW.mjs → chunk-XXZZMG6Q.mjs} +15 -3
- package/dist/cli.js +20962 -7343
- package/dist/cli.mjs +1159 -245
- package/dist/credential-mcp-server.js +671 -127
- package/dist/credential-mcp-server.mjs +3 -3
- package/dist/discovery-mcp-server.js +710 -129
- package/dist/discovery-mcp-server.mjs +4 -4
- package/dist/dist-BXHLIG5H.mjs +17 -0
- package/dist/inbox-mcp-server.js +664 -123
- package/dist/inbox-mcp-server.mjs +3 -3
- package/dist/route-seed-worker.js +671 -124
- package/dist/route-seed-worker.mjs +3 -3
- package/dist/run-write-guard-preload.js +713 -125
- package/dist/run-write-guard-preload.mjs +4 -4
- package/dist/run-write-guard.js +713 -125
- package/dist/run-write-guard.mjs +3 -3
- package/dist/tar-extract-child.js +38 -14
- package/dist/tar-extract-child.mjs +2 -2
- package/package.json +3 -2
- package/dist/dist-2G7YTNH5.mjs +0 -17
package/dist/inbox-mcp-server.js
CHANGED
|
@@ -67609,7 +67609,13 @@ function buildSandboxedEnv(processEnv, testVariables) {
|
|
|
67609
67609
|
return env;
|
|
67610
67610
|
}
|
|
67611
67611
|
function escapeEnvValue(value) {
|
|
67612
|
-
|
|
67612
|
+
if (!value.includes("\r")) {
|
|
67613
|
+
for (const quote of ["'", "`"]) {
|
|
67614
|
+
if (!value.includes(quote))
|
|
67615
|
+
return `${quote}${value}${quote}`;
|
|
67616
|
+
}
|
|
67617
|
+
}
|
|
67618
|
+
const escaped = value.replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r");
|
|
67613
67619
|
return `"${escaped}"`;
|
|
67614
67620
|
}
|
|
67615
67621
|
var API_PREFIX, SUPPORT_EMAIL, PLATFORM_ADMIN_EMAIL, NOREPLY_EMAIL, EMAIL_FROM_IDENTITIES, ADMIN_EMAIL_LIMITS, AUDIO_CHUNK_DURATION_MS, ACTION_BATCH_INTERVAL_MS, ACTION_BATCH_MAX_SIZE, MOBILE_SCREENSHOT_INTERVAL_MS, MOBILE_ACTION_BATCH_MAX_SIZE, MOBILE_BRIDGE_PORT, MOBILE_SNAPSHOT_MAX_SIZE_BYTES, MOBILE_APP_ID_MAX_LENGTH, MOBILE_APP_ID_PATTERN, MOBILE_FOCUS_SETTLE_MS, MOBILE_POST_ACTION_SETTLE_MS, MOBILE_COLD_BOOT_SETTLE_MS, MOBILE_DEFAULT_SWIPE_DISTANCE, MOBILE_MAX_SWIPE_DISTANCE, SELECTOR_PRIORITIES, MOBILE_STEP_TYPES, BLOCKED_ENV_VARS, SPAWNED_ENV_ALLOWLIST, MAX_PLAYWRIGHT_CODE_LENGTH;
|
|
@@ -70531,6 +70537,65 @@ var init_discovery_har_decision = __esm({
|
|
|
70531
70537
|
}
|
|
70532
70538
|
});
|
|
70533
70539
|
|
|
70540
|
+
// ../shared/dist/regex-literal.js
|
|
70541
|
+
function opensRegexLiteral(code, i) {
|
|
70542
|
+
let j = i - 1;
|
|
70543
|
+
while (j >= 0 && (code[j] === " " || code[j] === " "))
|
|
70544
|
+
j--;
|
|
70545
|
+
if (j < 0 || code[j] === "\n" || code[j] === "\r")
|
|
70546
|
+
return true;
|
|
70547
|
+
return regexOpensAfter(code, j);
|
|
70548
|
+
}
|
|
70549
|
+
function regexOpensAfter(code, j) {
|
|
70550
|
+
const prev = code[j];
|
|
70551
|
+
if (REGEX_OPENERS.includes(prev))
|
|
70552
|
+
return !((prev === "+" || prev === "-") && code[j - 1] === prev);
|
|
70553
|
+
if (!/[a-z]/.test(prev))
|
|
70554
|
+
return false;
|
|
70555
|
+
let start = j;
|
|
70556
|
+
while (start > 0 && /[A-Za-z0-9_$]/.test(code[start - 1]))
|
|
70557
|
+
start--;
|
|
70558
|
+
if (start > 0 && code[start - 1] === ".")
|
|
70559
|
+
return false;
|
|
70560
|
+
return REGEX_KEYWORDS.has(code.slice(start, j + 1));
|
|
70561
|
+
}
|
|
70562
|
+
function regexLiteralEnd(code, i) {
|
|
70563
|
+
let k = i + 1;
|
|
70564
|
+
let inClass = false;
|
|
70565
|
+
while (k < code.length) {
|
|
70566
|
+
const ch = code[k];
|
|
70567
|
+
if (ch === "\n" || ch === "\r")
|
|
70568
|
+
return k;
|
|
70569
|
+
if (ch === "\\") {
|
|
70570
|
+
if (code[k + 1] === "\n" || code[k + 1] === "\r")
|
|
70571
|
+
return k + 1;
|
|
70572
|
+
k += 2;
|
|
70573
|
+
continue;
|
|
70574
|
+
}
|
|
70575
|
+
if (inClass) {
|
|
70576
|
+
if (ch === "]")
|
|
70577
|
+
inClass = false;
|
|
70578
|
+
} else if (ch === "[") {
|
|
70579
|
+
inClass = true;
|
|
70580
|
+
} else if (ch === "/") {
|
|
70581
|
+
k++;
|
|
70582
|
+
while (k < code.length && /[a-z]/i.test(code[k]))
|
|
70583
|
+
k++;
|
|
70584
|
+
return k;
|
|
70585
|
+
}
|
|
70586
|
+
k++;
|
|
70587
|
+
}
|
|
70588
|
+
return code.length;
|
|
70589
|
+
}
|
|
70590
|
+
var REGEX_OPENERS, REGEX_KEYWORDS;
|
|
70591
|
+
var init_regex_literal = __esm({
|
|
70592
|
+
"../shared/dist/regex-literal.js"() {
|
|
70593
|
+
"use strict";
|
|
70594
|
+
REGEX_OPENERS = "(,=:[!&|?{};+-*%~^<>";
|
|
70595
|
+
REGEX_KEYWORDS = /* @__PURE__ */ new Set(["return", "typeof", "case", "do", "else", "in", "of", "new", "delete", "void", "throw", "await", "yield", "instanceof"]);
|
|
70596
|
+
}
|
|
70597
|
+
});
|
|
70598
|
+
|
|
70534
70599
|
// ../shared/dist/assertion-classifier.js
|
|
70535
70600
|
function isButtonOrLinkLocator(line) {
|
|
70536
70601
|
return /getByRole\s*\(\s*['"`](?:button|link)['"`]/i.test(line);
|
|
@@ -70839,7 +70904,7 @@ function classifyMobileAssertValue(value, context = {}) {
|
|
|
70839
70904
|
return { tier: 2, reason: t2[1] };
|
|
70840
70905
|
return null;
|
|
70841
70906
|
}
|
|
70842
|
-
function
|
|
70907
|
+
function regexLiteralEnd2(text, start) {
|
|
70843
70908
|
let inClass = false;
|
|
70844
70909
|
for (let i = start + 1; i < text.length; i++) {
|
|
70845
70910
|
const ch = text[i];
|
|
@@ -70865,7 +70930,7 @@ function parenDepthDelta(text) {
|
|
|
70865
70930
|
let depth = 0;
|
|
70866
70931
|
let quote = null;
|
|
70867
70932
|
let escaped = false;
|
|
70868
|
-
let
|
|
70933
|
+
let prevAt = -1;
|
|
70869
70934
|
let noRegexUntil = -1;
|
|
70870
70935
|
for (let i = 0; i < text.length; i++) {
|
|
70871
70936
|
const ch = text[i];
|
|
@@ -70880,7 +70945,7 @@ function parenDepthDelta(text) {
|
|
|
70880
70945
|
if (quote) {
|
|
70881
70946
|
if (ch === quote) {
|
|
70882
70947
|
quote = null;
|
|
70883
|
-
|
|
70948
|
+
prevAt = i;
|
|
70884
70949
|
}
|
|
70885
70950
|
continue;
|
|
70886
70951
|
}
|
|
@@ -70899,11 +70964,11 @@ function parenDepthDelta(text) {
|
|
|
70899
70964
|
i = close + 1;
|
|
70900
70965
|
continue;
|
|
70901
70966
|
}
|
|
70902
|
-
if (i > noRegexUntil && (
|
|
70903
|
-
const end =
|
|
70967
|
+
if (i > noRegexUntil && (prevAt < 0 || regexOpensAfter(text, prevAt))) {
|
|
70968
|
+
const end = regexLiteralEnd2(text, i);
|
|
70904
70969
|
if (end > 0) {
|
|
70905
70970
|
i = end - 1;
|
|
70906
|
-
|
|
70971
|
+
prevAt = end - 1;
|
|
70907
70972
|
continue;
|
|
70908
70973
|
}
|
|
70909
70974
|
const nl = text.indexOf("\n", i);
|
|
@@ -70915,14 +70980,15 @@ function parenDepthDelta(text) {
|
|
|
70915
70980
|
else if (ch === ")")
|
|
70916
70981
|
depth--;
|
|
70917
70982
|
if (ch !== " " && ch !== " " && ch !== "\n")
|
|
70918
|
-
|
|
70983
|
+
prevAt = i;
|
|
70919
70984
|
}
|
|
70920
70985
|
return depth;
|
|
70921
70986
|
}
|
|
70922
|
-
var PENDING_STATE_TEXT_REASON, PENDING_STATE_TEXT, TIER1_PATTERNS, TIER2_PATTERNS, TIER4_PATTERNS, SINGLE_QUOTED, DOUBLE_QUOTED, BACKTICK_QUOTED, QUOTED_BODY, LOCATOR_ARG_VALUE, LOCATOR_TEXT_ARG_PATTERNS, EXPECT_TOKEN
|
|
70987
|
+
var PENDING_STATE_TEXT_REASON, PENDING_STATE_TEXT, TIER1_PATTERNS, TIER2_PATTERNS, TIER4_PATTERNS, SINGLE_QUOTED, DOUBLE_QUOTED, BACKTICK_QUOTED, QUOTED_BODY, LOCATOR_ARG_VALUE, LOCATOR_TEXT_ARG_PATTERNS, EXPECT_TOKEN;
|
|
70923
70988
|
var init_assertion_classifier = __esm({
|
|
70924
70989
|
"../shared/dist/assertion-classifier.js"() {
|
|
70925
70990
|
"use strict";
|
|
70991
|
+
init_regex_literal();
|
|
70926
70992
|
PENDING_STATE_TEXT_REASON = 'pending-state text ("Sending...") is transient';
|
|
70927
70993
|
PENDING_STATE_TEXT = /\b(?!(?:Billing|Shipping|Pricing|Listing|Meeting|Morning|Evening|Warning|Building|Training|Marketing|Parking|Housing|Reading|Rating|Heading|Ceiling|Wedding|Clothing|Painting|Setting)\b)[A-Z][a-z]{2,}ing(?:\.{3}|…)/;
|
|
70928
70994
|
TIER1_PATTERNS = [
|
|
@@ -70999,7 +71065,6 @@ var init_assertion_classifier = __esm({
|
|
|
70999
71065
|
new RegExp(`\\.filter\\s*\\(\\s*\\{[^}]{0,200}?\\bhasText\\s*:\\s*${LOCATOR_ARG_VALUE}`, "gi")
|
|
71000
71066
|
];
|
|
71001
71067
|
EXPECT_TOKEN = /\bexpect\s*[.(]/;
|
|
71002
|
-
REGEX_PRECEDER = /* @__PURE__ */ new Set(["(", ",", "=", ":", "[", "!", "&", "|", "?", "{", "}", ";", "+", "-", "*", "%", "<", ">", "~", "^"]);
|
|
71003
71068
|
}
|
|
71004
71069
|
});
|
|
71005
71070
|
|
|
@@ -71007,14 +71072,80 @@ var init_assertion_classifier = __esm({
|
|
|
71007
71072
|
function isExpectCall(code) {
|
|
71008
71073
|
return EXPECT_CALL_RE.test(code);
|
|
71009
71074
|
}
|
|
71075
|
+
function specCallsExpect(code) {
|
|
71076
|
+
if (EXPECT_CALL_RE.test(code) || SPACED_EXPECT_CALL_RE.test(code) || CONFIGURE_IN_PLACE_RE.test(code))
|
|
71077
|
+
return true;
|
|
71078
|
+
const names = /* @__PURE__ */ new Set();
|
|
71079
|
+
for (const clause of code.matchAll(IMPORT_CLAUSE_RE)) {
|
|
71080
|
+
for (const alias of clause[1].matchAll(EXPECT_ALIAS_RE))
|
|
71081
|
+
names.add(alias[1]);
|
|
71082
|
+
}
|
|
71083
|
+
for (const decl of code.matchAll(DERIVED_EXPECT_DECL_RE)) {
|
|
71084
|
+
if (names.size >= MAX_DERIVED_EXPECT_NAMES)
|
|
71085
|
+
break;
|
|
71086
|
+
const base2 = decl[2];
|
|
71087
|
+
if (base2 === void 0 || base2 === "expect" || names.has(base2))
|
|
71088
|
+
names.add(decl[1]);
|
|
71089
|
+
}
|
|
71090
|
+
names.delete("expect");
|
|
71091
|
+
if (names.size === 0)
|
|
71092
|
+
return false;
|
|
71093
|
+
const alts = [...names].map((n) => n.replace(/\$/g, "\\$")).join("|");
|
|
71094
|
+
return new RegExp(String.raw`(?<![\w$.])(?:${alts})${EXPECT_MODIFIERS}`).test(code);
|
|
71095
|
+
}
|
|
71010
71096
|
function asPlainExpect(code) {
|
|
71011
71097
|
return code.replace(/\bexpect\.soft(\s*\()/g, "expect$1");
|
|
71012
71098
|
}
|
|
71013
|
-
|
|
71099
|
+
function expectAliasNames(code) {
|
|
71100
|
+
if (!MAY_ALIAS.test(code))
|
|
71101
|
+
return [];
|
|
71102
|
+
const imported = [];
|
|
71103
|
+
for (const m of code.matchAll(PW_IMPORT)) {
|
|
71104
|
+
for (const a of m[1].matchAll(IMPORT_AS_EXPECT))
|
|
71105
|
+
imported.push(a[1]);
|
|
71106
|
+
}
|
|
71107
|
+
const known = /* @__PURE__ */ new Set(["expect", ...imported]);
|
|
71108
|
+
const derived = [];
|
|
71109
|
+
for (const m of code.matchAll(DECLARATION)) {
|
|
71110
|
+
const rhs = DERIVED.exec(code.slice(m.index + m[0].length, m.index + m[0].length + 200));
|
|
71111
|
+
if (!rhs)
|
|
71112
|
+
continue;
|
|
71113
|
+
const base2 = rhs[1];
|
|
71114
|
+
const fromKnown = base2 === void 0 || (rhs[2] ? base2 === "test" : known.has(base2));
|
|
71115
|
+
if (!fromKnown || m[1] === "expect")
|
|
71116
|
+
continue;
|
|
71117
|
+
known.add(m[1]);
|
|
71118
|
+
derived.push(m[1]);
|
|
71119
|
+
}
|
|
71120
|
+
const fromImports = LOCAL_EXPECT.test(code) ? [] : imported;
|
|
71121
|
+
return [.../* @__PURE__ */ new Set([...fromImports, ...derived])].filter((n) => n !== "expect");
|
|
71122
|
+
}
|
|
71123
|
+
function withExpectAliasesAsExpect(code) {
|
|
71124
|
+
let out = code;
|
|
71125
|
+
for (const name of expectAliasNames(code)) {
|
|
71126
|
+
const escaped = name.replace(/\$/g, "\\$");
|
|
71127
|
+
out = out.replace(new RegExp(`(?<![\\w$.])${escaped}(?=\\s{0,20}(?:\\.\\s{0,20}(?:soft|poll)\\s{0,20})?\\()`, "g"), "expect");
|
|
71128
|
+
}
|
|
71129
|
+
return out;
|
|
71130
|
+
}
|
|
71131
|
+
var EXPECT_CALL_RE, EXPECT_MODIFIERS, SPACED_EXPECT_CALL_RE, CONFIGURE_IN_PLACE_RE, IMPORT_CLAUSE_RE, EXPECT_ALIAS_RE, DERIVED_EXPECT_DECL_RE, MAX_DERIVED_EXPECT_NAMES, PW_IMPORT, IMPORT_AS_EXPECT, DECLARATION, DERIVED, LOCAL_EXPECT, MAY_ALIAS;
|
|
71014
71132
|
var init_expect_call = __esm({
|
|
71015
71133
|
"../shared/dist/expect-call.js"() {
|
|
71016
71134
|
"use strict";
|
|
71017
71135
|
EXPECT_CALL_RE = /\bexpect(?:\.(?:soft|poll))?\s*\(/;
|
|
71136
|
+
EXPECT_MODIFIERS = String.raw`\s*(?:\.\s*soft\s*)?(?:\.\s*poll\s*)?\(`;
|
|
71137
|
+
SPACED_EXPECT_CALL_RE = new RegExp(String.raw`\bexpect${EXPECT_MODIFIERS}`);
|
|
71138
|
+
CONFIGURE_IN_PLACE_RE = new RegExp(String.raw`\bexpect\s*\.\s*configure\s*\(\s*(?:\{[^{}()]{0,500}\}\s*)?\)${EXPECT_MODIFIERS}`);
|
|
71139
|
+
IMPORT_CLAUSE_RE = /\bimport\s+(?:type\s+)?\{([^{}]{0,2000})\}/g;
|
|
71140
|
+
EXPECT_ALIAS_RE = /\bexpect\s+as\s+([A-Za-z_$][\w$]*)/g;
|
|
71141
|
+
DERIVED_EXPECT_DECL_RE = /\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*(?:([A-Za-z_$][\w$]*)\s*\.\s*(?:configure|extend)|mergeExpects)\s*\(/g;
|
|
71142
|
+
MAX_DERIVED_EXPECT_NAMES = 20;
|
|
71143
|
+
PW_IMPORT = /\bimport\s{0,20}\{([^}]{0,4000})\}\s{0,20}from\s{0,20}['"]@playwright\/test['"]/g;
|
|
71144
|
+
IMPORT_AS_EXPECT = /(?:^|,)\s{0,20}expect\s{1,20}as\s{1,20}([A-Za-z_$][\w$]{0,99})\s{0,20}(?=,|$)/g;
|
|
71145
|
+
DECLARATION = /\b(?:const|let|var)\s{1,20}([A-Za-z_$][\w$]{0,99})\s{0,20}(?::[^=;\n]{0,200})?=\s{0,20}/g;
|
|
71146
|
+
DERIVED = /^(?:mergeExpects\s{0,20}\(|([A-Za-z_$][\w$]{0,99})(\s{0,20}\.\s{0,20}expect)?\s{0,20}\.\s{0,20}(?:configure|extend)\s{0,20}\(|test\s{0,20}\.\s{0,20}expect\b(?!\s{0,20}[.(]))/;
|
|
71147
|
+
LOCAL_EXPECT = /\b(?:const|let|var)\s{1,20}expect\b/;
|
|
71148
|
+
MAY_ALIAS = /\bexpect\s{1,20}as\b|\.\s{0,20}(?:configure|extend)\s{0,20}\(|\bmergeExpects\b|\btest\s{0,20}\.\s{0,20}expect\b/;
|
|
71018
71149
|
}
|
|
71019
71150
|
});
|
|
71020
71151
|
|
|
@@ -71044,65 +71175,6 @@ var init_braced_clause = __esm({
|
|
|
71044
71175
|
}
|
|
71045
71176
|
});
|
|
71046
71177
|
|
|
71047
|
-
// ../shared/dist/regex-literal.js
|
|
71048
|
-
function opensRegexLiteral(code, i) {
|
|
71049
|
-
let j = i - 1;
|
|
71050
|
-
while (j >= 0 && (code[j] === " " || code[j] === " "))
|
|
71051
|
-
j--;
|
|
71052
|
-
if (j < 0 || code[j] === "\n" || code[j] === "\r")
|
|
71053
|
-
return true;
|
|
71054
|
-
return regexOpensAfter(code, j);
|
|
71055
|
-
}
|
|
71056
|
-
function regexOpensAfter(code, j) {
|
|
71057
|
-
const prev = code[j];
|
|
71058
|
-
if (REGEX_OPENERS.includes(prev))
|
|
71059
|
-
return !((prev === "+" || prev === "-") && code[j - 1] === prev);
|
|
71060
|
-
if (!/[a-z]/.test(prev))
|
|
71061
|
-
return false;
|
|
71062
|
-
let start = j;
|
|
71063
|
-
while (start > 0 && /[A-Za-z0-9_$]/.test(code[start - 1]))
|
|
71064
|
-
start--;
|
|
71065
|
-
if (start > 0 && code[start - 1] === ".")
|
|
71066
|
-
return false;
|
|
71067
|
-
return REGEX_KEYWORDS.has(code.slice(start, j + 1));
|
|
71068
|
-
}
|
|
71069
|
-
function regexLiteralEnd2(code, i) {
|
|
71070
|
-
let k = i + 1;
|
|
71071
|
-
let inClass = false;
|
|
71072
|
-
while (k < code.length) {
|
|
71073
|
-
const ch = code[k];
|
|
71074
|
-
if (ch === "\n" || ch === "\r")
|
|
71075
|
-
return k;
|
|
71076
|
-
if (ch === "\\") {
|
|
71077
|
-
if (code[k + 1] === "\n" || code[k + 1] === "\r")
|
|
71078
|
-
return k + 1;
|
|
71079
|
-
k += 2;
|
|
71080
|
-
continue;
|
|
71081
|
-
}
|
|
71082
|
-
if (inClass) {
|
|
71083
|
-
if (ch === "]")
|
|
71084
|
-
inClass = false;
|
|
71085
|
-
} else if (ch === "[") {
|
|
71086
|
-
inClass = true;
|
|
71087
|
-
} else if (ch === "/") {
|
|
71088
|
-
k++;
|
|
71089
|
-
while (k < code.length && /[a-z]/i.test(code[k]))
|
|
71090
|
-
k++;
|
|
71091
|
-
return k;
|
|
71092
|
-
}
|
|
71093
|
-
k++;
|
|
71094
|
-
}
|
|
71095
|
-
return code.length;
|
|
71096
|
-
}
|
|
71097
|
-
var REGEX_OPENERS, REGEX_KEYWORDS;
|
|
71098
|
-
var init_regex_literal = __esm({
|
|
71099
|
-
"../shared/dist/regex-literal.js"() {
|
|
71100
|
-
"use strict";
|
|
71101
|
-
REGEX_OPENERS = "(,=:[!&|?{};+-*%~^<>";
|
|
71102
|
-
REGEX_KEYWORDS = /* @__PURE__ */ new Set(["return", "typeof", "case", "do", "else", "in", "of", "new", "delete", "void", "throw", "await", "yield", "instanceof"]);
|
|
71103
|
-
}
|
|
71104
|
-
});
|
|
71105
|
-
|
|
71106
71178
|
// ../shared/dist/assertion-proof.js
|
|
71107
71179
|
function fragmentKindOf(literal, fromText) {
|
|
71108
71180
|
const text = literal.trim();
|
|
@@ -71261,7 +71333,7 @@ function stripCoverageComments(code) {
|
|
|
71261
71333
|
let copyFrom = 0;
|
|
71262
71334
|
let i = 0;
|
|
71263
71335
|
let quote = null;
|
|
71264
|
-
let
|
|
71336
|
+
let prevAt = -1;
|
|
71265
71337
|
let noRegexBefore = 0;
|
|
71266
71338
|
while (i < code.length) {
|
|
71267
71339
|
const ch = code[i];
|
|
@@ -71272,17 +71344,18 @@ function stripCoverageComments(code) {
|
|
|
71272
71344
|
}
|
|
71273
71345
|
if (ch === quote || ch === "\n" && quote !== "`") {
|
|
71274
71346
|
quote = null;
|
|
71275
|
-
|
|
71347
|
+
if (ch !== "\n")
|
|
71348
|
+
prevAt = i;
|
|
71276
71349
|
}
|
|
71277
71350
|
i++;
|
|
71278
71351
|
continue;
|
|
71279
71352
|
}
|
|
71280
71353
|
const next = code[i + 1];
|
|
71281
|
-
if (ch === "/" && next !== "*" && next !== "/" && i >= noRegexBefore && (
|
|
71354
|
+
if (ch === "/" && next !== "*" && next !== "/" && i >= noRegexBefore && (prevAt < 0 || regexOpensAfter(code, prevAt))) {
|
|
71282
71355
|
const end = regexLiteralEnd3(code, i);
|
|
71283
71356
|
if (end > 0) {
|
|
71284
71357
|
i = end;
|
|
71285
|
-
|
|
71358
|
+
prevAt = end - 1;
|
|
71286
71359
|
continue;
|
|
71287
71360
|
}
|
|
71288
71361
|
const eol = code.indexOf("\n", i);
|
|
@@ -71307,7 +71380,7 @@ function stripCoverageComments(code) {
|
|
|
71307
71380
|
if (ch === '"' || ch === "'" || ch === "`")
|
|
71308
71381
|
quote = ch;
|
|
71309
71382
|
if (ch !== " " && ch !== " " && ch !== "\n" && ch !== "\r")
|
|
71310
|
-
|
|
71383
|
+
prevAt = i;
|
|
71311
71384
|
i++;
|
|
71312
71385
|
}
|
|
71313
71386
|
out.push(code.slice(copyFrom));
|
|
@@ -71996,11 +72069,12 @@ function assessTitleCoverage(title, code) {
|
|
|
71996
72069
|
const repeatedHit = [...repeated].some((term) => hay.includes(term));
|
|
71997
72070
|
return { covered: hit >= needed || repeatedHit, missingTerms };
|
|
71998
72071
|
}
|
|
71999
|
-
var COVERAGE_STOP_WORDS, MAX_ASSERTION_JOIN_CHARS, MAX_COVERAGE_LINE_CHARS,
|
|
72072
|
+
var COVERAGE_STOP_WORDS, MAX_ASSERTION_JOIN_CHARS, MAX_COVERAGE_LINE_CHARS, BLOCK_SCAFFOLD, cachedAssertionInput, cachedAssertionSource, LOCAL_BINDING, ASSERTED_STATUS_RE, MAX_RESOLVED_NAMES_PER_LINE, WORD_CHAR_RE, NOT_CONTAIN_TEXT_RE, PLACE_PHRASE_RE, PLACE_WORD_MIN_CHARS, PLACE_FUNCTION_WORDS, HIDDEN_STATE_TERMS, HIDDEN_ELEMENT_LINE_RE, HIDDEN_LINE_RE, MAX_SHOWN_EARLIER_LINES, SHOWN_EARLIER_LITERAL_RE, SHARED_PREFIX_MIN_CHARS, MAX_SHOWN_EARLIER_LITERALS, VALUE_SHAPE_RE, VALUE_SHAPE_ALL_RE, TITLE_TERM_MIN;
|
|
72000
72073
|
var init_expected_outcome_coverage = __esm({
|
|
72001
72074
|
"../shared/dist/expected-outcome-coverage.js"() {
|
|
72002
72075
|
"use strict";
|
|
72003
72076
|
init_assertion_classifier();
|
|
72077
|
+
init_regex_literal();
|
|
72004
72078
|
COVERAGE_STOP_WORDS = /* @__PURE__ */ new Set([
|
|
72005
72079
|
"after",
|
|
72006
72080
|
"before",
|
|
@@ -72033,7 +72107,6 @@ var init_expected_outcome_coverage = __esm({
|
|
|
72033
72107
|
]);
|
|
72034
72108
|
MAX_ASSERTION_JOIN_CHARS = 8e3;
|
|
72035
72109
|
MAX_COVERAGE_LINE_CHARS = 2e3;
|
|
72036
|
-
REGEX_PRECEDER2 = "(,=:[!&|?{};+-*%<>~^";
|
|
72037
72110
|
BLOCK_SCAFFOLD = /=>|\b(?:test|describe|it|beforeEach|afterEach|beforeAll|afterAll|function)\b/;
|
|
72038
72111
|
cachedAssertionInput = null;
|
|
72039
72112
|
cachedAssertionSource = { raw: "", normalized: "", bindings: /* @__PURE__ */ new Map(), bindingRefs: /* @__PURE__ */ new Map() };
|
|
@@ -72129,7 +72202,7 @@ function replaceBlockComments(code, replacer) {
|
|
|
72129
72202
|
continue;
|
|
72130
72203
|
const next = code[i + 1];
|
|
72131
72204
|
if (next !== "/" && next !== "*" && opensRegexLiteral(code, i)) {
|
|
72132
|
-
i =
|
|
72205
|
+
i = regexLiteralEnd(code, i) - 1;
|
|
72133
72206
|
continue;
|
|
72134
72207
|
}
|
|
72135
72208
|
if (next === "/" && !(code[i - 1] === ":" && /[A-Za-z]/.test(code[i - 2] ?? ""))) {
|
|
@@ -72304,10 +72377,41 @@ var init_auth_handoff_coverage = __esm({
|
|
|
72304
72377
|
});
|
|
72305
72378
|
|
|
72306
72379
|
// ../shared/dist/auth-plan.js
|
|
72307
|
-
function
|
|
72380
|
+
function stripStampedHelperRegions(code) {
|
|
72381
|
+
let out = code;
|
|
72382
|
+
for (const [open, close] of STAMPED_HELPER_REGIONS) {
|
|
72383
|
+
if (out.indexOf(open) === -1)
|
|
72384
|
+
continue;
|
|
72385
|
+
let kept = "";
|
|
72386
|
+
let i = 0;
|
|
72387
|
+
while (i < out.length) {
|
|
72388
|
+
const start = out.indexOf(open, i);
|
|
72389
|
+
if (start === -1) {
|
|
72390
|
+
kept += out.slice(i);
|
|
72391
|
+
break;
|
|
72392
|
+
}
|
|
72393
|
+
const end = out.indexOf(close, start + open.length);
|
|
72394
|
+
if (end === -1) {
|
|
72395
|
+
kept += out.slice(i);
|
|
72396
|
+
break;
|
|
72397
|
+
}
|
|
72398
|
+
const lineEnd = out.indexOf("\n", end);
|
|
72399
|
+
kept += out.slice(i, start);
|
|
72400
|
+
i = lineEnd === -1 ? out.length : lineEnd + 1;
|
|
72401
|
+
}
|
|
72402
|
+
out = kept;
|
|
72403
|
+
}
|
|
72404
|
+
return out;
|
|
72405
|
+
}
|
|
72406
|
+
function signsInInline(playwrightCode) {
|
|
72308
72407
|
if (!playwrightCode)
|
|
72309
72408
|
return false;
|
|
72310
|
-
|
|
72409
|
+
if (!/process\.env\.TEST_USER_EMAIL!?/.test(playwrightCode))
|
|
72410
|
+
return false;
|
|
72411
|
+
if (/process\.env\.TEST_USER_PASSWORD!?/.test(playwrightCode))
|
|
72412
|
+
return true;
|
|
72413
|
+
const body = stripStampedHelperRegions(playwrightCode);
|
|
72414
|
+
return /process\.env\.TEST_USER_EMAIL/.test(body) && /__vqaWaitForEmail\s*\(/.test(body);
|
|
72311
72415
|
}
|
|
72312
72416
|
function hasGeneratedAuthGuard(playwrightCode) {
|
|
72313
72417
|
if (!playwrightCode)
|
|
@@ -72326,7 +72430,7 @@ function legacyNeedsCookieState(tags, code, sharedAuthInjectEnabled) {
|
|
|
72326
72430
|
if (sharedAuthInjectEnabled && tags.includes("@auth-guarded") && hasGeneratedAuthGuard(code))
|
|
72327
72431
|
return true;
|
|
72328
72432
|
const isGeneratedVariant = tags.includes("@edge") || tags.includes("@bug");
|
|
72329
|
-
const hasLegacyInlineLogin = tags.includes("@discovered") && !isGeneratedVariant &&
|
|
72433
|
+
const hasLegacyInlineLogin = tags.includes("@discovered") && !isGeneratedVariant && signsInInline(code);
|
|
72330
72434
|
return !tags.includes("@inline-login") && !hasLegacyInlineLogin;
|
|
72331
72435
|
}
|
|
72332
72436
|
function codeReadsStoredCredentials(code) {
|
|
@@ -72447,7 +72551,7 @@ function authTypeTag(tags) {
|
|
|
72447
72551
|
const explicit = explicitAuthTypeTags(t);
|
|
72448
72552
|
return explicit.length === 1 ? explicit[0] : void 0;
|
|
72449
72553
|
}
|
|
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;
|
|
72554
|
+
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, STAMPED_HELPER_REGIONS;
|
|
72451
72555
|
var init_auth_plan = __esm({
|
|
72452
72556
|
"../shared/dist/auth-plan.js"() {
|
|
72453
72557
|
"use strict";
|
|
@@ -72474,6 +72578,10 @@ var init_auth_plan = __esm({
|
|
|
72474
72578
|
};
|
|
72475
72579
|
TEST_USER_ENV_KEYS = ["TEST_USER_EMAIL", "TEST_USER_PASSWORD"];
|
|
72476
72580
|
API_AUTH_HEADERS_ENV_KEY = "API_AUTH_HEADERS";
|
|
72581
|
+
STAMPED_HELPER_REGIONS = [
|
|
72582
|
+
["// >>> VALIDATE_QA_INBOX", "// <<< VALIDATE_QA_INBOX"],
|
|
72583
|
+
["// >>> VALIDATE_QA_SMS", "// <<< VALIDATE_QA_SMS"]
|
|
72584
|
+
];
|
|
72477
72585
|
}
|
|
72478
72586
|
});
|
|
72479
72587
|
|
|
@@ -72482,6 +72590,9 @@ function parseLastActionProofMode(raw) {
|
|
|
72482
72590
|
const v = (raw ?? "").trim().toLowerCase();
|
|
72483
72591
|
return v === "on" || v === "shadow" ? v : "off";
|
|
72484
72592
|
}
|
|
72593
|
+
function parseAbsenceProofMode(raw) {
|
|
72594
|
+
return parseLastActionProofMode(raw);
|
|
72595
|
+
}
|
|
72485
72596
|
function isUrlProof(stmt) {
|
|
72486
72597
|
if (URL_PROOF.test(stmt))
|
|
72487
72598
|
return true;
|
|
@@ -72869,6 +72980,65 @@ function isVacuousAccountAbsence(stmt, shown, account) {
|
|
|
72869
72980
|
}
|
|
72870
72981
|
return true;
|
|
72871
72982
|
}
|
|
72983
|
+
function isAbsenceCheck(stmt) {
|
|
72984
|
+
if (!claimsAbsence(stmt))
|
|
72985
|
+
return false;
|
|
72986
|
+
const bare = stmt.replace(NOT_BEFORE_MATCHER, ".");
|
|
72987
|
+
return ABSENCE_READ.test(bare) || VALUE_ABSENCE.test(bare) || OPTION_ABSENCE.test(bare);
|
|
72988
|
+
}
|
|
72989
|
+
function comparableSubject(subject) {
|
|
72990
|
+
let s = subject.replace(/^\s*await\s+/, "").replace(/\s+/g, "");
|
|
72991
|
+
for (let prev = ""; prev !== s; ) {
|
|
72992
|
+
prev = s;
|
|
72993
|
+
s = s.replace(/\.(?:count|isVisible|isHidden|first|last)\(\)$/, "").replace(/\.nth\(\d+\)$/, "");
|
|
72994
|
+
}
|
|
72995
|
+
return s;
|
|
72996
|
+
}
|
|
72997
|
+
function subjectsThatExisted(checks, interactionStmts) {
|
|
72998
|
+
const out = [];
|
|
72999
|
+
const bound = locatorBindings(interactionStmts);
|
|
73000
|
+
const resolve = (expr) => {
|
|
73001
|
+
for (let depth = 0; depth < 4; depth++) {
|
|
73002
|
+
const lead = expr.match(/^\s*(?:await\s+)?([A-Za-z_$][\w$]*)(?![\w$(])/);
|
|
73003
|
+
const to = lead ? bound.get(lead[1]) : void 0;
|
|
73004
|
+
if (!lead || to === void 0)
|
|
73005
|
+
break;
|
|
73006
|
+
expr = `${to.replace(/;\s*$/, "")}${expr.slice(lead[0].length)}`;
|
|
73007
|
+
}
|
|
73008
|
+
return expr;
|
|
73009
|
+
};
|
|
73010
|
+
for (const { stmt } of checks) {
|
|
73011
|
+
if (isAbsenceCheck(stmt))
|
|
73012
|
+
continue;
|
|
73013
|
+
const subject = extractExpectSubject(stmt);
|
|
73014
|
+
if (subject)
|
|
73015
|
+
out.push(comparableSubject(subject));
|
|
73016
|
+
}
|
|
73017
|
+
for (const stmt of interactionStmts) {
|
|
73018
|
+
if (EXPECT_CALL_RE.test(stmt))
|
|
73019
|
+
continue;
|
|
73020
|
+
for (const m of stmt.matchAll(LOCATOR_USE)) {
|
|
73021
|
+
if (m[0].includes("waitFor") && /state\s*:\s*['"`](?:hidden|detached)/.test(stmt.slice(m.index)))
|
|
73022
|
+
continue;
|
|
73023
|
+
const before = stmt.slice(0, m.index).replace(/^\s*(?:(?:const|let|var)\s+[\w$]+\s*=|return\b)\s*/, "");
|
|
73024
|
+
if (before.trim())
|
|
73025
|
+
out.push(comparableSubject(resolve(before)));
|
|
73026
|
+
}
|
|
73027
|
+
}
|
|
73028
|
+
return out;
|
|
73029
|
+
}
|
|
73030
|
+
function isUnshownAbsence(stmt, existed, entered) {
|
|
73031
|
+
if (!isAbsenceCheck(stmt))
|
|
73032
|
+
return false;
|
|
73033
|
+
const raw = extractExpectSubject(stmt);
|
|
73034
|
+
if (!raw || !/\b(?:locator|getBy[A-Z]\w*|frameLocator)\s*\(/.test(raw))
|
|
73035
|
+
return false;
|
|
73036
|
+
const subject = comparableSubject(raw);
|
|
73037
|
+
if (existed.some((e) => e === subject || e.startsWith(`${subject}.`)))
|
|
73038
|
+
return false;
|
|
73039
|
+
const named = raw.match(/['"`][^'"`]+['"`]/g) ?? [];
|
|
73040
|
+
return !named.some((q) => entered.values.has(q.slice(1, -1).toLowerCase()));
|
|
73041
|
+
}
|
|
72872
73042
|
function endOfEnclosingCall(stmt, from) {
|
|
72873
73043
|
let depth = 0;
|
|
72874
73044
|
for (let i = from; i < stmt.length; i++) {
|
|
@@ -73368,10 +73538,31 @@ function comparesWithItself(subject, tail) {
|
|
|
73368
73538
|
const expected = squash2(args);
|
|
73369
73539
|
return expected === squash2(m[1] === "toHaveCount" ? `${subject}.count()` : subject);
|
|
73370
73540
|
}
|
|
73541
|
+
function ariaSnapshotTexts(template) {
|
|
73542
|
+
const out = [];
|
|
73543
|
+
for (const raw of template.split(ARIA_ENTRY_SPLIT)) {
|
|
73544
|
+
const m = ARIA_ENTRY.exec(raw.trim());
|
|
73545
|
+
if (!m || !ARIA_CONTENT_ROLES.has(m[1]))
|
|
73546
|
+
continue;
|
|
73547
|
+
for (const text of [m[2], m[3]]) {
|
|
73548
|
+
const t = text?.replace(/\\(.)/g, "$1").replace(/^["']|["']$/g, "").trim();
|
|
73549
|
+
if (!t || t.startsWith("/") || !/[\p{L}\p{N}]/u.test(t) || /["'`\\]/.test(t))
|
|
73550
|
+
continue;
|
|
73551
|
+
out.push(t);
|
|
73552
|
+
}
|
|
73553
|
+
}
|
|
73554
|
+
return out;
|
|
73555
|
+
}
|
|
73556
|
+
function presenceTwin(stmt) {
|
|
73557
|
+
return stmt.replace(NOT_HIDDEN, ".toBeVisible(").replace(NOT_COUNT_ZERO, ".toBeVisible(");
|
|
73558
|
+
}
|
|
73371
73559
|
function asPlainAssertion(s) {
|
|
73372
73560
|
return plainAssertion(s, false);
|
|
73373
73561
|
}
|
|
73374
73562
|
function plainAssertion(s, keepSelfCompare) {
|
|
73563
|
+
const twin = presenceTwin(s.stmt);
|
|
73564
|
+
if (twin !== s.stmt)
|
|
73565
|
+
return plainAssertion({ ...s, stmt: twin }, keepSelfCompare);
|
|
73375
73566
|
const { stmt } = s;
|
|
73376
73567
|
if (COUNT_AT_LEAST_ZERO.test(stmt))
|
|
73377
73568
|
return [];
|
|
@@ -73382,6 +73573,12 @@ function plainAssertion(s, keepSelfCompare) {
|
|
|
73382
73573
|
const subjectAt = stmt.indexOf(subject, stmt.search(EXPECT_CALL_RE));
|
|
73383
73574
|
const tail = (stmt.startsWith("expect.poll", stmt.search(EXPECT_CALL_RE)) ? expectCallTail(stmt) : null) ?? stmt.slice(subjectAt + subject.length).trimStart();
|
|
73384
73575
|
const as = (rewritten) => [{ ...s, stmt: rewritten }];
|
|
73576
|
+
const aria = ARIA_TEMPLATE_CALL.exec(tail);
|
|
73577
|
+
if (aria && !NEGATED_ASSERT.test(stmt)) {
|
|
73578
|
+
const texts = ariaSnapshotTexts(aria[2]);
|
|
73579
|
+
if (texts.length > 0)
|
|
73580
|
+
return texts.map((t) => ({ ...s, stmt: `await expect(${plain}).toContainText(${JSON.stringify(t)});` }));
|
|
73581
|
+
}
|
|
73385
73582
|
if (LOCATOR_EXPR.test(plain) && !LOCATOR_VALUE_READ.test(plain) && ALWAYS_TRUE_ON_OBJECT.test(tail))
|
|
73386
73583
|
return [];
|
|
73387
73584
|
if (DEFINED_VALUE_READ.test(plain) && ALWAYS_DEFINED.test(tail))
|
|
@@ -73688,7 +73885,8 @@ function teardownLines(lines) {
|
|
|
73688
73885
|
}
|
|
73689
73886
|
return out;
|
|
73690
73887
|
}
|
|
73691
|
-
function validateAssertionStrength(
|
|
73888
|
+
function validateAssertionStrength(source, opts = {}) {
|
|
73889
|
+
const code = withExpectAliasesAsExpect(source);
|
|
73692
73890
|
const body = stripLoginScaffolding(code);
|
|
73693
73891
|
const lines = body.split("\n");
|
|
73694
73892
|
const stmts = liveExpectStatements(stripCoverageComments(body)).flatMap(asPlainAssertion);
|
|
@@ -73841,8 +74039,23 @@ function validateAssertionStrength(code, opts = {}) {
|
|
|
73841
74039
|
const orderedPersistence = firstMutLine !== void 0 ? persistence : void 0;
|
|
73842
74040
|
const signedIn = signInProofWindow(interactionStmts, interactionStmtsWithLines, lines, blockIds);
|
|
73843
74041
|
const proof = classifyOutcomeProof(checks, mutated, reloaded, clickedControlNames(interactionStmts), entered, firstMutLine, orderedPersistence, signedIn);
|
|
74042
|
+
const absenceProof = opts.absenceProof ?? "off";
|
|
74043
|
+
let absenceOnly = false;
|
|
74044
|
+
if (absenceProof !== "off" && proof.kind === "durable") {
|
|
74045
|
+
const existed = subjectsThatExisted(checks, interactionStmtsRaw);
|
|
74046
|
+
const kept = checks.filter(({ stmt }) => !isUnshownAbsence(stmt, existed, entered));
|
|
74047
|
+
absenceOnly = kept.length < checks.length && classifyOutcomeProof(kept, mutated, reloaded, clickedControlNames(interactionStmts), entered, firstMutLine, orderedPersistence, signedIn).kind !== "durable";
|
|
74048
|
+
if (absenceOnly && absenceProof === "on") {
|
|
74049
|
+
return {
|
|
74050
|
+
ok: false,
|
|
74051
|
+
severity: mutated ? "block" : "downgrade",
|
|
74052
|
+
reason: "the only outcome checks are absence checks (not visible / hidden / count 0) of something the test never showed, touched or typed: they pass whether or not the action worked \u2014 assert what the action produced (the new text, value, count or page), or assert the element present before it goes",
|
|
74053
|
+
signals: base2({ interacted, mutated, navOnly, hasOutcomeProof: false, terminal, absenceOnly: true })
|
|
74054
|
+
};
|
|
74055
|
+
}
|
|
74056
|
+
}
|
|
73844
74057
|
if (proof.kind === "durable") {
|
|
73845
|
-
const signals2 = base2({ interacted, mutated, navOnly, hasOutcomeProof: true, terminal });
|
|
74058
|
+
const signals2 = base2({ interacted, mutated, navOnly, hasOutcomeProof: true, terminal, ...absenceOnly ? { absenceOnly } : {} });
|
|
73846
74059
|
const { last, prev } = acts;
|
|
73847
74060
|
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
74061
|
const lastLine = interactionStmtsWithLines[last.i].startLine;
|
|
@@ -73946,7 +74159,7 @@ function validateAssertionStrength(code, opts = {}) {
|
|
|
73946
74159
|
signals
|
|
73947
74160
|
};
|
|
73948
74161
|
}
|
|
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;
|
|
74162
|
+
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, ABSENCE_READ, LOCATOR_USE, 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, ARIA_TEMPLATE_CALL, ARIA_ENTRY_SPLIT, ARIA_CONTENT_ROLES, ARIA_ENTRY, NOT_HIDDEN, NOT_COUNT_ZERO, 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;
|
|
73950
74163
|
var init_assertion_strength = __esm({
|
|
73951
74164
|
"../shared/dist/assertion-strength.js"() {
|
|
73952
74165
|
"use strict";
|
|
@@ -74035,6 +74248,8 @@ var init_assertion_strength = __esm({
|
|
|
74035
74248
|
NOT_BEFORE_MATCHER = /\.not\s*\.\s*(?=to[A-Z])/g;
|
|
74036
74249
|
ERROR_TEXT_WORDS = /error|fail|wrong|try again|unable|could ?n.?t|can.?t|problem|invalid|unavailable/i;
|
|
74037
74250
|
TEXT_REGEX_ARG = /(?:getByText|hasText|getByRole\([^)]{0,200}name)\s*[:(]\s*(\/(?:\\.|[^/\\\n])+\/[a-z]*)/;
|
|
74251
|
+
ABSENCE_READ = /\.toBeVisible\s*\(|\.toBeHidden\s*\(|\.toHaveCount\s*\(\s*0\s*\)|\.toBeAttached\s*\(|\.toHaveText\s*\(|\.toContainText\s*\(/;
|
|
74252
|
+
LOCATOR_USE = /\.\s*(?:click|dblclick|tap|hover|focus|fill|clear|press|pressSequentially|type|check|uncheck|setChecked|selectOption|setInputFiles|dragTo|selectText|waitFor)\s*\(/g;
|
|
74038
74253
|
SCOPING_STEP = /(?:\s*\.\s*(?:first|last|nth)\s*\([^()]*\))*\s*\.\s*(?:getBy[A-Z]\w*|locator|filter)\s*\(/y;
|
|
74039
74254
|
NEGATED_TEXT = /\.not\s*\.\s*(?:toHaveText|toContainText)\s*\(\s*(?:['"`]([^'"`]*)['"`]|\/((?:\\.|[^/\\\n])+)\/)?/;
|
|
74040
74255
|
ASYNC_DESTRUCTURE_OPEN = /async\s*\(\s*\{/g;
|
|
@@ -74076,6 +74291,29 @@ var init_assertion_strength = __esm({
|
|
|
74076
74291
|
IS_VISIBLE_TRUE = /^\)*\s*\.\s*(?:toBe\s*\(\s*true\s*\)|toBeTruthy\s*\(\s*\))/;
|
|
74077
74292
|
PAGE_VALUE_MATCHER = /^\)\s*\.\s*(?:toBe|toEqual|toStrictEqual|toMatch|toContain)\s*\(/;
|
|
74078
74293
|
COUNT_ONE = /\.\s*toHaveCount\s*\(\s*1\s*\)/;
|
|
74294
|
+
ARIA_TEMPLATE_CALL = /^\)\s*\.\s*toMatchAriaSnapshot\s*\(\s*(['"`])((?:\\[\s\S]|(?!\1)[^\\])*)\1/;
|
|
74295
|
+
ARIA_ENTRY_SPLIT = /(?:^|\s)-\s+(?=\/?[a-z][a-z-]*(?:\s|:|\[|$))/;
|
|
74296
|
+
ARIA_CONTENT_ROLES = /* @__PURE__ */ new Set([
|
|
74297
|
+
"listitem",
|
|
74298
|
+
"row",
|
|
74299
|
+
"cell",
|
|
74300
|
+
"gridcell",
|
|
74301
|
+
"article",
|
|
74302
|
+
"treeitem",
|
|
74303
|
+
"paragraph",
|
|
74304
|
+
"text",
|
|
74305
|
+
"strong",
|
|
74306
|
+
"emphasis",
|
|
74307
|
+
"code",
|
|
74308
|
+
"blockquote",
|
|
74309
|
+
"term",
|
|
74310
|
+
"definition",
|
|
74311
|
+
"alert",
|
|
74312
|
+
"status"
|
|
74313
|
+
]);
|
|
74314
|
+
ARIA_ENTRY = /^([a-z][a-z-]*)(?:\s+"((?:\\.|[^"\\])*)")?(?:\s*\[[^\]]*\])*\s*(?::\s*(\S.*)?)?$/s;
|
|
74315
|
+
NOT_HIDDEN = /\.not\s*\.\s*toBeHidden\s*\(/g;
|
|
74316
|
+
NOT_COUNT_ZERO = /\.not\s*\.\s*toHaveCount\s*\(\s*0\s*(?:,\s*|(?=\)))/g;
|
|
74079
74317
|
URL_CHECK_ARG = /\bpage\s*\.\s*waitForURL\s*\(\s*([^,)]+)|\bexpect(?:\s*\.\s*soft)?\s*\(\s*page\s*\)\s*\.\s*toHaveURL\s*\(\s*([^,)]+)/;
|
|
74080
74318
|
PLAIN_PAGE_PATH = /^\/[\w\-./~%]*(?:[?#][^\s]*)?$/;
|
|
74081
74319
|
FORM_CONTROL_LOCATOR = /getByRole\s*\(\s*['"`](?:combobox|switch|checkbox|radio|textbox|searchbox|spinbutton|slider)['"`]|getByLabel\s*\(|getByPlaceholder\s*\(/;
|
|
@@ -74121,6 +74359,12 @@ function isCancelledReason(error2) {
|
|
|
74121
74359
|
function isHeldHealRun(run) {
|
|
74122
74360
|
return run?.status === "PASSED" && typeof run.error === "string" && run.error.startsWith(HEAL_PATCH_HELD_RUN_ERROR_PREFIX);
|
|
74123
74361
|
}
|
|
74362
|
+
function mayBeUnverifiedHealPass(run, tags) {
|
|
74363
|
+
return !!run && run.status === "PASSED" && run.mode === "heal" && !isHeldHealRun(run) && (tags ?? []).includes(NEEDS_REVIEW_TAG);
|
|
74364
|
+
}
|
|
74365
|
+
function isUnverifiedHealPass(run, tags, healConfidence) {
|
|
74366
|
+
return mayBeUnverifiedHealPass(run, tags) && typeof healConfidence === "string" && UNVERIFIED_HEAL_CONFIDENCES.has(healConfidence);
|
|
74367
|
+
}
|
|
74124
74368
|
function isRunInterruptedError(error2) {
|
|
74125
74369
|
return typeof error2 === "string" && RUN_INTERRUPTED_ERROR_PREFIXES.some((prefix) => error2.startsWith(prefix));
|
|
74126
74370
|
}
|
|
@@ -74207,12 +74451,25 @@ function classifyErrorMessage(error2) {
|
|
|
74207
74451
|
return "config_issue";
|
|
74208
74452
|
if (EMAIL_NOT_RECEIVED_PREFIXES.some((prefix) => normalized.startsWith(prefix)))
|
|
74209
74453
|
return "email_not_received";
|
|
74454
|
+
if (SMS_NOT_RECEIVED_PREFIXES.some((prefix) => normalized.startsWith(prefix)))
|
|
74455
|
+
return "email_not_received";
|
|
74210
74456
|
if (isCancelledReason(error2))
|
|
74211
74457
|
return "cancelled";
|
|
74212
74458
|
if (isRetriedRunInterruption(error2))
|
|
74213
74459
|
return "interrupted";
|
|
74214
74460
|
return null;
|
|
74215
74461
|
}
|
|
74462
|
+
function isSmsNotReceivedError(error2) {
|
|
74463
|
+
if (typeof error2 !== "string")
|
|
74464
|
+
return false;
|
|
74465
|
+
const normalized = error2.replace(/^\s+/, "").replace(/^Error:\s*/i, "");
|
|
74466
|
+
return SMS_NOT_RECEIVED_PREFIXES.some((prefix) => normalized.startsWith(prefix));
|
|
74467
|
+
}
|
|
74468
|
+
function blockedRunLogLine(error2, durationMs) {
|
|
74469
|
+
const reason = classifyErrorMessage(error2);
|
|
74470
|
+
const tail = reason === "rate_limit" ? "rate-limit detected, not counted as failure" : reason === "config_issue" ? "config issue (needs setup or sign-in), not counted as failure" : reason === "email_not_received" ? "verification email not received, not counted as failure" : reason === "cancelled" ? "cancelled, not counted as failure" : reason === "interrupted" ? "run interrupted, not counted as failure" : "run error";
|
|
74471
|
+
return `BLOCKED (${durationMs}ms) \u2014 ${tail}`;
|
|
74472
|
+
}
|
|
74216
74473
|
function stripEnvironmentalPrefix(error2) {
|
|
74217
74474
|
for (const prefix of ENVIRONMENTAL_ERROR_PREFIXES) {
|
|
74218
74475
|
if (error2.startsWith(prefix)) {
|
|
@@ -74275,8 +74532,19 @@ function computePassRate(passed, tested) {
|
|
|
74275
74532
|
}
|
|
74276
74533
|
function summarizeHealth(items) {
|
|
74277
74534
|
const c = { passed: 0, failed: 0, errored: 0, environmental: 0, never_run: 0 };
|
|
74535
|
+
let rateLimited = 0;
|
|
74536
|
+
let configIssue = 0;
|
|
74278
74537
|
for (const item of items) {
|
|
74279
|
-
|
|
74538
|
+
const weight = item.weight ?? 1;
|
|
74539
|
+
const bucket = classifyTestHealth(item.run);
|
|
74540
|
+
c[bucket] += weight;
|
|
74541
|
+
if (bucket === "environmental") {
|
|
74542
|
+
const reason = classifyErrorMessage(item.run?.error);
|
|
74543
|
+
if (reason === "rate_limit")
|
|
74544
|
+
rateLimited += weight;
|
|
74545
|
+
else if (isConfigLikeReason(reason))
|
|
74546
|
+
configIssue += weight;
|
|
74547
|
+
}
|
|
74280
74548
|
}
|
|
74281
74549
|
const tested = c.passed + c.failed + c.errored;
|
|
74282
74550
|
return {
|
|
@@ -74284,6 +74552,8 @@ function summarizeHealth(items) {
|
|
|
74284
74552
|
failed: c.failed,
|
|
74285
74553
|
errored: c.errored,
|
|
74286
74554
|
environmental: c.environmental,
|
|
74555
|
+
rateLimited,
|
|
74556
|
+
configIssue,
|
|
74287
74557
|
neverRun: c.never_run,
|
|
74288
74558
|
tested,
|
|
74289
74559
|
total: tested + c.environmental + c.never_run,
|
|
@@ -74320,7 +74590,7 @@ function reportedBugWhere() {
|
|
|
74320
74590
|
function bugReviewStatus(status) {
|
|
74321
74591
|
return status === "QUARANTINED" ? "confirmed" : "needs-review";
|
|
74322
74592
|
}
|
|
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;
|
|
74593
|
+
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, UNVERIFIED_HEAL_CONFIDENCES, NEEDS_REVIEW_TAG, 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, SMS_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;
|
|
74324
74594
|
var init_run_classification = __esm({
|
|
74325
74595
|
"../shared/dist/run-classification.js"() {
|
|
74326
74596
|
"use strict";
|
|
@@ -74340,6 +74610,8 @@ var init_run_classification = __esm({
|
|
|
74340
74610
|
];
|
|
74341
74611
|
isUserCancelledError = isCancelledReason;
|
|
74342
74612
|
HEAL_PATCH_HELD_RUN_ERROR_PREFIX = "Heal patch held";
|
|
74613
|
+
UNVERIFIED_HEAL_CONFIDENCES = /* @__PURE__ */ new Set(["low", "medium"]);
|
|
74614
|
+
NEEDS_REVIEW_TAG = "@needs-review";
|
|
74343
74615
|
RUNNER_INTERRUPT_ERROR_PREFIX = "Runner shutting down";
|
|
74344
74616
|
SERVER_INTERRUPT_ERROR_PREFIX = "Run interrupted by server restart";
|
|
74345
74617
|
RUN_LOST_ERROR_PREFIX = "Runner lost this run";
|
|
@@ -74360,10 +74632,12 @@ var init_run_classification = __esm({
|
|
|
74360
74632
|
"VERIFICATION_EMAIL_HAS_NO_CODE:",
|
|
74361
74633
|
"VERIFICATION_EMAIL_HAS_NO_LINK:"
|
|
74362
74634
|
];
|
|
74635
|
+
SMS_NOT_RECEIVED_PREFIXES = ["VERIFICATION_SMS_NOT_RECEIVED:"];
|
|
74363
74636
|
ENVIRONMENTAL_ERROR_PREFIXES = [
|
|
74364
74637
|
"RATE_LIMIT_BLOCKED:",
|
|
74365
74638
|
"CONFIG_ISSUE:",
|
|
74366
|
-
...EMAIL_NOT_RECEIVED_PREFIXES
|
|
74639
|
+
...EMAIL_NOT_RECEIVED_PREFIXES,
|
|
74640
|
+
...SMS_NOT_RECEIVED_PREFIXES
|
|
74367
74641
|
];
|
|
74368
74642
|
ENVIRONMENTAL_ERROR_STORED_PREFIXES = [
|
|
74369
74643
|
...ENVIRONMENTAL_ERROR_PREFIXES.flatMap((prefix) => [prefix, `Error: ${prefix}`]),
|
|
@@ -76748,6 +77022,19 @@ function googleBrokerUnavailableLine(lines, testError) {
|
|
|
76748
77022
|
}
|
|
76749
77023
|
return last;
|
|
76750
77024
|
}
|
|
77025
|
+
function googleSignInRefusedLine(lines) {
|
|
77026
|
+
let last = null;
|
|
77027
|
+
for (const raw of lines ?? []) {
|
|
77028
|
+
for (const line of String(raw).split("\n")) {
|
|
77029
|
+
const text = line.trim();
|
|
77030
|
+
if (GOOGLE_SIGN_IN_REFUSED.test(text))
|
|
77031
|
+
last = text;
|
|
77032
|
+
else if (GOOGLE_SIGNED_IN.test(text))
|
|
77033
|
+
last = null;
|
|
77034
|
+
}
|
|
77035
|
+
}
|
|
77036
|
+
return last;
|
|
77037
|
+
}
|
|
76751
77038
|
function stepConsoleLines(result) {
|
|
76752
77039
|
const steps = Array.isArray(result) ? result : result && typeof result === "object" && Array.isArray(result.stepResults) ? result.stepResults : [];
|
|
76753
77040
|
return steps.flatMap((step) => {
|
|
@@ -76755,7 +77042,23 @@ function stepConsoleLines(result) {
|
|
|
76755
77042
|
return Array.isArray(logs) ? logs.filter((line) => typeof line === "string") : [];
|
|
76756
77043
|
});
|
|
76757
77044
|
}
|
|
76758
|
-
|
|
77045
|
+
function googleSignInRefusedReason(lines) {
|
|
77046
|
+
let reason = null;
|
|
77047
|
+
for (const raw of lines ?? []) {
|
|
77048
|
+
for (const line of String(raw).split("\n")) {
|
|
77049
|
+
const text = line.trim();
|
|
77050
|
+
if (GOOGLE_SIGNED_IN.test(text)) {
|
|
77051
|
+
reason = null;
|
|
77052
|
+
continue;
|
|
77053
|
+
}
|
|
77054
|
+
const m = GOOGLE_SIGN_IN_ANSWER.exec(text);
|
|
77055
|
+
if (m)
|
|
77056
|
+
reason = m[1];
|
|
77057
|
+
}
|
|
77058
|
+
}
|
|
77059
|
+
return reason;
|
|
77060
|
+
}
|
|
77061
|
+
var GOOGLE_BROKER_UNAVAILABLE, GOOGLE_BROKER_ASKED, GOOGLE_SIGNED_IN, TIMEOUT_ERROR, GOOGLE_SIGN_IN_REFUSED, GOOGLE_SIGN_IN_ANSWER;
|
|
76759
77062
|
var init_google_broker_lines = __esm({
|
|
76760
77063
|
"../shared/dist/google-broker-lines.js"() {
|
|
76761
77064
|
"use strict";
|
|
@@ -76763,6 +77066,8 @@ var init_google_broker_lines = __esm({
|
|
|
76763
77066
|
GOOGLE_BROKER_ASKED = /^\[google-sign-in\] the app started Google sign-in; asking the broker/;
|
|
76764
77067
|
GOOGLE_SIGNED_IN = /^\[google-sign-in\] returned to the app with Google sign-in/;
|
|
76765
77068
|
TIMEOUT_ERROR = /Test timeout of \d+ms exceeded|TimeoutError|Timeout:? \d+ ?ms/i;
|
|
77069
|
+
GOOGLE_SIGN_IN_REFUSED = /^\[google-sign-in\] (?:not_seeded|not_enabled|expired|needs_reseed|device_approval|needs_verification|policy_rejected|unsupported_flow|unsupported_one_tap): /;
|
|
77070
|
+
GOOGLE_SIGN_IN_ANSWER = /^\[google-sign-in\] ([a-z][a-z0-9_]*): /;
|
|
76766
77071
|
}
|
|
76767
77072
|
});
|
|
76768
77073
|
|
|
@@ -76814,22 +77119,87 @@ function isIntentionalNegativeAuthTest(input) {
|
|
|
76814
77119
|
const meta = [input.testName, input.description].filter(Boolean).join(" ");
|
|
76815
77120
|
return matchesAny(meta, INTENTIONAL_NEGATIVE_AUTH);
|
|
76816
77121
|
}
|
|
77122
|
+
function signInStepPassedBeforeFailure(steps) {
|
|
77123
|
+
const list = steps ?? [];
|
|
77124
|
+
const failedAt = list.findIndex((step) => typeof step.status === "string" && step.status !== "passed" && step.status !== "skipped");
|
|
77125
|
+
if (failedAt <= 0)
|
|
77126
|
+
return false;
|
|
77127
|
+
if (SIGN_IN_STEP_TITLE.test(list[failedAt].title ?? ""))
|
|
77128
|
+
return false;
|
|
77129
|
+
return list.slice(0, failedAt).some((step) => step.status === "passed" && SIGN_IN_STEP_TITLE.test(step.title ?? ""));
|
|
77130
|
+
}
|
|
77131
|
+
function loginFormAlertTexts(body) {
|
|
77132
|
+
const text = body.length > ERROR_CONTEXT_CAP ? body.slice(0, ERROR_CONTEXT_CAP) : body;
|
|
77133
|
+
const blocks = [];
|
|
77134
|
+
let open = null;
|
|
77135
|
+
for (const line of text.split("\n")) {
|
|
77136
|
+
const fence = /^```(\w*)$/.exec(line.trim());
|
|
77137
|
+
if (fence) {
|
|
77138
|
+
if (open) {
|
|
77139
|
+
blocks.push(open);
|
|
77140
|
+
open = null;
|
|
77141
|
+
} else if (fence[1].toLowerCase() === "yaml")
|
|
77142
|
+
open = [];
|
|
77143
|
+
continue;
|
|
77144
|
+
}
|
|
77145
|
+
if (open)
|
|
77146
|
+
open.push(line);
|
|
77147
|
+
}
|
|
77148
|
+
const alerts = [];
|
|
77149
|
+
for (const lines of blocks) {
|
|
77150
|
+
if (!lines.some((l) => SNAPSHOT_PASSWORD_FIELD.test(l)))
|
|
77151
|
+
continue;
|
|
77152
|
+
for (let i = 0; i < lines.length && alerts.length < MAX_ALERTS; i++) {
|
|
77153
|
+
const m = SNAPSHOT_ALERT.exec(lines[i]);
|
|
77154
|
+
if (!m)
|
|
77155
|
+
continue;
|
|
77156
|
+
const indent = m[1].length;
|
|
77157
|
+
const parts = [m[2]];
|
|
77158
|
+
let j = i + 1;
|
|
77159
|
+
for (; j < lines.length; j++) {
|
|
77160
|
+
const lead = /^\s*/.exec(lines[j])?.[0].length ?? 0;
|
|
77161
|
+
if (lines[j].trim() === "" || lead <= indent)
|
|
77162
|
+
break;
|
|
77163
|
+
parts.push(lines[j].trim());
|
|
77164
|
+
}
|
|
77165
|
+
alerts.push(parts.join(" ").slice(0, MAX_ALERT_CHARS));
|
|
77166
|
+
i = j - 1;
|
|
77167
|
+
}
|
|
77168
|
+
}
|
|
77169
|
+
return alerts;
|
|
77170
|
+
}
|
|
77171
|
+
function stepLoginFormAlerts(steps) {
|
|
77172
|
+
const out = [];
|
|
77173
|
+
for (const sr of steps ?? []) {
|
|
77174
|
+
for (const a of sr.attachments ?? []) {
|
|
77175
|
+
if (a?.name === "error-context" && typeof a.body === "string")
|
|
77176
|
+
out.push(...loginFormAlertTexts(a.body));
|
|
77177
|
+
}
|
|
77178
|
+
}
|
|
77179
|
+
return out;
|
|
77180
|
+
}
|
|
76817
77181
|
function detectAuthBlock(input) {
|
|
76818
77182
|
const tags = input.tags ?? [];
|
|
76819
77183
|
const isAuthed = tags.some((t) => AUTHED_TAGS.includes(t));
|
|
76820
|
-
|
|
77184
|
+
const signsInInline2 = !isAuthed && codeReadsStoredCredentials(input.code);
|
|
77185
|
+
if (!isAuthed && !signsInInline2)
|
|
76821
77186
|
return NO_DETECTION;
|
|
76822
77187
|
if (isIntentionalNegativeAuthTest(input))
|
|
76823
77188
|
return NO_DETECTION;
|
|
77189
|
+
if (signInStepPassedBeforeFailure(input.stepResults))
|
|
77190
|
+
return NO_DETECTION;
|
|
76824
77191
|
const sources = [];
|
|
76825
|
-
if (
|
|
76826
|
-
|
|
76827
|
-
|
|
76828
|
-
|
|
76829
|
-
|
|
76830
|
-
|
|
76831
|
-
|
|
77192
|
+
if (isAuthed) {
|
|
77193
|
+
if (input.error)
|
|
77194
|
+
sources.push(stripEchoLines(input.error));
|
|
77195
|
+
if (input.logs)
|
|
77196
|
+
sources.push(stripEchoLines(input.logs));
|
|
77197
|
+
for (const sr of input.stepResults ?? []) {
|
|
77198
|
+
if (sr.error)
|
|
77199
|
+
sources.push(stripEchoLines(sr.error));
|
|
77200
|
+
}
|
|
76832
77201
|
}
|
|
77202
|
+
sources.push(...stepLoginFormAlerts(input.stepResults));
|
|
76833
77203
|
for (const text of sources) {
|
|
76834
77204
|
if (!text)
|
|
76835
77205
|
continue;
|
|
@@ -76878,10 +77248,11 @@ function detectApiColdSessionBlock(input) {
|
|
|
76878
77248
|
function coldSessionConfigMessage(context, reason, evidence) {
|
|
76879
77249
|
return `CONFIG_ISSUE: ${context} without valid injected auth (${reason}) \u2014 no session cookie was injected this run. Ensure the project login (auth-setup recipe / prewarm) is configured so the shared session jar warms (a project with no login: set TEST_USER_EMAIL and TEST_USER_PASSWORD in Test Data \u2192 Test Variables so a session can be captured); for endpoints that authenticate with a standing API key or bearer header instead, set them in the project's API_AUTH_HEADERS variable (injected as request headers). Evidence: ${evidence.join("; ")}`;
|
|
76880
77250
|
}
|
|
76881
|
-
var NO_DETECTION, AUTHED_TAGS, LOGIN_CTX, AUTH_BLOCK_SIGNATURES, INTENTIONAL_NEGATIVE_AUTH, ECHO_LINE_RE, UNAUTHORIZED_TEXT_RE;
|
|
77251
|
+
var NO_DETECTION, AUTHED_TAGS, LOGIN_CTX, AUTH_BLOCK_SIGNATURES, INTENTIONAL_NEGATIVE_AUTH, ECHO_LINE_RE, SIGN_IN_STEP_TITLE, ERROR_CONTEXT_CAP, MAX_ALERTS, MAX_ALERT_CHARS, SNAPSHOT_PASSWORD_FIELD, SNAPSHOT_ALERT, UNAUTHORIZED_TEXT_RE;
|
|
76882
77252
|
var init_auth_block_detector = __esm({
|
|
76883
77253
|
"../shared/dist/auth-block-detector.js"() {
|
|
76884
77254
|
"use strict";
|
|
77255
|
+
init_auth_plan();
|
|
76885
77256
|
NO_DETECTION = { detected: false, reason: "", evidence: [] };
|
|
76886
77257
|
AUTHED_TAGS = ["@needs-auth", "@inline-login"];
|
|
76887
77258
|
LOGIN_CTX = "\\b(?:log\\s*in|login|logging\\s+in|sign[\\s-]?in|signing\\s+in|continue)\\b";
|
|
@@ -76891,6 +77262,10 @@ var init_auth_block_detector = __esm({
|
|
|
76891
77262
|
{ reason: "invalid credentials", re: /\b(invalid|incorrect|wrong|bad)\s+(login\s+)?credentials\b/i },
|
|
76892
77263
|
{ reason: "credentials do not match", re: /\bcredentials\b[^\n]{0,40}\b(do(?:es)?\s*n['’]?t|do\s+not)\s+match\b/i },
|
|
76893
77264
|
{ reason: "incorrect email or password", re: /\b(incorrect|invalid|wrong)\s+(email|username)\s+or\s+password\b/i },
|
|
77265
|
+
{ reason: "username and password do not match", re: /\b(?:user\s*name|e-?mail)\s+and\s+password\s+(?:do(?:es)?\s*n['’]?t|do(?:es)?\s+not)\s+match\b/i },
|
|
77266
|
+
// A locked account is a blocker of the same kind: the configured user can't sign in until it is unlocked. The
|
|
77267
|
+
// rate-limit detector keeps the timed lockouts ("temporarily locked", "too many attempts").
|
|
77268
|
+
{ reason: "account locked out", re: /\b(?:user|account)\b[^\n]{0,30}\b(?:has\s+been|is)\s+locked\s+out\b/i },
|
|
76894
77269
|
// Require an EXPLICIT negative (codex #21): the old `(not\s+)?(confirmed|verified)` made the negation
|
|
76895
77270
|
// optional, so a benign "Email verified" success message / feature assertion matched and hid a real
|
|
76896
77271
|
// feature failure as a CONFIG_ISSUE. Only "email not (yet) confirmed/verified" or "unconfirmed/unverified".
|
|
@@ -76922,6 +77297,12 @@ var init_auth_block_detector = __esm({
|
|
|
76922
77297
|
/\b(reject|deny|denied|block(ed)?)\b[^\n]{0,20}\b(login|sign[\s-]?in|auth|credential|password)\b/i
|
|
76923
77298
|
];
|
|
76924
77299
|
ECHO_LINE_RE = /^\s*(?:(?:📋|🎭|🌐|⚙️?)|(?:stderr:\s*|stdout:\s*)?Locator:)/u;
|
|
77300
|
+
SIGN_IN_STEP_TITLE = /\b(?:log(?:ging)?\s*in(?:to)?|sign(?:ing)?[\s-]?in(?:to)?|authenticat(?:e|es|ed|ing|ion))\b/i;
|
|
77301
|
+
ERROR_CONTEXT_CAP = 64 * 1024;
|
|
77302
|
+
MAX_ALERTS = 20;
|
|
77303
|
+
MAX_ALERT_CHARS = 1e3;
|
|
77304
|
+
SNAPSHOT_PASSWORD_FIELD = /^\s*- textbox "[^"\n]{0,80}\bpass(?:word|code)?\b/i;
|
|
77305
|
+
SNAPSHOT_ALERT = /^(\s*)- alert\b(.*)$/;
|
|
76925
77306
|
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;
|
|
76926
77307
|
}
|
|
76927
77308
|
});
|
|
@@ -77356,6 +77737,77 @@ var init_redact_needles = __esm({
|
|
|
77356
77737
|
}
|
|
77357
77738
|
});
|
|
77358
77739
|
|
|
77740
|
+
// ../shared/dist/credential-header-scrub.js
|
|
77741
|
+
function scrubCredentialHeaders(text) {
|
|
77742
|
+
if (text.length < 6)
|
|
77743
|
+
return text;
|
|
77744
|
+
let out = text.replace(HEADER_LINE, (match, keyQuote, name, sep, value) => {
|
|
77745
|
+
if (value === "" || ALREADY_REDACTED.test(value))
|
|
77746
|
+
return match;
|
|
77747
|
+
if (COOKIE_NAME.test(name) && !value.includes("="))
|
|
77748
|
+
return match;
|
|
77749
|
+
if (AUTHORIZATION_NAME.test(name) && WORDS_ONLY.test(value))
|
|
77750
|
+
return match;
|
|
77751
|
+
const q = value[0] === '"' || value[0] === "'" ? value[0] : "";
|
|
77752
|
+
return `${keyQuote}${name}${keyQuote}${sep}${q}${REDACTED2}${q}`;
|
|
77753
|
+
});
|
|
77754
|
+
out = out.replace(SET_COOKIE_PAIR, `$1${REDACTED2}`);
|
|
77755
|
+
return out;
|
|
77756
|
+
}
|
|
77757
|
+
function isCredentialHeaderName(name) {
|
|
77758
|
+
return name.length <= 100 && HEADER_NAME_ONLY.test(name);
|
|
77759
|
+
}
|
|
77760
|
+
function scrubCredentialHeaderValue(value) {
|
|
77761
|
+
if (typeof value === "string")
|
|
77762
|
+
return value === REDACTED2 || value === "" ? value : REDACTED2;
|
|
77763
|
+
if (Array.isArray(value) && value.every((item) => typeof item === "string")) {
|
|
77764
|
+
const next = value.map((item) => item === REDACTED2 || item === "" ? item : REDACTED2);
|
|
77765
|
+
return next.every((item, i) => item === value[i]) ? value : next;
|
|
77766
|
+
}
|
|
77767
|
+
return value;
|
|
77768
|
+
}
|
|
77769
|
+
function scrubCredentialHeadersDeep(value) {
|
|
77770
|
+
if (typeof value === "string")
|
|
77771
|
+
return scrubCredentialHeaders(value);
|
|
77772
|
+
if (Array.isArray(value)) {
|
|
77773
|
+
let changed = false;
|
|
77774
|
+
const next = value.map((item) => {
|
|
77775
|
+
const scrubbed = scrubCredentialHeadersDeep(item);
|
|
77776
|
+
if (scrubbed !== item)
|
|
77777
|
+
changed = true;
|
|
77778
|
+
return scrubbed;
|
|
77779
|
+
});
|
|
77780
|
+
return changed ? next : value;
|
|
77781
|
+
}
|
|
77782
|
+
if (value !== null && typeof value === "object") {
|
|
77783
|
+
let changed = false;
|
|
77784
|
+
const next = {};
|
|
77785
|
+
for (const [k, v] of Object.entries(value)) {
|
|
77786
|
+
const scrubbed = isCredentialHeaderName(k) ? scrubCredentialHeaderValue(v) : scrubCredentialHeadersDeep(v);
|
|
77787
|
+
if (scrubbed !== v)
|
|
77788
|
+
changed = true;
|
|
77789
|
+
next[k] = scrubbed;
|
|
77790
|
+
}
|
|
77791
|
+
return changed ? next : value;
|
|
77792
|
+
}
|
|
77793
|
+
return value;
|
|
77794
|
+
}
|
|
77795
|
+
var REDACTED2, HEADER_NAMES, COOKIE_NAME, AUTHORIZATION_NAME, WORDS_ONLY, HEADER_NAME_ONLY, HEADER_LINE, ALREADY_REDACTED, SET_COOKIE_PAIR;
|
|
77796
|
+
var init_credential_header_scrub = __esm({
|
|
77797
|
+
"../shared/dist/credential-header-scrub.js"() {
|
|
77798
|
+
"use strict";
|
|
77799
|
+
REDACTED2 = "[REDACTED]";
|
|
77800
|
+
HEADER_NAMES = "cookie2?|set-cookie2?|proxy-authorization|authorization|api-?key|(?:x-)?(?:csrf|xsrf)[a-z0-9-]{0,30}|x-[a-z0-9-]{0,40}?(?:token|session|secret|key|auth)[a-z0-9-]{0,40}";
|
|
77801
|
+
COOKIE_NAME = /^(?:set-)?cookie2?$/i;
|
|
77802
|
+
AUTHORIZATION_NAME = /^(?:proxy-)?authorization$/i;
|
|
77803
|
+
WORDS_ONLY = /^[A-Za-z]+(?: [A-Za-z]+){0,3}$/;
|
|
77804
|
+
HEADER_NAME_ONLY = new RegExp(`^(?:${HEADER_NAMES})$`, "i");
|
|
77805
|
+
HEADER_LINE = new RegExp(`(?<![A-Za-z0-9_-])(["']?)(${HEADER_NAMES})\\1(\\s*:\\s*)("(?:[^"\\\\\\r\\n]|\\\\.)*"|'(?:[^'\\\\\\r\\n]|\\\\.)*'|[^\\r\\n\\x1b]*)`, "gi");
|
|
77806
|
+
ALREADY_REDACTED = /^["']?(?:[A-Za-z][\w-]*\s+)?\[REDACTED\]["']?[,;]?\s*$/;
|
|
77807
|
+
SET_COOKIE_PAIR = /(?<![A-Za-z0-9_-])([A-Za-z0-9_.%-]{1,64}=)(?!\[REDACTED\])([^\s;,"'<>]{6,2048})(?=;\s*(?:Path|Domain|Expires|Max-Age|HttpOnly|Secure|SameSite|Partitioned)\b)/gi;
|
|
77808
|
+
}
|
|
77809
|
+
});
|
|
77810
|
+
|
|
77359
77811
|
// ../shared/dist/deepgram-voices.js
|
|
77360
77812
|
function voice(family, name, gender, accent, description) {
|
|
77361
77813
|
const label = name.charAt(0).toUpperCase() + name.slice(1);
|
|
@@ -77932,13 +78384,13 @@ function isSensitiveQueryKey(key) {
|
|
|
77932
78384
|
return SENSITIVE_QUERY_KEY_RE.test(key);
|
|
77933
78385
|
}
|
|
77934
78386
|
function redactSecretValues(value) {
|
|
77935
|
-
return value.replace(MCP_SECRET_VALUE_RE,
|
|
78387
|
+
return value.replace(MCP_SECRET_VALUE_RE, REDACTED3);
|
|
77936
78388
|
}
|
|
77937
78389
|
function scrubReturnUrlValue(value, depth) {
|
|
77938
78390
|
if (!/[?%]/.test(value))
|
|
77939
78391
|
return value;
|
|
77940
78392
|
if (depth >= MAX_NESTED_URL_DEPTH)
|
|
77941
|
-
return
|
|
78393
|
+
return REDACTED3;
|
|
77942
78394
|
const q = value.indexOf("?");
|
|
77943
78395
|
if (q !== -1) {
|
|
77944
78396
|
const hashIdx = value.indexOf("#", q);
|
|
@@ -77960,7 +78412,7 @@ function scrubReturnUrlValue(value, depth) {
|
|
|
77960
78412
|
try {
|
|
77961
78413
|
return encodeURIComponent(scrubbed);
|
|
77962
78414
|
} catch {
|
|
77963
|
-
return
|
|
78415
|
+
return REDACTED3;
|
|
77964
78416
|
}
|
|
77965
78417
|
}
|
|
77966
78418
|
function scrubQuery(search, depth) {
|
|
@@ -77976,7 +78428,7 @@ function scrubQuery(search, depth) {
|
|
|
77976
78428
|
params.forEach((value, key) => {
|
|
77977
78429
|
let scrubbed = value;
|
|
77978
78430
|
if (isSensitiveQueryKey(key)) {
|
|
77979
|
-
scrubbed =
|
|
78431
|
+
scrubbed = REDACTED3;
|
|
77980
78432
|
} else {
|
|
77981
78433
|
if (RETURN_URL_QUERY_KEY_RE.test(key))
|
|
77982
78434
|
scrubbed = scrubReturnUrlValue(scrubbed, depth);
|
|
@@ -78088,12 +78540,12 @@ function scrubUrlPropertyBag(props) {
|
|
|
78088
78540
|
} catch {
|
|
78089
78541
|
}
|
|
78090
78542
|
}
|
|
78091
|
-
var SENSITIVE_QUERY_KEY_RE,
|
|
78543
|
+
var SENSITIVE_QUERY_KEY_RE, REDACTED3, MCP_SECRET_VALUE_RE, RETURN_URL_QUERY_KEY_RE, MAX_NESTED_URL_DEPTH, MAX_PROPERTY_SWEEP_DEPTH;
|
|
78092
78544
|
var init_analytics_url = __esm({
|
|
78093
78545
|
"../shared/dist/analytics-url.js"() {
|
|
78094
78546
|
"use strict";
|
|
78095
78547
|
SENSITIVE_QUERY_KEY_RE = /^(access_token|refresh_token|id_token|token|code|state|password|secret|api[_-]?key|auth|authorization|session|jwt|otp|email|phone|magic[_-]?link)$|token|secret|password|credential|email|phone|(^|[_-])(otp|verification|auth)[_-]?code($|[_-])|(^|[_-])(state|session|grant)$/i;
|
|
78096
|
-
|
|
78548
|
+
REDACTED3 = "[redacted]";
|
|
78097
78549
|
MCP_SECRET_VALUE_RE = /mcp_(consent|code|at|rt)_[A-Za-z0-9]+/g;
|
|
78098
78550
|
RETURN_URL_QUERY_KEY_RE = /^(next|redirect|return|continue)([_-]?(to|url|uri|path))?$/i;
|
|
78099
78551
|
MAX_NESTED_URL_DEPTH = 5;
|
|
@@ -80923,8 +81375,19 @@ function successContradicted(text) {
|
|
|
80923
81375
|
}
|
|
80924
81376
|
return SUCCESS_NO_STATUS_RE.test(text) || OFF_BY_RE.test(text);
|
|
80925
81377
|
}
|
|
81378
|
+
function negatedSafeguard(text) {
|
|
81379
|
+
for (const match of matches(NEGATED_SAFEGUARD_RE, text)) {
|
|
81380
|
+
if (!NOT_KEPT_RE.test(match[1]))
|
|
81381
|
+
return true;
|
|
81382
|
+
const head = text.slice(Math.max(0, match.index - SAFEGUARD_LOOKBEHIND), match.index);
|
|
81383
|
+
const sentence = head.slice(Math.max(head.lastIndexOf("."), head.lastIndexOf(";"), head.lastIndexOf("\n")) + 1);
|
|
81384
|
+
if (!REFUSED_INPUT_RE.test(sentence))
|
|
81385
|
+
return true;
|
|
81386
|
+
}
|
|
81387
|
+
return false;
|
|
81388
|
+
}
|
|
80926
81389
|
function claimsDefect(text) {
|
|
80927
|
-
if (BUG_LABEL_RE.test(text) || SILENT_RE.test(text) || CONCESSION_RE.test(text) || successContradicted(text) ||
|
|
81390
|
+
if (BUG_LABEL_RE.test(text) || SILENT_RE.test(text) || CONCESSION_RE.test(text) || successContradicted(text) || negatedSafeguard(text)) {
|
|
80928
81391
|
return true;
|
|
80929
81392
|
}
|
|
80930
81393
|
return BAD_VALUE_RE.test(text) && !REFUSAL_RE.test(text);
|
|
@@ -80932,7 +81395,7 @@ function claimsDefect(text) {
|
|
|
80932
81395
|
function hasTestFailContract(code) {
|
|
80933
81396
|
return TEST_FAIL_CONTRACT_RE.test(code);
|
|
80934
81397
|
}
|
|
80935
|
-
var BUG_LABEL_RE, SILENT_RE, CONCESSION_RE, SUCCESS_REPORT, SUCCESS_CONTRADICTED_RE, CONTRADICTION_VETO_RE, NOTHING_PROVIDED_RE, UNTOUCHED_SUBSETS, ACTION_LOOKBEHIND, TRAILING_ACTION_RE, ADJECTIVE_BEFORE_NOUN_RE, SUCCESS_SAME_STATE_RE, GENERIC_REPORT_RE, SAME_STATE, OTHER_ITEM_RE, SUCCESS_STATUS_RE, STATUS_ACTION_RE, SUCCESS_WITHOUT_EFFECT_RE, COUNT_UNCHANGED_RE, CLEARING_ACTION_RE, NOT_A_CLEARING_RE, SUCCESS_NO_STATUS_RE, OFF_BY_RE, NEGATED_SAFEGUARD_RE, BAD_VALUE_RE, REFUSAL_RE, TEST_FAIL_CONTRACT_RE;
|
|
81398
|
+
var BUG_LABEL_RE, SILENT_RE, CONCESSION_RE, SUCCESS_REPORT, SUCCESS_CONTRADICTED_RE, CONTRADICTION_VETO_RE, NOTHING_PROVIDED_RE, UNTOUCHED_SUBSETS, ACTION_LOOKBEHIND, TRAILING_ACTION_RE, ADJECTIVE_BEFORE_NOUN_RE, SUCCESS_SAME_STATE_RE, GENERIC_REPORT_RE, SAME_STATE, OTHER_ITEM_RE, SUCCESS_STATUS_RE, STATUS_ACTION_RE, SUCCESS_WITHOUT_EFFECT_RE, COUNT_UNCHANGED_RE, CLEARING_ACTION_RE, NOT_A_CLEARING_RE, SUCCESS_NO_STATUS_RE, OFF_BY_RE, NEGATED_SAFEGUARD_RE, NOT_KEPT_RE, REFUSED_INPUT_RE, SAFEGUARD_LOOKBEHIND, BAD_VALUE_RE, REFUSAL_RE, TEST_FAIL_CONTRACT_RE;
|
|
80936
81399
|
var init_claims_defect = __esm({
|
|
80937
81400
|
"../shared/dist/claims-defect.js"() {
|
|
80938
81401
|
"use strict";
|
|
@@ -80976,7 +81439,10 @@ var init_claims_defect = __esm({
|
|
|
80976
81439
|
NOT_A_CLEARING_RE = /\b(?:cancel|refresh|reload|preview|open|view|fail|hover|scroll|sort|filter|search)\w*/i;
|
|
80977
81440
|
SUCCESS_NO_STATUS_RE = /\bsuccess\w*\b[^.;\n]{0,30}?\b(?:(?:do|does|did) not|don't|doesn't|didn't) (?:change|update|move)\b[^.;\n]{0,20}?\bstatus\b/i;
|
|
80978
81441
|
OFF_BY_RE = /\boff[- ]by[- ](?:one|two|\d{1,3})\b/i;
|
|
80979
|
-
NEGATED_SAFEGUARD_RE = /\bnot (
|
|
81442
|
+
NEGATED_SAFEGUARD_RE = /\bnot (rejected|validated|enforced|applied|persisted|saved)\b/gi;
|
|
81443
|
+
NOT_KEPT_RE = /^(?:applied|persisted|saved)$/i;
|
|
81444
|
+
REFUSED_INPUT_RE = /\b(?:blank|empty|whitespace|invalid|malformed|expired|duplicate[sd]?|too (?:long|short)|cancel(?:s|led|ed|ling|ing)?|discard\w*|escape)\b/i;
|
|
81445
|
+
SAFEGUARD_LOOKBEHIND = 80;
|
|
80980
81446
|
BAD_VALUE_RE = /\b(?:incorrect|wrong|stale|negative|epoch|unix) (?:total|amount|value|date|count|price|label|plan|balance)\b/i;
|
|
80981
81447
|
REFUSAL_RE = /\b(?<!not )(?:rejected|refused|denied|blocked|disallowed|prevented)\b|\breturns? (?:4\d\d|an? (?:error|validation))\b|\bshows (?:an? )?(?:error|validation)\b/i;
|
|
80982
81448
|
TEST_FAIL_CONTRACT_RE = /\btest\.fail\s{0,20}\(/;
|
|
@@ -81835,7 +82301,7 @@ function findExpectCalls(code) {
|
|
|
81835
82301
|
return out;
|
|
81836
82302
|
}
|
|
81837
82303
|
function countExpectCalls(code) {
|
|
81838
|
-
return findExpectCalls(stripComments2(code)).length;
|
|
82304
|
+
return findExpectCalls(stripComments2(withExpectAliasesAsExpect(code))).length;
|
|
81839
82305
|
}
|
|
81840
82306
|
function countActionCalls(code) {
|
|
81841
82307
|
return [...stripComments2(code).matchAll(ACTION_CALL)].length;
|
|
@@ -84164,6 +84630,7 @@ var init_test_authoring_quality = __esm({
|
|
|
84164
84630
|
"../shared/dist/test-authoring-quality.js"() {
|
|
84165
84631
|
"use strict";
|
|
84166
84632
|
init_claims_defect();
|
|
84633
|
+
init_expect_call();
|
|
84167
84634
|
init_readiness_poll();
|
|
84168
84635
|
init_persistence_reread();
|
|
84169
84636
|
init_write_response_check();
|
|
@@ -84290,7 +84757,7 @@ var init_test_authoring_quality = __esm({
|
|
|
84290
84757
|
MAX_BALANCED_SCAN = 2048;
|
|
84291
84758
|
MAX_CALLS = 500;
|
|
84292
84759
|
MAX_SEEN_SCAN = 200;
|
|
84293
|
-
ACTION_CALL = /\.(?:click|dblclick|fill|press|pressSequentially|type|check|uncheck|selectOption|setInputFiles|hover|tap|dragTo|goto)\s*\(/g;
|
|
84760
|
+
ACTION_CALL = /\.(?:(?:click|dblclick|fill|clear|press|pressSequentially|type|check|uncheck|setChecked|selectOption|setInputFiles|hover|tap|dragTo|dragAndDrop|dispatchEvent|goto)|(?:keyboard|mouse)\s*\.\s*(?:down|up|insertText|move|wheel))\s*\(/g;
|
|
84294
84761
|
BY_NAME_LOCATOR = /\.getByRole\(\s{0,20}['"][^'"\n]{1,100}['"]\s{0,20},\s{0,20}\{[^}\n]{0,200}\bname\s{0,20}:|\.getByText\(|\.getByLabel\(|\.getByTitle\(|\.getByAltText\(|\.getByPlaceholder\(/;
|
|
84295
84762
|
ACTION_AFTER = /^\s{0,20}\.\s{0,20}(?:click|fill|check|uncheck|press|type|hover|focus|selectOption|setInputFiles|dblclick|tap)\s{0,20}\(/;
|
|
84296
84763
|
MAX_CONTACTS = 200;
|
|
@@ -85799,7 +86266,7 @@ function credentialEntries(maps) {
|
|
|
85799
86266
|
}
|
|
85800
86267
|
function replacePattern(value, form) {
|
|
85801
86268
|
const escaped = form.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
85802
|
-
return
|
|
86269
|
+
return value.length < WHOLE_WORD_BELOW ? `(?<![A-Za-z0-9_])${escaped}(?![A-Za-z0-9_])` : escaped;
|
|
85803
86270
|
}
|
|
85804
86271
|
function findCredentialTextLeftover(text, maps) {
|
|
85805
86272
|
const bare = text.split(WITHHELD_CREDENTIAL_TEXT).join(" ").replace(REFERENCE, " ").toLowerCase();
|
|
@@ -85813,11 +86280,17 @@ function scrubCredentialText(text, maps) {
|
|
|
85813
86280
|
const entries = credentialEntries(maps);
|
|
85814
86281
|
if (entries.length === 0)
|
|
85815
86282
|
return text;
|
|
85816
|
-
|
|
86283
|
+
const alternatives = [];
|
|
85817
86284
|
for (const [key, value] of entries) {
|
|
85818
86285
|
for (const form of credentialValueForms(value))
|
|
85819
|
-
|
|
86286
|
+
alternatives.push({ pattern: replacePattern(value, form), key, length: form.length });
|
|
85820
86287
|
}
|
|
86288
|
+
alternatives.sort((a, b) => b.length - a.length);
|
|
86289
|
+
const matcher = new RegExp([REFERENCE.source, ...alternatives.map((alt) => `(${alt.pattern})`)].join("|"), "gi");
|
|
86290
|
+
const out = text.replace(matcher, (...args) => {
|
|
86291
|
+
const index = args.slice(1, 1 + alternatives.length).findIndex((group) => group !== void 0);
|
|
86292
|
+
return index < 0 ? String(args[0]) : `{{secret:${alternatives[index].key}}}`;
|
|
86293
|
+
});
|
|
85821
86294
|
return findCredentialTextLeftover(out, maps) ? WITHHELD_CREDENTIAL_TEXT : out;
|
|
85822
86295
|
}
|
|
85823
86296
|
function scrubCredentialStringsIn(value, maps) {
|
|
@@ -86311,10 +86784,24 @@ function onlyUrlAfter(code, writeAt) {
|
|
|
86311
86784
|
i = at + 6;
|
|
86312
86785
|
}
|
|
86313
86786
|
}
|
|
86787
|
+
function readsOrderAfter(code, writeAt) {
|
|
86788
|
+
const rest = code.slice(writeAt + 1);
|
|
86789
|
+
if (ORDER_READ_MARKERS.some((m) => rest.includes(m)) && nextExpect(code, writeAt + 1) >= 0)
|
|
86790
|
+
return true;
|
|
86791
|
+
for (let i = writeAt + 1; ; ) {
|
|
86792
|
+
const at = nextExpect(code, i);
|
|
86793
|
+
if (at < 0)
|
|
86794
|
+
return false;
|
|
86795
|
+
if (ORDERED_ARRAY_EXPECT.test(expectStatement(code, at)))
|
|
86796
|
+
return true;
|
|
86797
|
+
i = at + 6;
|
|
86798
|
+
}
|
|
86799
|
+
}
|
|
86314
86800
|
function assessTitlePromiseShape(claimText, code) {
|
|
86315
86801
|
const persistence = PERSISTENCE_RE.test(claimText);
|
|
86316
86802
|
const refusal = REFUSAL_RE2.test(claimText);
|
|
86317
|
-
|
|
86803
|
+
const order = ORDER_RE.test(claimText) || ORDER_RE_CASED.test(claimText);
|
|
86804
|
+
if (!persistence && !refusal && !order)
|
|
86318
86805
|
return [];
|
|
86319
86806
|
const blank = blankCommentsAndStringLiterals(code);
|
|
86320
86807
|
const writeAt = proofAnchor(blank);
|
|
@@ -86327,9 +86814,12 @@ function assessTitlePromiseShape(claimText, code) {
|
|
|
86327
86814
|
if (refusal && onlyUrlAfter(blank, writeAt)) {
|
|
86328
86815
|
findings.push({ rule: "rejection-only-url", reason: REFUSAL_REASON });
|
|
86329
86816
|
}
|
|
86817
|
+
if (order && !readsOrderAfter(blank, writeAt)) {
|
|
86818
|
+
findings.push({ rule: "sort-without-order", reason: ORDER_REASON });
|
|
86819
|
+
}
|
|
86330
86820
|
return findings;
|
|
86331
86821
|
}
|
|
86332
|
-
var PERSIST_REASON, REFUSAL_REASON, PERSISTENCE_RE, REFUSAL_RE2, WRITE_MARKERS, VALUE_WRITE_MARKERS, REREAD_MARKERS;
|
|
86822
|
+
var PERSIST_REASON, REFUSAL_REASON, PERSISTENCE_RE, REFUSAL_RE2, ORDER_REASON, ORDER_RE, ORDER_RE_CASED, ORDER_READ_MARKERS, ORDERED_ARRAY_EXPECT, WRITE_MARKERS, VALUE_WRITE_MARKERS, REREAD_MARKERS;
|
|
86333
86823
|
var init_title_promise_shape = __esm({
|
|
86334
86824
|
"../shared/dist/title-promise-shape.js"() {
|
|
86335
86825
|
"use strict";
|
|
@@ -86338,6 +86828,21 @@ var init_title_promise_shape = __esm({
|
|
|
86338
86828
|
REFUSAL_REASON = "The title says the app refuses the input, but the only check after submitting is the URL: assert the error message, the field's invalid state or the response status.";
|
|
86339
86829
|
PERSISTENCE_RE = /\b(?:is|are|gets|stays)\s{1,20}saved\b|\b(?:is|are)\s{1,20}persisted\b|\bpersists\s{1,20}(?:after|across|through)\s{1,20}(?:a\s{1,20})?(?:reloads?|refresh(?:es)?|sessions?)\b|\bis\s{1,20}(?:stored|kept|remembered)\b|\bafter\s{1,20}(?:a\s{1,20})?reload\b|\bafter\s{1,20}refresh\b|\bsurvives\s{1,20}(?:a\s{1,20})?reload\b/i;
|
|
86340
86830
|
REFUSAL_RE2 = /\b(?:rejects|rejected|refuses|refused|prevents|prevented|disallows)\b|\b(?:is|are|gets)\s{1,20}blocked\b|\bis\s{1,20}denied\b|\bshows\s{1,20}an\s{1,20}error\b|\bshows\s{1,20}a\s{1,20}validation\b|\bshows\s{1,20}validation\b|\breturns\s{1,20}4\d\d\b/i;
|
|
86831
|
+
ORDER_REASON = "The title says the list is sorted, but no check after the sort reads the order: assert the items in order (toHaveText([...]) on the list, the first and last item, or allTextContents() compared with a sorted copy).";
|
|
86832
|
+
ORDER_RE = /\bsort(?:s|ed|ing)?\b[^\n.]{0,60}?\bby\b|\b(?:ascending|descending)\b|\b(?:low|lowest)\s{1,20}to\s{1,20}(?:high|highest)\b|\b(?:high|highest)\s{1,20}to\s{1,20}(?:low|lowest)\b|\balphabetical(?:ly)?\b|\b(?:newest|oldest)\s{1,20}first\b/i;
|
|
86833
|
+
ORDER_RE_CASED = /\b[AZ]\s{0,3}(?:to|-|→)\s{0,3}[AZ]\b/;
|
|
86834
|
+
ORDER_READ_MARKERS = [
|
|
86835
|
+
".allTextContents(",
|
|
86836
|
+
".allInnerTexts(",
|
|
86837
|
+
".evaluateAll(",
|
|
86838
|
+
".toMatchAriaSnapshot(",
|
|
86839
|
+
".sort(",
|
|
86840
|
+
".toSorted(",
|
|
86841
|
+
".first()",
|
|
86842
|
+
".last()",
|
|
86843
|
+
".nth("
|
|
86844
|
+
];
|
|
86845
|
+
ORDERED_ARRAY_EXPECT = /\.(?:toHaveText|toContainText|toEqual|toStrictEqual)\s*\(\s*\[/;
|
|
86341
86846
|
WRITE_MARKERS = [
|
|
86342
86847
|
".fill(",
|
|
86343
86848
|
".click(",
|
|
@@ -86669,7 +87174,7 @@ function assertionsReadVisibleContent(code) {
|
|
|
86669
87174
|
});
|
|
86670
87175
|
}
|
|
86671
87176
|
function isLegacyReviewFlag(tags, activity) {
|
|
86672
|
-
const flagged = tags.includes(
|
|
87177
|
+
const flagged = tags.includes(NEEDS_REVIEW_TAG2) || activity?.needsReview === true;
|
|
86673
87178
|
const source = activity?.needsReviewSource;
|
|
86674
87179
|
return flagged && !(typeof source === "string" && source in SOURCE_RANK);
|
|
86675
87180
|
}
|
|
@@ -86731,7 +87236,7 @@ function recheckGeneratorNotes(notes, input) {
|
|
|
86731
87236
|
}
|
|
86732
87237
|
function reviewHolds(tags, activity, cleared = /* @__PURE__ */ new Set()) {
|
|
86733
87238
|
const out = [];
|
|
86734
|
-
const tagged = tags.includes(
|
|
87239
|
+
const tagged = tags.includes(NEEDS_REVIEW_TAG2);
|
|
86735
87240
|
const generatorAsked = activity?.needsReview === true;
|
|
86736
87241
|
if (tagged) {
|
|
86737
87242
|
if (activity?.needsReviewSource === "human")
|
|
@@ -86791,7 +87296,7 @@ function evaluatePromotionGate(input, checks = PROMOTION_QUALITY_CHECKS) {
|
|
|
86791
87296
|
...suspiciousTagged ? { suspiciousPass: { mode: suspicious, covered: suspiciousCovered, wouldHold: suspiciousHold } } : {}
|
|
86792
87297
|
};
|
|
86793
87298
|
}
|
|
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,
|
|
87299
|
+
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_TAG2, count2, RECHECKED_NOTES, EVIDENCE_NOTE_PREFIXES, PENDING_RECHECK_NOTE_PREFIXES, STRENGTH_RANK;
|
|
86795
87300
|
var init_promotion_quality_gate = __esm({
|
|
86796
87301
|
"../shared/dist/promotion-quality-gate.js"() {
|
|
86797
87302
|
"use strict";
|
|
@@ -86810,8 +87315,8 @@ var init_promotion_quality_gate = __esm({
|
|
|
86810
87315
|
SOURCE_RANK = { generator: 0, classifier: 0, healer: 1, human: 2 };
|
|
86811
87316
|
strengthCheck = {
|
|
86812
87317
|
id: "assertion-strength",
|
|
86813
|
-
run({ code, tags, strengthGate, flagContradictedAdditions, lastActionProof }) {
|
|
86814
|
-
const verdict = validateAssertionStrength(code, { flagContradictedAdditions: flagContradictedAdditions === true, lastActionProof });
|
|
87318
|
+
run({ code, tags, strengthGate, flagContradictedAdditions, lastActionProof, absenceProof }) {
|
|
87319
|
+
const verdict = validateAssertionStrength(code, { flagContradictedAdditions: flagContradictedAdditions === true, lastActionProof, absenceProof });
|
|
86815
87320
|
if (verdict.severity === "route-bug")
|
|
86816
87321
|
return [{ check: "route-bug" }];
|
|
86817
87322
|
const authDowngrade = verdict.severity === "downgrade" && tags.some((t) => t.toLowerCase() === "@auth");
|
|
@@ -87069,7 +87574,7 @@ ${goalText}`);
|
|
|
87069
87574
|
NOT_CONTENT_MATCHER = /\.(?:toHaveURL|toHaveTitle|toBeOK)\s*\(|\bwaitForURL\s*\(|\.(?:status|ok)\s*\(\s*\)/;
|
|
87070
87575
|
CONTENT_PROOF = /* @__PURE__ */ new Set(["controlled", "revealed", "value"]);
|
|
87071
87576
|
NAMED_ELEMENT = /\bgetByRole\s*\(\s*['"`](?!(?:navigation|banner|main|contentinfo|complementary|region|search)['"`])\w{1,30}['"`]\s*,\s*\{[^}]{0,200}?\bname\s*:\s*(['"`])[^'"`$\n]{1,200}\1|\bgetByLabel\s*\(\s*(['"`])[^'"`$\n]{1,200}\2/;
|
|
87072
|
-
|
|
87577
|
+
NEEDS_REVIEW_TAG2 = "@needs-review";
|
|
87073
87578
|
count2 = (v) => typeof v === "number" && Number.isFinite(v) ? v : 0;
|
|
87074
87579
|
RECHECKED_NOTES = [
|
|
87075
87580
|
{
|
|
@@ -87190,11 +87695,18 @@ var init_regex_alternation = __esm({
|
|
|
87190
87695
|
function isPageEvidenceEntry(entry) {
|
|
87191
87696
|
return typeof entry === "object" && entry !== null && entry.outcomeType === PAGE_LOADING_OUTCOME_TYPE;
|
|
87192
87697
|
}
|
|
87193
|
-
|
|
87698
|
+
function pageScreenshotKey(projectId, safeName, stillLoading = false) {
|
|
87699
|
+
return `discovery/${projectId}/screenshots/${stillLoading ? `${STILL_LOADING_SCREENSHOT_DIR}/` : ""}${safeName}.png`;
|
|
87700
|
+
}
|
|
87701
|
+
function isStillLoadingScreenshotKey(key) {
|
|
87702
|
+
return typeof key === "string" && key.includes(`/screenshots/${STILL_LOADING_SCREENSHOT_DIR}/`);
|
|
87703
|
+
}
|
|
87704
|
+
var PAGE_LOADING_OUTCOME_TYPE, STILL_LOADING_SCREENSHOT_DIR;
|
|
87194
87705
|
var init_page_evidence = __esm({
|
|
87195
87706
|
"../shared/dist/page-evidence.js"() {
|
|
87196
87707
|
"use strict";
|
|
87197
87708
|
PAGE_LOADING_OUTCOME_TYPE = "LOADING";
|
|
87709
|
+
STILL_LOADING_SCREENSHOT_DIR = "still-loading";
|
|
87198
87710
|
}
|
|
87199
87711
|
});
|
|
87200
87712
|
|
|
@@ -87599,11 +88111,13 @@ __export(dist_exports, {
|
|
|
87599
88111
|
SERVER_INTERRUPT_ERROR_PREFIX: () => SERVER_INTERRUPT_ERROR_PREFIX,
|
|
87600
88112
|
SHARED_PRICING_PLAN_MAP: () => SHARED_PRICING_PLAN_MAP,
|
|
87601
88113
|
SHARED_SERVER_APPLICATION_NAME: () => SHARED_SERVER_APPLICATION_NAME,
|
|
88114
|
+
SMS_NOT_RECEIVED_PREFIXES: () => SMS_NOT_RECEIVED_PREFIXES,
|
|
87602
88115
|
SPEND_SOURCE_KEY: () => SPEND_SOURCE_KEY,
|
|
87603
88116
|
SPEND_SOURCE_SERVER: () => SPEND_SOURCE_SERVER,
|
|
87604
88117
|
STATED_LIMITS_VERSION: () => STATED_LIMITS_VERSION,
|
|
87605
88118
|
STATED_PATTERN_MAX: () => STATED_PATTERN_MAX,
|
|
87606
88119
|
STATIC_STANDARD_MIN_INTERACTIVE: () => STATIC_STANDARD_MIN_INTERACTIVE,
|
|
88120
|
+
STILL_LOADING_SCREENSHOT_DIR: () => STILL_LOADING_SCREENSHOT_DIR,
|
|
87607
88121
|
STT_MODEL_OPTIONS: () => STT_MODEL_OPTIONS,
|
|
87608
88122
|
SUCCESS_NOTICE_TEXT: () => SUCCESS_NOTICE_TEXT,
|
|
87609
88123
|
SUPPORT_EMAIL: () => SUPPORT_EMAIL,
|
|
@@ -87631,6 +88145,7 @@ __export(dist_exports, {
|
|
|
87631
88145
|
TTS_VOICE_OPTIONS: () => TTS_VOICE_OPTIONS,
|
|
87632
88146
|
UI_VARIANTS: () => UI_VARIANTS,
|
|
87633
88147
|
UNEXPECTED_PASS_ERROR_PREFIX: () => UNEXPECTED_PASS_ERROR_PREFIX,
|
|
88148
|
+
UNVERIFIED_HEAL_CONFIDENCES: () => UNVERIFIED_HEAL_CONFIDENCES,
|
|
87634
88149
|
USER_CANCELLED_RUN_ERROR: () => USER_CANCELLED_RUN_ERROR,
|
|
87635
88150
|
VISUAL_MASK_SELECTORS_MAX: () => VISUAL_MASK_SELECTORS_MAX,
|
|
87636
88151
|
VISUAL_MASK_SELECTOR_FORBIDDEN: () => VISUAL_MASK_SELECTOR_FORBIDDEN,
|
|
@@ -87684,6 +88199,7 @@ __export(dist_exports, {
|
|
|
87684
88199
|
blankBlockComments: () => blankBlockComments3,
|
|
87685
88200
|
blankCommentsAndStringLiterals: () => blankCommentsAndStringLiterals,
|
|
87686
88201
|
blankKeepingLines: () => blankKeepingLines,
|
|
88202
|
+
blockedRunLogLine: () => blockedRunLogLine,
|
|
87687
88203
|
boundedCallCostUsd: () => boundedCallCostUsd,
|
|
87688
88204
|
brokerResponseBody: () => brokerResponseBody,
|
|
87689
88205
|
bugFoundQuarantineWhere: () => bugFoundQuarantineWhere,
|
|
@@ -87789,6 +88305,7 @@ __export(dist_exports, {
|
|
|
87789
88305
|
evaluatePromotionGate: () => evaluatePromotionGate,
|
|
87790
88306
|
excludeCancelledRunsAnd: () => excludeCancelledRunsAnd,
|
|
87791
88307
|
excludeCancelledRunsWhere: () => excludeCancelledRunsWhere,
|
|
88308
|
+
expectAliasNames: () => expectAliasNames,
|
|
87792
88309
|
explicitAgenticCliOverrideError: () => explicitAgenticCliOverrideError,
|
|
87793
88310
|
extractAssertedControlSignatures: () => extractAssertedControlSignatures,
|
|
87794
88311
|
extractMuseAssistantJson: () => extractMuseAssistantJson,
|
|
@@ -87855,6 +88372,8 @@ __export(dist_exports, {
|
|
|
87855
88372
|
googleGisRequestUrl: () => googleGisRequestUrl,
|
|
87856
88373
|
googleSignInLimitLines: () => googleSignInLimitLines,
|
|
87857
88374
|
googleSignInPolicyProblems: () => googleSignInPolicyProblems,
|
|
88375
|
+
googleSignInRefusedLine: () => googleSignInRefusedLine,
|
|
88376
|
+
googleSignInRefusedReason: () => googleSignInRefusedReason,
|
|
87858
88377
|
hasCrossPlatformIdentity: () => hasCrossPlatformIdentity,
|
|
87859
88378
|
hasEncodedRequestBody: () => hasEncodedRequestBody,
|
|
87860
88379
|
hasEngineSpecParts: () => hasEngineSpecParts,
|
|
@@ -87898,6 +88417,7 @@ __export(dist_exports, {
|
|
|
87898
88417
|
isCodeFactNote: () => isCodeFactNote,
|
|
87899
88418
|
isConfigLikeReason: () => isConfigLikeReason,
|
|
87900
88419
|
isCountedFailure: () => isCountedFailure,
|
|
88420
|
+
isCredentialHeaderName: () => isCredentialHeaderName,
|
|
87901
88421
|
isCreditPackAmountCents: () => isCreditPackAmountCents,
|
|
87902
88422
|
isDbPricingPlan: () => isDbPricingPlan,
|
|
87903
88423
|
isDeniedGoogleBrokerRedirectHost: () => isDeniedGoogleBrokerRedirectHost,
|
|
@@ -87953,8 +88473,10 @@ __export(dist_exports, {
|
|
|
87953
88473
|
isSharedAuthTenantHost: () => isSharedAuthTenantHost,
|
|
87954
88474
|
isSharedSuffix: () => isSharedSuffix,
|
|
87955
88475
|
isSingleEmailAddress: () => isSingleEmailAddress,
|
|
88476
|
+
isSmsNotReceivedError: () => isSmsNotReceivedError,
|
|
87956
88477
|
isSoftOutcome: () => isSoftOutcome,
|
|
87957
88478
|
isStateValueMobileClassName: () => isStateValueMobileClassName,
|
|
88479
|
+
isStillLoadingScreenshotKey: () => isStillLoadingScreenshotKey,
|
|
87958
88480
|
isSttModelForProvider: () => isSttModelForProvider,
|
|
87959
88481
|
isTestReadyForPlatform: () => isTestReadyForPlatform,
|
|
87960
88482
|
isTestVariableSecretKey: () => isTestVariableSecretKey,
|
|
@@ -87962,6 +88484,7 @@ __export(dist_exports, {
|
|
|
87962
88484
|
isUIVariant: () => isUIVariant,
|
|
87963
88485
|
isUnexpectedPassError: () => isUnexpectedPassError,
|
|
87964
88486
|
isUnsafePrecondition: () => isUnsafePrecondition,
|
|
88487
|
+
isUnverifiedHealPass: () => isUnverifiedHealPass,
|
|
87965
88488
|
isUsableDeepgramKey: () => isUsableDeepgramKey,
|
|
87966
88489
|
isUserCancelledError: () => isUserCancelledError,
|
|
87967
88490
|
isValidAgenticCliModel: () => isValidAgenticCliModel,
|
|
@@ -87986,8 +88509,10 @@ __export(dist_exports, {
|
|
|
87986
88509
|
lintTestData: () => lintTestData,
|
|
87987
88510
|
lintTestQuality: () => lintTestQuality,
|
|
87988
88511
|
literalUrlRegex: () => literalUrlRegex,
|
|
88512
|
+
loginFormAlertTexts: () => loginFormAlertTexts,
|
|
87989
88513
|
longCredentialValues: () => longCredentialValues,
|
|
87990
88514
|
maskedOutsideStrings: () => maskedOutsideStrings,
|
|
88515
|
+
mayBeUnverifiedHealPass: () => mayBeUnverifiedHealPass,
|
|
87991
88516
|
mediumForMobilePlatform: () => mediumForMobilePlatform,
|
|
87992
88517
|
mergePageType: () => mergePageType,
|
|
87993
88518
|
mergeSuspectedBugsAcrossSurveys: () => mergeSuspectedBugsAcrossSurveys,
|
|
@@ -88021,7 +88546,9 @@ __export(dist_exports, {
|
|
|
88021
88546
|
opensRegexLiteral: () => opensRegexLiteral,
|
|
88022
88547
|
otherMobilePlatform: () => otherMobilePlatform,
|
|
88023
88548
|
outcomeNamedByAssertion: () => outcomeNamedByAssertion,
|
|
88549
|
+
pageScreenshotKey: () => pageScreenshotKey,
|
|
88024
88550
|
parenDepthDelta: () => parenDepthDelta,
|
|
88551
|
+
parseAbsenceProofMode: () => parseAbsenceProofMode,
|
|
88025
88552
|
parseApiCardModelUpdate: () => parseApiCardModelUpdate,
|
|
88026
88553
|
parseAppTimezone: () => parseAppTimezone,
|
|
88027
88554
|
parseAuditGroupScopeId: () => parseAuditGroupScopeId,
|
|
@@ -88097,7 +88624,7 @@ __export(dist_exports, {
|
|
|
88097
88624
|
redactNeedlesText: () => redactNeedlesText,
|
|
88098
88625
|
redirectOnAppSite: () => redirectOnAppSite,
|
|
88099
88626
|
refuseEncodedRequestBodies: () => refuseEncodedRequestBodies,
|
|
88100
|
-
regexLiteralEnd: () =>
|
|
88627
|
+
regexLiteralEnd: () => regexLiteralEnd,
|
|
88101
88628
|
regexOpensAfter: () => regexOpensAfter,
|
|
88102
88629
|
registrableDomain: () => registrableDomain,
|
|
88103
88630
|
renderIdentity: () => renderIdentity,
|
|
@@ -88139,6 +88666,9 @@ __export(dist_exports, {
|
|
|
88139
88666
|
saveOpensConfirm: () => saveOpensConfirm,
|
|
88140
88667
|
scanClockDependentLiterals: () => scanClockDependentLiterals,
|
|
88141
88668
|
scanHtmlTags: () => scanHtmlTags,
|
|
88669
|
+
scrubCredentialHeaderValue: () => scrubCredentialHeaderValue,
|
|
88670
|
+
scrubCredentialHeaders: () => scrubCredentialHeaders,
|
|
88671
|
+
scrubCredentialHeadersDeep: () => scrubCredentialHeadersDeep,
|
|
88142
88672
|
scrubCredentialStringsIn: () => scrubCredentialStringsIn,
|
|
88143
88673
|
scrubCredentialText: () => scrubCredentialText,
|
|
88144
88674
|
scrubSearchParams: () => scrubSearchParams,
|
|
@@ -88149,9 +88679,12 @@ __export(dist_exports, {
|
|
|
88149
88679
|
selectorForValue: () => selectorForValue,
|
|
88150
88680
|
setAgenticCliRuntime: () => setAgenticCliRuntime,
|
|
88151
88681
|
setProviderChainOverrides: () => setProviderChainOverrides,
|
|
88682
|
+
signInStepPassedBeforeFailure: () => signInStepPassedBeforeFailure,
|
|
88683
|
+
signsInInline: () => signsInInline,
|
|
88152
88684
|
signupPlanFor: () => signupPlanFor,
|
|
88153
88685
|
simplifyMobileWanderingInPlace: () => simplifyMobileWanderingInPlace,
|
|
88154
88686
|
siteOf: () => siteOf,
|
|
88687
|
+
specCallsExpect: () => specCallsExpect,
|
|
88155
88688
|
specItemsFromTestPlans: () => specItemsFromTestPlans,
|
|
88156
88689
|
splitAnswerLines: () => splitAnswerLines,
|
|
88157
88690
|
statedLimitsFromAttrs: () => statedLimitsFromAttrs,
|
|
@@ -88199,6 +88732,7 @@ __export(dist_exports, {
|
|
|
88199
88732
|
visualProDailyBudget: () => visualProDailyBudget,
|
|
88200
88733
|
voiceMatchesTtsModel: () => voiceMatchesTtsModel,
|
|
88201
88734
|
voicesForTtsModel: () => voicesForTtsModel,
|
|
88735
|
+
withExpectAliasesAsExpect: () => withExpectAliasesAsExpect,
|
|
88202
88736
|
withGeneratorReviewSource: () => withGeneratorReviewSource,
|
|
88203
88737
|
withReviewSource: () => withReviewSource,
|
|
88204
88738
|
withoutNotChargedClaim: () => withoutNotChargedClaim,
|
|
@@ -88253,6 +88787,7 @@ var init_dist = __esm({
|
|
|
88253
88787
|
init_encoded_forms();
|
|
88254
88788
|
init_block_comments();
|
|
88255
88789
|
init_redact_needles();
|
|
88790
|
+
init_credential_header_scrub();
|
|
88256
88791
|
init_voice_config();
|
|
88257
88792
|
init_deepgram_speech();
|
|
88258
88793
|
init_deepgram_voices();
|
|
@@ -88946,7 +89481,13 @@ await expect(page).not.toHaveURL(/accounts\\.google\\.com/, { timeout: 60_000 })
|
|
|
88946
89481
|
\`\`\`
|
|
88947
89482
|
Never emit code that clicks, fills or asserts anything on accounts.google.com.`;
|
|
88948
89483
|
}
|
|
88949
|
-
function buildGoogleSignInTestGenSection(_opts) {
|
|
89484
|
+
function buildGoogleSignInTestGenSection(_opts, ctx = {}) {
|
|
89485
|
+
if (ctx.appLoginGiven) {
|
|
89486
|
+
return `
|
|
89487
|
+
## SIGN-IN: USE THE TEST ACCOUNT
|
|
89488
|
+
This project gave a test account (the Browser Credentials / \`process.env.TEST_USER_*\` values). Sign in with it on the app's own email (or username) and password form, even when the app also offers Continue with Google. Do not click Continue with Google / Sign in with Google / Sign up with Google to sign in.
|
|
89489
|
+
Use Continue with Google only when this scenario's goal is the Google sign-in itself, or the app has no email/username and password sign-in at all. Then click that control on the app and wait until the browser is back on the app: \`await expect(page).not.toHaveURL(/accounts\\.google\\.com/, { timeout: 60_000 })\` (the runner completes Google's step). Never click, fill or assert anything on accounts.google.com, never type a password or code there.`;
|
|
89490
|
+
}
|
|
88950
89491
|
return `
|
|
88951
89492
|
## GOOGLE SIGN-IN (the runner completes Google's step)
|
|
88952
89493
|
When this scenario uses Continue with Google / Sign in with Google / Sign up with Google:
|