@validate.qa/runner 1.0.47 → 1.0.48
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/dist/cli.js +210 -8
- package/dist/cli.mjs +210 -8
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -5041,6 +5041,191 @@ var init_auth_block_detector = __esm({
|
|
|
5041
5041
|
}
|
|
5042
5042
|
});
|
|
5043
5043
|
|
|
5044
|
+
// ../shared/dist/auth-state-freshness.js
|
|
5045
|
+
function isCsrfTokenName(name) {
|
|
5046
|
+
return /csrf|xsrf|forgery|authenticity|requestverification/.test(name.toLowerCase());
|
|
5047
|
+
}
|
|
5048
|
+
function isAuthTokenName(name) {
|
|
5049
|
+
const n = name.toLowerCase();
|
|
5050
|
+
if (isCsrfTokenName(n))
|
|
5051
|
+
return false;
|
|
5052
|
+
if (/session|auth|jwt|credential|identity|login|token/.test(n))
|
|
5053
|
+
return true;
|
|
5054
|
+
if (/(?:^|[^a-z0-9])(?:sid|sess|account|remember)(?:[^a-z0-9]|$)/.test(n))
|
|
5055
|
+
return true;
|
|
5056
|
+
return [
|
|
5057
|
+
"connect.sid",
|
|
5058
|
+
"jsessionid",
|
|
5059
|
+
"phpsessid",
|
|
5060
|
+
"aspnet",
|
|
5061
|
+
"asp.net",
|
|
5062
|
+
"aspxauth",
|
|
5063
|
+
"sb-",
|
|
5064
|
+
"supabase",
|
|
5065
|
+
"amplify",
|
|
5066
|
+
"cognito",
|
|
5067
|
+
"auth0",
|
|
5068
|
+
"okta",
|
|
5069
|
+
"kc-",
|
|
5070
|
+
"li_at",
|
|
5071
|
+
"ltpatoken",
|
|
5072
|
+
"wordpress_logged_in"
|
|
5073
|
+
].some((frag) => n.includes(frag));
|
|
5074
|
+
}
|
|
5075
|
+
function isSessionClassName(name) {
|
|
5076
|
+
const n = name.toLowerCase();
|
|
5077
|
+
if (isCsrfTokenName(n))
|
|
5078
|
+
return false;
|
|
5079
|
+
if (/session|sess/.test(n))
|
|
5080
|
+
return true;
|
|
5081
|
+
if (/(?:^|[^a-z0-9])sid(?:[^a-z0-9]|$)/.test(n))
|
|
5082
|
+
return true;
|
|
5083
|
+
return [
|
|
5084
|
+
"connect.sid",
|
|
5085
|
+
"jsessionid",
|
|
5086
|
+
"phpsessid",
|
|
5087
|
+
"aspxauth",
|
|
5088
|
+
"li_at",
|
|
5089
|
+
"ltpatoken",
|
|
5090
|
+
"wordpress_logged_in"
|
|
5091
|
+
].some((frag) => n.includes(frag));
|
|
5092
|
+
}
|
|
5093
|
+
function decodeBase64UrlToUtf8(segment) {
|
|
5094
|
+
if (typeof atob !== "function")
|
|
5095
|
+
return void 0;
|
|
5096
|
+
const base64 = segment.replace(/-/g, "+").replace(/_/g, "/");
|
|
5097
|
+
const padded = base64.length % 4 === 0 ? base64 : base64 + "=".repeat(4 - base64.length % 4);
|
|
5098
|
+
try {
|
|
5099
|
+
const binary = atob(padded);
|
|
5100
|
+
let percentEncoded = "";
|
|
5101
|
+
for (let i = 0; i < binary.length; i += 1) {
|
|
5102
|
+
percentEncoded += `%${binary.charCodeAt(i).toString(16).padStart(2, "0")}`;
|
|
5103
|
+
}
|
|
5104
|
+
return decodeURIComponent(percentEncoded);
|
|
5105
|
+
} catch {
|
|
5106
|
+
return void 0;
|
|
5107
|
+
}
|
|
5108
|
+
}
|
|
5109
|
+
function jwtExpiryMs(value) {
|
|
5110
|
+
const parts = value.split(".");
|
|
5111
|
+
if (parts.length !== 3 || !parts[0] || !parts[1] || !parts[2])
|
|
5112
|
+
return void 0;
|
|
5113
|
+
const json = decodeBase64UrlToUtf8(parts[1]);
|
|
5114
|
+
if (json === void 0)
|
|
5115
|
+
return void 0;
|
|
5116
|
+
try {
|
|
5117
|
+
const payload = JSON.parse(json);
|
|
5118
|
+
const exp = payload?.exp;
|
|
5119
|
+
return typeof exp === "number" && Number.isFinite(exp) && exp > 0 ? exp * 1e3 : void 0;
|
|
5120
|
+
} catch {
|
|
5121
|
+
return void 0;
|
|
5122
|
+
}
|
|
5123
|
+
}
|
|
5124
|
+
function localStorageAuthExpiryMs(value) {
|
|
5125
|
+
const direct = jwtExpiryMs(value);
|
|
5126
|
+
if (direct !== void 0)
|
|
5127
|
+
return direct;
|
|
5128
|
+
let obj;
|
|
5129
|
+
try {
|
|
5130
|
+
obj = JSON.parse(value);
|
|
5131
|
+
} catch {
|
|
5132
|
+
return void 0;
|
|
5133
|
+
}
|
|
5134
|
+
if (!obj || typeof obj !== "object")
|
|
5135
|
+
return void 0;
|
|
5136
|
+
const record = obj;
|
|
5137
|
+
const nested = record.currentSession ?? record.session;
|
|
5138
|
+
const jwtCandidates = [
|
|
5139
|
+
record.access_token,
|
|
5140
|
+
record.accessToken,
|
|
5141
|
+
record.token,
|
|
5142
|
+
record.id_token,
|
|
5143
|
+
record.idToken,
|
|
5144
|
+
nested?.access_token,
|
|
5145
|
+
nested?.accessToken
|
|
5146
|
+
];
|
|
5147
|
+
for (const candidate of jwtCandidates) {
|
|
5148
|
+
if (typeof candidate === "string") {
|
|
5149
|
+
const exp = jwtExpiryMs(candidate);
|
|
5150
|
+
if (exp !== void 0)
|
|
5151
|
+
return exp;
|
|
5152
|
+
}
|
|
5153
|
+
}
|
|
5154
|
+
const expiresAt = record.expires_at ?? record.expiresAt ?? nested?.expires_at;
|
|
5155
|
+
if (typeof expiresAt === "number" && Number.isFinite(expiresAt) && expiresAt > 0) {
|
|
5156
|
+
return expiresAt < 1e12 ? expiresAt * 1e3 : expiresAt;
|
|
5157
|
+
}
|
|
5158
|
+
return void 0;
|
|
5159
|
+
}
|
|
5160
|
+
function collectAuthTokens(parsed) {
|
|
5161
|
+
const tokens = [];
|
|
5162
|
+
if (!parsed || typeof parsed !== "object")
|
|
5163
|
+
return tokens;
|
|
5164
|
+
const cookies = parsed.cookies;
|
|
5165
|
+
if (Array.isArray(cookies)) {
|
|
5166
|
+
for (const raw of cookies) {
|
|
5167
|
+
if (!raw || typeof raw !== "object")
|
|
5168
|
+
continue;
|
|
5169
|
+
const name = typeof raw.name === "string" ? raw.name : "";
|
|
5170
|
+
const value = typeof raw.value === "string" ? raw.value : "";
|
|
5171
|
+
if (isCsrfTokenName(name))
|
|
5172
|
+
continue;
|
|
5173
|
+
const jwtExp = value ? jwtExpiryMs(value) : void 0;
|
|
5174
|
+
if (jwtExp !== void 0) {
|
|
5175
|
+
tokens.push({ expiryMs: jwtExp, sessionClass: true });
|
|
5176
|
+
continue;
|
|
5177
|
+
}
|
|
5178
|
+
if (isAuthTokenName(name) && typeof raw.expires === "number" && Number.isFinite(raw.expires) && raw.expires > 0) {
|
|
5179
|
+
tokens.push({ expiryMs: raw.expires * 1e3, sessionClass: isSessionClassName(name) });
|
|
5180
|
+
}
|
|
5181
|
+
}
|
|
5182
|
+
}
|
|
5183
|
+
const origins = parsed.origins;
|
|
5184
|
+
if (Array.isArray(origins)) {
|
|
5185
|
+
for (const origin of origins) {
|
|
5186
|
+
if (!origin || typeof origin !== "object" || !Array.isArray(origin.localStorage))
|
|
5187
|
+
continue;
|
|
5188
|
+
for (const entry of origin.localStorage) {
|
|
5189
|
+
if (!entry || typeof entry !== "object")
|
|
5190
|
+
continue;
|
|
5191
|
+
const key = typeof entry.name === "string" ? entry.name : "";
|
|
5192
|
+
const value = typeof entry.value === "string" ? entry.value : "";
|
|
5193
|
+
if (!key || !value || isCsrfTokenName(key) || !isAuthTokenName(key))
|
|
5194
|
+
continue;
|
|
5195
|
+
const exp = localStorageAuthExpiryMs(value);
|
|
5196
|
+
if (exp !== void 0)
|
|
5197
|
+
tokens.push({ expiryMs: exp, sessionClass: true });
|
|
5198
|
+
}
|
|
5199
|
+
}
|
|
5200
|
+
}
|
|
5201
|
+
return tokens;
|
|
5202
|
+
}
|
|
5203
|
+
function storageStateExpiredBySkew(stateJson, nowMs, skewMs = AUTH_STATE_EXPIRY_SKEW_MS) {
|
|
5204
|
+
let parsed;
|
|
5205
|
+
try {
|
|
5206
|
+
parsed = JSON.parse(stateJson);
|
|
5207
|
+
} catch {
|
|
5208
|
+
return false;
|
|
5209
|
+
}
|
|
5210
|
+
const tokens = collectAuthTokens(parsed);
|
|
5211
|
+
if (tokens.length === 0)
|
|
5212
|
+
return false;
|
|
5213
|
+
const margin = Number.isFinite(skewMs) ? Math.max(0, skewMs) : AUTH_STATE_EXPIRY_SKEW_MS;
|
|
5214
|
+
const deadline = nowMs + margin;
|
|
5215
|
+
const anyExpired = tokens.some((t) => t.expiryMs <= deadline);
|
|
5216
|
+
if (!anyExpired)
|
|
5217
|
+
return false;
|
|
5218
|
+
const liveSession = tokens.some((t) => t.expiryMs > deadline && t.sessionClass);
|
|
5219
|
+
return !liveSession;
|
|
5220
|
+
}
|
|
5221
|
+
var AUTH_STATE_EXPIRY_SKEW_MS;
|
|
5222
|
+
var init_auth_state_freshness = __esm({
|
|
5223
|
+
"../shared/dist/auth-state-freshness.js"() {
|
|
5224
|
+
"use strict";
|
|
5225
|
+
AUTH_STATE_EXPIRY_SKEW_MS = 3e4;
|
|
5226
|
+
}
|
|
5227
|
+
});
|
|
5228
|
+
|
|
5044
5229
|
// ../shared/dist/skip-coverage-detector.js
|
|
5045
5230
|
function detectSkippedApiCoverage(steps) {
|
|
5046
5231
|
const allSkipped = steps.length > 0 && steps.every((s) => s.status === "skipped");
|
|
@@ -5430,6 +5615,7 @@ __export(dist_exports, {
|
|
|
5430
5615
|
API_AUTH_HEADERS_ENV_KEY: () => API_AUTH_HEADERS_ENV_KEY,
|
|
5431
5616
|
API_PREFIX: () => API_PREFIX,
|
|
5432
5617
|
AUDIO_CHUNK_DURATION_MS: () => AUDIO_CHUNK_DURATION_MS,
|
|
5618
|
+
AUTH_STATE_EXPIRY_SKEW_MS: () => AUTH_STATE_EXPIRY_SKEW_MS,
|
|
5433
5619
|
AUTH_TAG_COOKIE_STATE: () => AUTH_TAG_COOKIE_STATE,
|
|
5434
5620
|
AUTH_TAG_LOGIN_BEARER: () => AUTH_TAG_LOGIN_BEARER,
|
|
5435
5621
|
AUTH_TAG_LOGIN_COOKIE: () => AUTH_TAG_LOGIN_COOKIE,
|
|
@@ -5547,6 +5733,7 @@ __export(dist_exports, {
|
|
|
5547
5733
|
isApiTest: () => isApiTest,
|
|
5548
5734
|
isAppOriginResolutionEnabled: () => isAppOriginResolutionEnabled,
|
|
5549
5735
|
isAuthReadinessGuardEnabled: () => isAuthReadinessGuardEnabled,
|
|
5736
|
+
isAuthTokenName: () => isAuthTokenName,
|
|
5550
5737
|
isBlockedEnvVar: () => isBlockedEnvVar,
|
|
5551
5738
|
isCountedFailure: () => isCountedFailure,
|
|
5552
5739
|
isCreditPackAmountCents: () => isCreditPackAmountCents,
|
|
@@ -5569,6 +5756,7 @@ __export(dist_exports, {
|
|
|
5569
5756
|
isValidSttProvider: () => isValidSttProvider,
|
|
5570
5757
|
isValidTtsModel: () => isValidTtsModel,
|
|
5571
5758
|
isValidTtsVoiceId: () => isValidTtsVoiceId,
|
|
5759
|
+
jwtExpiryMs: () => jwtExpiryMs,
|
|
5572
5760
|
mediumForMobilePlatform: () => mediumForMobilePlatform,
|
|
5573
5761
|
mobileCredentialPlaceholder: () => mobileCredentialPlaceholder,
|
|
5574
5762
|
mobilePlatformFromMedium: () => mobilePlatformFromMedium,
|
|
@@ -5600,6 +5788,7 @@ __export(dist_exports, {
|
|
|
5600
5788
|
stepIsDivergentForPlatform: () => stepIsDivergentForPlatform,
|
|
5601
5789
|
stepsMissingPlatformLocators: () => stepsMissingPlatformLocators,
|
|
5602
5790
|
stepsNeedingReviewForPlatform: () => stepsNeedingReviewForPlatform,
|
|
5791
|
+
storageStateExpiredBySkew: () => storageStateExpiredBySkew,
|
|
5603
5792
|
stripEnvironmentalPrefix: () => stripEnvironmentalPrefix,
|
|
5604
5793
|
stripLoginScaffolding: () => stripLoginScaffolding,
|
|
5605
5794
|
sttModelsForProvider: () => sttModelsForProvider,
|
|
@@ -5630,6 +5819,7 @@ var init_dist = __esm({
|
|
|
5630
5819
|
init_origin_domain();
|
|
5631
5820
|
init_auth_plan();
|
|
5632
5821
|
init_auth_block_detector();
|
|
5822
|
+
init_auth_state_freshness();
|
|
5633
5823
|
init_skip_coverage_detector();
|
|
5634
5824
|
init_redact_needles();
|
|
5635
5825
|
init_voice_config();
|
|
@@ -333991,7 +334181,7 @@ var require_local_auth_state = __commonJS({
|
|
|
333991
334181
|
exports2.ensurePrivateDirectory = ensurePrivateDirectory2;
|
|
333992
334182
|
exports2.isValidStorageState = isValidStorageState;
|
|
333993
334183
|
exports2.isValidStorageStateJson = isValidStorageStateJson;
|
|
333994
|
-
exports2.isValidLocalAuthStateFile =
|
|
334184
|
+
exports2.isValidLocalAuthStateFile = isValidLocalAuthStateFile2;
|
|
333995
334185
|
exports2.cleanupLocalAuthStateFiles = cleanupLocalAuthStateFiles;
|
|
333996
334186
|
exports2.cleanupExpiredLocalAuthStateFiles = cleanupExpiredLocalAuthStateFiles2;
|
|
333997
334187
|
exports2.localAuthStatePaths = localAuthStatePaths2;
|
|
@@ -334005,6 +334195,7 @@ var require_local_auth_state = __commonJS({
|
|
|
334005
334195
|
var node_fs_1 = require("fs");
|
|
334006
334196
|
var node_crypto_1 = require("crypto");
|
|
334007
334197
|
var node_path_1 = require("path");
|
|
334198
|
+
var shared_1 = (init_dist(), __toCommonJS(dist_exports));
|
|
334008
334199
|
var auth_recipe_js_1 = require_auth_recipe();
|
|
334009
334200
|
exports2.LOCAL_AUTH_STATE_MAX_AGE_MS = 60 * 60 * 1e3;
|
|
334010
334201
|
exports2.LOCAL_AUTH_STATE_WAIT_MS = 3 * 60 * 1e3;
|
|
@@ -334134,7 +334325,7 @@ var require_local_auth_state = __commonJS({
|
|
|
334134
334325
|
return false;
|
|
334135
334326
|
return isValidStorageState(value);
|
|
334136
334327
|
}
|
|
334137
|
-
function
|
|
334328
|
+
function isValidLocalAuthStateFile2(path) {
|
|
334138
334329
|
try {
|
|
334139
334330
|
return isStorageStateShape(JSON.parse((0, node_fs_1.readFileSync)(path, "utf8")));
|
|
334140
334331
|
} catch {
|
|
@@ -334192,11 +334383,22 @@ var require_local_auth_state = __commonJS({
|
|
|
334192
334383
|
lockPath: `${cachePath}.lock`
|
|
334193
334384
|
};
|
|
334194
334385
|
}
|
|
334386
|
+
function localAuthStateExpiredByAuthMaterial(path, now) {
|
|
334387
|
+
try {
|
|
334388
|
+
return (0, shared_1.storageStateExpiredBySkew)((0, node_fs_1.readFileSync)(path, "utf8"), now);
|
|
334389
|
+
} catch {
|
|
334390
|
+
return false;
|
|
334391
|
+
}
|
|
334392
|
+
}
|
|
334195
334393
|
function getValidLocalAuthState2(path, now = Date.now(), maxAgeMs = exports2.LOCAL_AUTH_STATE_MAX_AGE_MS) {
|
|
334196
334394
|
if (!(0, node_fs_1.existsSync)(path))
|
|
334197
334395
|
return void 0;
|
|
334198
334396
|
try {
|
|
334199
|
-
if (now - (0, node_fs_1.statSync)(path).mtimeMs >= maxAgeMs || !
|
|
334397
|
+
if (now - (0, node_fs_1.statSync)(path).mtimeMs >= maxAgeMs || !isValidLocalAuthStateFile2(path)) {
|
|
334398
|
+
removeFile(path);
|
|
334399
|
+
return void 0;
|
|
334400
|
+
}
|
|
334401
|
+
if (localAuthStateExpiredByAuthMaterial(path, now)) {
|
|
334200
334402
|
removeFile(path);
|
|
334201
334403
|
return void 0;
|
|
334202
334404
|
}
|
|
@@ -334243,7 +334445,7 @@ var require_local_auth_state = __commonJS({
|
|
|
334243
334445
|
removeFile(capturePath);
|
|
334244
334446
|
return false;
|
|
334245
334447
|
}
|
|
334246
|
-
if (!(0, node_fs_1.existsSync)(capturePath) || !
|
|
334448
|
+
if (!(0, node_fs_1.existsSync)(capturePath) || !isValidLocalAuthStateFile2(capturePath)) {
|
|
334247
334449
|
removeFile(capturePath);
|
|
334248
334450
|
return false;
|
|
334249
334451
|
}
|
|
@@ -334257,7 +334459,7 @@ var require_local_auth_state = __commonJS({
|
|
|
334257
334459
|
return false;
|
|
334258
334460
|
}
|
|
334259
334461
|
if ((0, node_fs_1.existsSync)(cachePath)) {
|
|
334260
|
-
if (!replaceExisting &&
|
|
334462
|
+
if (!replaceExisting && isValidLocalAuthStateFile2(cachePath)) {
|
|
334261
334463
|
removeFile(capturePath);
|
|
334262
334464
|
return true;
|
|
334263
334465
|
}
|
|
@@ -334274,7 +334476,7 @@ var require_local_auth_state = __commonJS({
|
|
|
334274
334476
|
}
|
|
334275
334477
|
return true;
|
|
334276
334478
|
} catch {
|
|
334277
|
-
const winnerIsValid = (0, node_fs_1.existsSync)(cachePath) &&
|
|
334479
|
+
const winnerIsValid = (0, node_fs_1.existsSync)(cachePath) && isValidLocalAuthStateFile2(cachePath);
|
|
334278
334480
|
removeFile(capturePath);
|
|
334279
334481
|
return winnerIsValid;
|
|
334280
334482
|
}
|
|
@@ -346967,7 +347169,7 @@ var require_package4 = __commonJS({
|
|
|
346967
347169
|
"package.json"(exports2, module2) {
|
|
346968
347170
|
module2.exports = {
|
|
346969
347171
|
name: "@validate.qa/runner",
|
|
346970
|
-
version: "1.0.
|
|
347172
|
+
version: "1.0.48",
|
|
346971
347173
|
description: "validate local test runner - execute Playwright tests on your machine, connected to validate.qa cloud.",
|
|
346972
347174
|
bin: {
|
|
346973
347175
|
"validate-runner": "dist/cli.js"
|
|
@@ -356629,7 +356831,7 @@ ${result2.logs}`);
|
|
|
356629
356831
|
});
|
|
356630
356832
|
} finally {
|
|
356631
356833
|
if (runAuthPath && authPaths) {
|
|
356632
|
-
if ((0, import_runner_core12.
|
|
356834
|
+
if ((0, import_runner_core12.isValidLocalAuthStateFile)(runAuthPath)) {
|
|
356633
356835
|
const releasePromotionLock = releaseAuthLock ? void 0 : await (0, import_runner_core12.acquireLocalAuthStateLock)(authPaths.lockKey, authPaths.lockPath);
|
|
356634
356836
|
try {
|
|
356635
356837
|
const captured = (0, import_runner_core12.promoteLocalAuthStateCapture)(
|
package/dist/cli.mjs
CHANGED
|
@@ -5046,6 +5046,191 @@ var init_auth_block_detector = __esm({
|
|
|
5046
5046
|
}
|
|
5047
5047
|
});
|
|
5048
5048
|
|
|
5049
|
+
// ../shared/dist/auth-state-freshness.js
|
|
5050
|
+
function isCsrfTokenName(name) {
|
|
5051
|
+
return /csrf|xsrf|forgery|authenticity|requestverification/.test(name.toLowerCase());
|
|
5052
|
+
}
|
|
5053
|
+
function isAuthTokenName(name) {
|
|
5054
|
+
const n = name.toLowerCase();
|
|
5055
|
+
if (isCsrfTokenName(n))
|
|
5056
|
+
return false;
|
|
5057
|
+
if (/session|auth|jwt|credential|identity|login|token/.test(n))
|
|
5058
|
+
return true;
|
|
5059
|
+
if (/(?:^|[^a-z0-9])(?:sid|sess|account|remember)(?:[^a-z0-9]|$)/.test(n))
|
|
5060
|
+
return true;
|
|
5061
|
+
return [
|
|
5062
|
+
"connect.sid",
|
|
5063
|
+
"jsessionid",
|
|
5064
|
+
"phpsessid",
|
|
5065
|
+
"aspnet",
|
|
5066
|
+
"asp.net",
|
|
5067
|
+
"aspxauth",
|
|
5068
|
+
"sb-",
|
|
5069
|
+
"supabase",
|
|
5070
|
+
"amplify",
|
|
5071
|
+
"cognito",
|
|
5072
|
+
"auth0",
|
|
5073
|
+
"okta",
|
|
5074
|
+
"kc-",
|
|
5075
|
+
"li_at",
|
|
5076
|
+
"ltpatoken",
|
|
5077
|
+
"wordpress_logged_in"
|
|
5078
|
+
].some((frag) => n.includes(frag));
|
|
5079
|
+
}
|
|
5080
|
+
function isSessionClassName(name) {
|
|
5081
|
+
const n = name.toLowerCase();
|
|
5082
|
+
if (isCsrfTokenName(n))
|
|
5083
|
+
return false;
|
|
5084
|
+
if (/session|sess/.test(n))
|
|
5085
|
+
return true;
|
|
5086
|
+
if (/(?:^|[^a-z0-9])sid(?:[^a-z0-9]|$)/.test(n))
|
|
5087
|
+
return true;
|
|
5088
|
+
return [
|
|
5089
|
+
"connect.sid",
|
|
5090
|
+
"jsessionid",
|
|
5091
|
+
"phpsessid",
|
|
5092
|
+
"aspxauth",
|
|
5093
|
+
"li_at",
|
|
5094
|
+
"ltpatoken",
|
|
5095
|
+
"wordpress_logged_in"
|
|
5096
|
+
].some((frag) => n.includes(frag));
|
|
5097
|
+
}
|
|
5098
|
+
function decodeBase64UrlToUtf8(segment) {
|
|
5099
|
+
if (typeof atob !== "function")
|
|
5100
|
+
return void 0;
|
|
5101
|
+
const base64 = segment.replace(/-/g, "+").replace(/_/g, "/");
|
|
5102
|
+
const padded = base64.length % 4 === 0 ? base64 : base64 + "=".repeat(4 - base64.length % 4);
|
|
5103
|
+
try {
|
|
5104
|
+
const binary = atob(padded);
|
|
5105
|
+
let percentEncoded = "";
|
|
5106
|
+
for (let i = 0; i < binary.length; i += 1) {
|
|
5107
|
+
percentEncoded += `%${binary.charCodeAt(i).toString(16).padStart(2, "0")}`;
|
|
5108
|
+
}
|
|
5109
|
+
return decodeURIComponent(percentEncoded);
|
|
5110
|
+
} catch {
|
|
5111
|
+
return void 0;
|
|
5112
|
+
}
|
|
5113
|
+
}
|
|
5114
|
+
function jwtExpiryMs(value) {
|
|
5115
|
+
const parts = value.split(".");
|
|
5116
|
+
if (parts.length !== 3 || !parts[0] || !parts[1] || !parts[2])
|
|
5117
|
+
return void 0;
|
|
5118
|
+
const json = decodeBase64UrlToUtf8(parts[1]);
|
|
5119
|
+
if (json === void 0)
|
|
5120
|
+
return void 0;
|
|
5121
|
+
try {
|
|
5122
|
+
const payload = JSON.parse(json);
|
|
5123
|
+
const exp = payload?.exp;
|
|
5124
|
+
return typeof exp === "number" && Number.isFinite(exp) && exp > 0 ? exp * 1e3 : void 0;
|
|
5125
|
+
} catch {
|
|
5126
|
+
return void 0;
|
|
5127
|
+
}
|
|
5128
|
+
}
|
|
5129
|
+
function localStorageAuthExpiryMs(value) {
|
|
5130
|
+
const direct = jwtExpiryMs(value);
|
|
5131
|
+
if (direct !== void 0)
|
|
5132
|
+
return direct;
|
|
5133
|
+
let obj;
|
|
5134
|
+
try {
|
|
5135
|
+
obj = JSON.parse(value);
|
|
5136
|
+
} catch {
|
|
5137
|
+
return void 0;
|
|
5138
|
+
}
|
|
5139
|
+
if (!obj || typeof obj !== "object")
|
|
5140
|
+
return void 0;
|
|
5141
|
+
const record = obj;
|
|
5142
|
+
const nested = record.currentSession ?? record.session;
|
|
5143
|
+
const jwtCandidates = [
|
|
5144
|
+
record.access_token,
|
|
5145
|
+
record.accessToken,
|
|
5146
|
+
record.token,
|
|
5147
|
+
record.id_token,
|
|
5148
|
+
record.idToken,
|
|
5149
|
+
nested?.access_token,
|
|
5150
|
+
nested?.accessToken
|
|
5151
|
+
];
|
|
5152
|
+
for (const candidate of jwtCandidates) {
|
|
5153
|
+
if (typeof candidate === "string") {
|
|
5154
|
+
const exp = jwtExpiryMs(candidate);
|
|
5155
|
+
if (exp !== void 0)
|
|
5156
|
+
return exp;
|
|
5157
|
+
}
|
|
5158
|
+
}
|
|
5159
|
+
const expiresAt = record.expires_at ?? record.expiresAt ?? nested?.expires_at;
|
|
5160
|
+
if (typeof expiresAt === "number" && Number.isFinite(expiresAt) && expiresAt > 0) {
|
|
5161
|
+
return expiresAt < 1e12 ? expiresAt * 1e3 : expiresAt;
|
|
5162
|
+
}
|
|
5163
|
+
return void 0;
|
|
5164
|
+
}
|
|
5165
|
+
function collectAuthTokens(parsed) {
|
|
5166
|
+
const tokens = [];
|
|
5167
|
+
if (!parsed || typeof parsed !== "object")
|
|
5168
|
+
return tokens;
|
|
5169
|
+
const cookies = parsed.cookies;
|
|
5170
|
+
if (Array.isArray(cookies)) {
|
|
5171
|
+
for (const raw of cookies) {
|
|
5172
|
+
if (!raw || typeof raw !== "object")
|
|
5173
|
+
continue;
|
|
5174
|
+
const name = typeof raw.name === "string" ? raw.name : "";
|
|
5175
|
+
const value = typeof raw.value === "string" ? raw.value : "";
|
|
5176
|
+
if (isCsrfTokenName(name))
|
|
5177
|
+
continue;
|
|
5178
|
+
const jwtExp = value ? jwtExpiryMs(value) : void 0;
|
|
5179
|
+
if (jwtExp !== void 0) {
|
|
5180
|
+
tokens.push({ expiryMs: jwtExp, sessionClass: true });
|
|
5181
|
+
continue;
|
|
5182
|
+
}
|
|
5183
|
+
if (isAuthTokenName(name) && typeof raw.expires === "number" && Number.isFinite(raw.expires) && raw.expires > 0) {
|
|
5184
|
+
tokens.push({ expiryMs: raw.expires * 1e3, sessionClass: isSessionClassName(name) });
|
|
5185
|
+
}
|
|
5186
|
+
}
|
|
5187
|
+
}
|
|
5188
|
+
const origins = parsed.origins;
|
|
5189
|
+
if (Array.isArray(origins)) {
|
|
5190
|
+
for (const origin of origins) {
|
|
5191
|
+
if (!origin || typeof origin !== "object" || !Array.isArray(origin.localStorage))
|
|
5192
|
+
continue;
|
|
5193
|
+
for (const entry of origin.localStorage) {
|
|
5194
|
+
if (!entry || typeof entry !== "object")
|
|
5195
|
+
continue;
|
|
5196
|
+
const key = typeof entry.name === "string" ? entry.name : "";
|
|
5197
|
+
const value = typeof entry.value === "string" ? entry.value : "";
|
|
5198
|
+
if (!key || !value || isCsrfTokenName(key) || !isAuthTokenName(key))
|
|
5199
|
+
continue;
|
|
5200
|
+
const exp = localStorageAuthExpiryMs(value);
|
|
5201
|
+
if (exp !== void 0)
|
|
5202
|
+
tokens.push({ expiryMs: exp, sessionClass: true });
|
|
5203
|
+
}
|
|
5204
|
+
}
|
|
5205
|
+
}
|
|
5206
|
+
return tokens;
|
|
5207
|
+
}
|
|
5208
|
+
function storageStateExpiredBySkew(stateJson, nowMs, skewMs = AUTH_STATE_EXPIRY_SKEW_MS) {
|
|
5209
|
+
let parsed;
|
|
5210
|
+
try {
|
|
5211
|
+
parsed = JSON.parse(stateJson);
|
|
5212
|
+
} catch {
|
|
5213
|
+
return false;
|
|
5214
|
+
}
|
|
5215
|
+
const tokens = collectAuthTokens(parsed);
|
|
5216
|
+
if (tokens.length === 0)
|
|
5217
|
+
return false;
|
|
5218
|
+
const margin = Number.isFinite(skewMs) ? Math.max(0, skewMs) : AUTH_STATE_EXPIRY_SKEW_MS;
|
|
5219
|
+
const deadline = nowMs + margin;
|
|
5220
|
+
const anyExpired = tokens.some((t) => t.expiryMs <= deadline);
|
|
5221
|
+
if (!anyExpired)
|
|
5222
|
+
return false;
|
|
5223
|
+
const liveSession = tokens.some((t) => t.expiryMs > deadline && t.sessionClass);
|
|
5224
|
+
return !liveSession;
|
|
5225
|
+
}
|
|
5226
|
+
var AUTH_STATE_EXPIRY_SKEW_MS;
|
|
5227
|
+
var init_auth_state_freshness = __esm({
|
|
5228
|
+
"../shared/dist/auth-state-freshness.js"() {
|
|
5229
|
+
"use strict";
|
|
5230
|
+
AUTH_STATE_EXPIRY_SKEW_MS = 3e4;
|
|
5231
|
+
}
|
|
5232
|
+
});
|
|
5233
|
+
|
|
5049
5234
|
// ../shared/dist/skip-coverage-detector.js
|
|
5050
5235
|
function detectSkippedApiCoverage(steps) {
|
|
5051
5236
|
const allSkipped = steps.length > 0 && steps.every((s) => s.status === "skipped");
|
|
@@ -5435,6 +5620,7 @@ __export(dist_exports, {
|
|
|
5435
5620
|
API_AUTH_HEADERS_ENV_KEY: () => API_AUTH_HEADERS_ENV_KEY,
|
|
5436
5621
|
API_PREFIX: () => API_PREFIX,
|
|
5437
5622
|
AUDIO_CHUNK_DURATION_MS: () => AUDIO_CHUNK_DURATION_MS,
|
|
5623
|
+
AUTH_STATE_EXPIRY_SKEW_MS: () => AUTH_STATE_EXPIRY_SKEW_MS,
|
|
5438
5624
|
AUTH_TAG_COOKIE_STATE: () => AUTH_TAG_COOKIE_STATE,
|
|
5439
5625
|
AUTH_TAG_LOGIN_BEARER: () => AUTH_TAG_LOGIN_BEARER,
|
|
5440
5626
|
AUTH_TAG_LOGIN_COOKIE: () => AUTH_TAG_LOGIN_COOKIE,
|
|
@@ -5552,6 +5738,7 @@ __export(dist_exports, {
|
|
|
5552
5738
|
isApiTest: () => isApiTest,
|
|
5553
5739
|
isAppOriginResolutionEnabled: () => isAppOriginResolutionEnabled,
|
|
5554
5740
|
isAuthReadinessGuardEnabled: () => isAuthReadinessGuardEnabled,
|
|
5741
|
+
isAuthTokenName: () => isAuthTokenName,
|
|
5555
5742
|
isBlockedEnvVar: () => isBlockedEnvVar,
|
|
5556
5743
|
isCountedFailure: () => isCountedFailure,
|
|
5557
5744
|
isCreditPackAmountCents: () => isCreditPackAmountCents,
|
|
@@ -5574,6 +5761,7 @@ __export(dist_exports, {
|
|
|
5574
5761
|
isValidSttProvider: () => isValidSttProvider,
|
|
5575
5762
|
isValidTtsModel: () => isValidTtsModel,
|
|
5576
5763
|
isValidTtsVoiceId: () => isValidTtsVoiceId,
|
|
5764
|
+
jwtExpiryMs: () => jwtExpiryMs,
|
|
5577
5765
|
mediumForMobilePlatform: () => mediumForMobilePlatform,
|
|
5578
5766
|
mobileCredentialPlaceholder: () => mobileCredentialPlaceholder,
|
|
5579
5767
|
mobilePlatformFromMedium: () => mobilePlatformFromMedium,
|
|
@@ -5605,6 +5793,7 @@ __export(dist_exports, {
|
|
|
5605
5793
|
stepIsDivergentForPlatform: () => stepIsDivergentForPlatform,
|
|
5606
5794
|
stepsMissingPlatformLocators: () => stepsMissingPlatformLocators,
|
|
5607
5795
|
stepsNeedingReviewForPlatform: () => stepsNeedingReviewForPlatform,
|
|
5796
|
+
storageStateExpiredBySkew: () => storageStateExpiredBySkew,
|
|
5608
5797
|
stripEnvironmentalPrefix: () => stripEnvironmentalPrefix,
|
|
5609
5798
|
stripLoginScaffolding: () => stripLoginScaffolding,
|
|
5610
5799
|
sttModelsForProvider: () => sttModelsForProvider,
|
|
@@ -5635,6 +5824,7 @@ var init_dist = __esm({
|
|
|
5635
5824
|
init_origin_domain();
|
|
5636
5825
|
init_auth_plan();
|
|
5637
5826
|
init_auth_block_detector();
|
|
5827
|
+
init_auth_state_freshness();
|
|
5638
5828
|
init_skip_coverage_detector();
|
|
5639
5829
|
init_redact_needles();
|
|
5640
5830
|
init_voice_config();
|
|
@@ -333996,7 +334186,7 @@ var require_local_auth_state = __commonJS({
|
|
|
333996
334186
|
exports.ensurePrivateDirectory = ensurePrivateDirectory2;
|
|
333997
334187
|
exports.isValidStorageState = isValidStorageState;
|
|
333998
334188
|
exports.isValidStorageStateJson = isValidStorageStateJson;
|
|
333999
|
-
exports.isValidLocalAuthStateFile =
|
|
334189
|
+
exports.isValidLocalAuthStateFile = isValidLocalAuthStateFile2;
|
|
334000
334190
|
exports.cleanupLocalAuthStateFiles = cleanupLocalAuthStateFiles;
|
|
334001
334191
|
exports.cleanupExpiredLocalAuthStateFiles = cleanupExpiredLocalAuthStateFiles2;
|
|
334002
334192
|
exports.localAuthStatePaths = localAuthStatePaths2;
|
|
@@ -334010,6 +334200,7 @@ var require_local_auth_state = __commonJS({
|
|
|
334010
334200
|
var node_fs_1 = __require("fs");
|
|
334011
334201
|
var node_crypto_1 = __require("crypto");
|
|
334012
334202
|
var node_path_1 = __require("path");
|
|
334203
|
+
var shared_1 = (init_dist(), __toCommonJS(dist_exports));
|
|
334013
334204
|
var auth_recipe_js_1 = require_auth_recipe();
|
|
334014
334205
|
exports.LOCAL_AUTH_STATE_MAX_AGE_MS = 60 * 60 * 1e3;
|
|
334015
334206
|
exports.LOCAL_AUTH_STATE_WAIT_MS = 3 * 60 * 1e3;
|
|
@@ -334139,7 +334330,7 @@ var require_local_auth_state = __commonJS({
|
|
|
334139
334330
|
return false;
|
|
334140
334331
|
return isValidStorageState(value);
|
|
334141
334332
|
}
|
|
334142
|
-
function
|
|
334333
|
+
function isValidLocalAuthStateFile2(path) {
|
|
334143
334334
|
try {
|
|
334144
334335
|
return isStorageStateShape(JSON.parse((0, node_fs_1.readFileSync)(path, "utf8")));
|
|
334145
334336
|
} catch {
|
|
@@ -334197,11 +334388,22 @@ var require_local_auth_state = __commonJS({
|
|
|
334197
334388
|
lockPath: `${cachePath}.lock`
|
|
334198
334389
|
};
|
|
334199
334390
|
}
|
|
334391
|
+
function localAuthStateExpiredByAuthMaterial(path, now) {
|
|
334392
|
+
try {
|
|
334393
|
+
return (0, shared_1.storageStateExpiredBySkew)((0, node_fs_1.readFileSync)(path, "utf8"), now);
|
|
334394
|
+
} catch {
|
|
334395
|
+
return false;
|
|
334396
|
+
}
|
|
334397
|
+
}
|
|
334200
334398
|
function getValidLocalAuthState2(path, now = Date.now(), maxAgeMs = exports.LOCAL_AUTH_STATE_MAX_AGE_MS) {
|
|
334201
334399
|
if (!(0, node_fs_1.existsSync)(path))
|
|
334202
334400
|
return void 0;
|
|
334203
334401
|
try {
|
|
334204
|
-
if (now - (0, node_fs_1.statSync)(path).mtimeMs >= maxAgeMs || !
|
|
334402
|
+
if (now - (0, node_fs_1.statSync)(path).mtimeMs >= maxAgeMs || !isValidLocalAuthStateFile2(path)) {
|
|
334403
|
+
removeFile(path);
|
|
334404
|
+
return void 0;
|
|
334405
|
+
}
|
|
334406
|
+
if (localAuthStateExpiredByAuthMaterial(path, now)) {
|
|
334205
334407
|
removeFile(path);
|
|
334206
334408
|
return void 0;
|
|
334207
334409
|
}
|
|
@@ -334248,7 +334450,7 @@ var require_local_auth_state = __commonJS({
|
|
|
334248
334450
|
removeFile(capturePath);
|
|
334249
334451
|
return false;
|
|
334250
334452
|
}
|
|
334251
|
-
if (!(0, node_fs_1.existsSync)(capturePath) || !
|
|
334453
|
+
if (!(0, node_fs_1.existsSync)(capturePath) || !isValidLocalAuthStateFile2(capturePath)) {
|
|
334252
334454
|
removeFile(capturePath);
|
|
334253
334455
|
return false;
|
|
334254
334456
|
}
|
|
@@ -334262,7 +334464,7 @@ var require_local_auth_state = __commonJS({
|
|
|
334262
334464
|
return false;
|
|
334263
334465
|
}
|
|
334264
334466
|
if ((0, node_fs_1.existsSync)(cachePath)) {
|
|
334265
|
-
if (!replaceExisting &&
|
|
334467
|
+
if (!replaceExisting && isValidLocalAuthStateFile2(cachePath)) {
|
|
334266
334468
|
removeFile(capturePath);
|
|
334267
334469
|
return true;
|
|
334268
334470
|
}
|
|
@@ -334279,7 +334481,7 @@ var require_local_auth_state = __commonJS({
|
|
|
334279
334481
|
}
|
|
334280
334482
|
return true;
|
|
334281
334483
|
} catch {
|
|
334282
|
-
const winnerIsValid = (0, node_fs_1.existsSync)(cachePath) &&
|
|
334484
|
+
const winnerIsValid = (0, node_fs_1.existsSync)(cachePath) && isValidLocalAuthStateFile2(cachePath);
|
|
334283
334485
|
removeFile(capturePath);
|
|
334284
334486
|
return winnerIsValid;
|
|
334285
334487
|
}
|
|
@@ -346972,7 +347174,7 @@ var require_package4 = __commonJS({
|
|
|
346972
347174
|
"package.json"(exports, module) {
|
|
346973
347175
|
module.exports = {
|
|
346974
347176
|
name: "@validate.qa/runner",
|
|
346975
|
-
version: "1.0.
|
|
347177
|
+
version: "1.0.48",
|
|
346976
347178
|
description: "validate local test runner - execute Playwright tests on your machine, connected to validate.qa cloud.",
|
|
346977
347179
|
bin: {
|
|
346978
347180
|
"validate-runner": "dist/cli.js"
|
|
@@ -356637,7 +356839,7 @@ ${result2.logs}`);
|
|
|
356637
356839
|
});
|
|
356638
356840
|
} finally {
|
|
356639
356841
|
if (runAuthPath && authPaths) {
|
|
356640
|
-
if ((0, import_runner_core12.
|
|
356842
|
+
if ((0, import_runner_core12.isValidLocalAuthStateFile)(runAuthPath)) {
|
|
356641
356843
|
const releasePromotionLock = releaseAuthLock ? void 0 : await (0, import_runner_core12.acquireLocalAuthStateLock)(authPaths.lockKey, authPaths.lockPath);
|
|
356642
356844
|
try {
|
|
356643
356845
|
const captured = (0, import_runner_core12.promoteLocalAuthStateCapture)(
|
package/package.json
CHANGED