@riddledc/riddle-proof 0.8.35 → 0.8.37
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/{chunk-TWTEUS7R.js → chunk-DI2XNGEZ.js} +126 -1
- package/dist/{chunk-UGHN77PS.js → chunk-F4HKK2YH.js} +35 -4
- package/dist/{chunk-PEWAIEER.js → chunk-Z2LCVROU.js} +126 -0
- package/dist/cli/index.js +3 -3
- package/dist/cli.cjs +285 -3
- package/dist/cli.js +3 -3
- package/dist/index.cjs +252 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/profile/index.cjs +126 -0
- package/dist/profile/index.js +1 -1
- package/dist/profile.cjs +126 -0
- package/dist/profile.d.cts +2 -0
- package/dist/profile.d.ts +2 -0
- package/dist/profile.js +1 -1
- package/dist/riddle-client.cjs +126 -1
- package/dist/riddle-client.d.cts +21 -1
- package/dist/riddle-client.d.ts +21 -1
- package/dist/riddle-client.js +1 -1
- package/dist/runtime/index.cjs +126 -1
- package/dist/runtime/index.d.cts +1 -1
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/index.js +1 -1
- package/dist/runtime/riddle-client.cjs +126 -1
- package/dist/runtime/riddle-client.d.cts +1 -1
- package/dist/runtime/riddle-client.d.ts +1 -1
- package/dist/runtime/riddle-client.js +1 -1
- package/examples/regression-packs/oc-flow-regression.json +16 -2
- package/package.json +1 -1
|
@@ -81,10 +81,68 @@ function previewDeployResultFromRecord(input) {
|
|
|
81
81
|
function canRecoverPreviewPublish(error) {
|
|
82
82
|
return error instanceof RiddleApiError && PREVIEW_PUBLISH_RECOVERY_STATUSES.has(error.status);
|
|
83
83
|
}
|
|
84
|
+
function summarizePreviewDirectory(directory) {
|
|
85
|
+
const stack = [directory];
|
|
86
|
+
let fileCount = 0;
|
|
87
|
+
let totalBytes = 0;
|
|
88
|
+
while (stack.length) {
|
|
89
|
+
const current = stack.pop();
|
|
90
|
+
for (const entry of readdirSync(current, { withFileTypes: true })) {
|
|
91
|
+
const fullPath = path.join(current, entry.name);
|
|
92
|
+
if (entry.isDirectory()) {
|
|
93
|
+
stack.push(fullPath);
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (!entry.isFile()) continue;
|
|
97
|
+
const stat = statSync(fullPath);
|
|
98
|
+
fileCount += 1;
|
|
99
|
+
totalBytes += stat.size;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return { file_count: fileCount, total_bytes: totalBytes };
|
|
103
|
+
}
|
|
104
|
+
function previewProgressEmitter(config, base) {
|
|
105
|
+
return async (snapshot) => {
|
|
106
|
+
if (!config.onPreviewProgress) return;
|
|
107
|
+
await config.onPreviewProgress({
|
|
108
|
+
label: base.label,
|
|
109
|
+
framework: base.framework,
|
|
110
|
+
directory: base.directory,
|
|
111
|
+
elapsed_ms: Math.max(0, Date.now() - base.startedAt),
|
|
112
|
+
warnings: base.warnings?.length ? base.warnings : void 0,
|
|
113
|
+
...snapshot
|
|
114
|
+
});
|
|
115
|
+
};
|
|
116
|
+
}
|
|
84
117
|
async function waitForPublishedPreview(config, input) {
|
|
118
|
+
await input.emitProgress?.({
|
|
119
|
+
stage: "publish_recovering",
|
|
120
|
+
id: input.id,
|
|
121
|
+
file_count: input.localSummary?.file_count,
|
|
122
|
+
total_bytes: input.localSummary?.total_bytes,
|
|
123
|
+
publish_error: input.publishError.message,
|
|
124
|
+
message: `publish returned ${input.publishError.status}; polling preview status`
|
|
125
|
+
});
|
|
85
126
|
for (let attempt = 1; attempt <= PREVIEW_PUBLISH_RECOVERY_ATTEMPTS; attempt += 1) {
|
|
86
127
|
const status = await riddleRequestJson(config, `/v1/preview/${input.id}`);
|
|
128
|
+
await input.emitProgress?.({
|
|
129
|
+
stage: "checking_status",
|
|
130
|
+
id: input.id,
|
|
131
|
+
attempt,
|
|
132
|
+
attempts: PREVIEW_PUBLISH_RECOVERY_ATTEMPTS,
|
|
133
|
+
status: typeof status.status === "string" ? status.status : null,
|
|
134
|
+
preview_url: typeof status.preview_url === "string" ? status.preview_url : void 0,
|
|
135
|
+
file_count: typeof status.file_count === "number" ? status.file_count : input.localSummary?.file_count,
|
|
136
|
+
total_bytes: typeof status.total_bytes === "number" ? status.total_bytes : input.localSummary?.total_bytes
|
|
137
|
+
});
|
|
87
138
|
if (String(status.status || "") === "ready" && String(status.preview_url || "").trim()) {
|
|
139
|
+
await input.emitProgress?.({
|
|
140
|
+
stage: "ready",
|
|
141
|
+
id: input.id,
|
|
142
|
+
preview_url: String(status.preview_url),
|
|
143
|
+
file_count: typeof status.file_count === "number" ? status.file_count : input.localSummary?.file_count,
|
|
144
|
+
total_bytes: typeof status.total_bytes === "number" ? status.total_bytes : input.localSummary?.total_bytes
|
|
145
|
+
});
|
|
88
146
|
return previewDeployResultFromRecord({
|
|
89
147
|
record: status,
|
|
90
148
|
id: input.id,
|
|
@@ -106,7 +164,17 @@ async function deployRiddlePreview(config, directory, label, framework = "static
|
|
|
106
164
|
if (!directory?.trim()) throw new Error("directory is required");
|
|
107
165
|
if (!label?.trim()) throw new Error("label is required");
|
|
108
166
|
if (framework !== "spa" && framework !== "static") throw new Error("framework must be spa or static");
|
|
167
|
+
const startedAt = Date.now();
|
|
109
168
|
const warnings = collectRiddlePreviewDeployWarnings(directory, framework);
|
|
169
|
+
const emitProgress = previewProgressEmitter(config, { label, framework, directory, startedAt, warnings });
|
|
170
|
+
await emitProgress({ stage: "validating", message: "checking preview input directory" });
|
|
171
|
+
const localSummary = summarizePreviewDirectory(directory);
|
|
172
|
+
await emitProgress({
|
|
173
|
+
stage: "creating",
|
|
174
|
+
file_count: localSummary.file_count,
|
|
175
|
+
total_bytes: localSummary.total_bytes,
|
|
176
|
+
message: "creating preview upload target"
|
|
177
|
+
});
|
|
110
178
|
const created = await riddleRequestJson(config, "/v1/preview", {
|
|
111
179
|
method: "POST",
|
|
112
180
|
body: JSON.stringify({ framework, label })
|
|
@@ -114,10 +182,42 @@ async function deployRiddlePreview(config, directory, label, framework = "static
|
|
|
114
182
|
const id = String(created.id || "");
|
|
115
183
|
const uploadUrl = String(created.upload_url || "");
|
|
116
184
|
if (!id || !uploadUrl) throw new Error("Riddle preview create response was missing id or upload_url.");
|
|
185
|
+
await emitProgress({
|
|
186
|
+
stage: "created",
|
|
187
|
+
id,
|
|
188
|
+
file_count: localSummary.file_count,
|
|
189
|
+
total_bytes: localSummary.total_bytes,
|
|
190
|
+
message: "preview upload target created"
|
|
191
|
+
});
|
|
117
192
|
const scratch = mkdtempSync(path.join(tmpdir(), "riddle-preview-upload-"));
|
|
118
193
|
const tarball = path.join(scratch, `${id}.tar.gz`);
|
|
194
|
+
let tarballBytes = 0;
|
|
119
195
|
try {
|
|
196
|
+
await emitProgress({
|
|
197
|
+
stage: "archiving",
|
|
198
|
+
id,
|
|
199
|
+
file_count: localSummary.file_count,
|
|
200
|
+
total_bytes: localSummary.total_bytes,
|
|
201
|
+
message: "creating preview archive"
|
|
202
|
+
});
|
|
120
203
|
execFileSync("tar", ["czf", tarball, "-C", directory, "."], { stdio: "pipe" });
|
|
204
|
+
tarballBytes = statSync(tarball).size;
|
|
205
|
+
await emitProgress({
|
|
206
|
+
stage: "archived",
|
|
207
|
+
id,
|
|
208
|
+
file_count: localSummary.file_count,
|
|
209
|
+
total_bytes: localSummary.total_bytes,
|
|
210
|
+
tarball_bytes: tarballBytes,
|
|
211
|
+
message: "preview archive created"
|
|
212
|
+
});
|
|
213
|
+
await emitProgress({
|
|
214
|
+
stage: "uploading",
|
|
215
|
+
id,
|
|
216
|
+
file_count: localSummary.file_count,
|
|
217
|
+
total_bytes: localSummary.total_bytes,
|
|
218
|
+
tarball_bytes: tarballBytes,
|
|
219
|
+
message: "uploading preview archive"
|
|
220
|
+
});
|
|
121
221
|
const upload = await fetchFor(config)(uploadUrl, {
|
|
122
222
|
method: "PUT",
|
|
123
223
|
headers: { "Content-Type": "application/gzip" },
|
|
@@ -126,14 +226,37 @@ async function deployRiddlePreview(config, directory, label, framework = "static
|
|
|
126
226
|
if (!upload.ok) {
|
|
127
227
|
throw new RiddleApiError(uploadUrl, upload.status, await upload.text());
|
|
128
228
|
}
|
|
229
|
+
await emitProgress({
|
|
230
|
+
stage: "uploaded",
|
|
231
|
+
id,
|
|
232
|
+
file_count: localSummary.file_count,
|
|
233
|
+
total_bytes: localSummary.total_bytes,
|
|
234
|
+
tarball_bytes: tarballBytes,
|
|
235
|
+
message: "preview archive uploaded"
|
|
236
|
+
});
|
|
129
237
|
} finally {
|
|
130
238
|
rmSync(scratch, { recursive: true, force: true });
|
|
131
239
|
}
|
|
132
240
|
const expiresAt = typeof created.expires_at === "string" ? created.expires_at : void 0;
|
|
133
241
|
try {
|
|
242
|
+
await emitProgress({
|
|
243
|
+
stage: "publishing",
|
|
244
|
+
id,
|
|
245
|
+
file_count: localSummary.file_count,
|
|
246
|
+
total_bytes: localSummary.total_bytes,
|
|
247
|
+
tarball_bytes: tarballBytes || void 0,
|
|
248
|
+
message: "publishing preview"
|
|
249
|
+
});
|
|
134
250
|
const published = await riddleRequestJson(config, `/v1/preview/${id}/publish`, {
|
|
135
251
|
method: "POST"
|
|
136
252
|
});
|
|
253
|
+
await emitProgress({
|
|
254
|
+
stage: "ready",
|
|
255
|
+
id,
|
|
256
|
+
preview_url: String(published.preview_url || ""),
|
|
257
|
+
file_count: typeof published.file_count === "number" ? published.file_count : localSummary.file_count,
|
|
258
|
+
total_bytes: typeof published.total_bytes === "number" ? published.total_bytes : localSummary.total_bytes
|
|
259
|
+
});
|
|
137
260
|
return previewDeployResultFromRecord({ record: published, id, label, framework, expiresAt, warnings });
|
|
138
261
|
} catch (error) {
|
|
139
262
|
if (!canRecoverPreviewPublish(error)) throw error;
|
|
@@ -143,7 +266,9 @@ async function deployRiddlePreview(config, directory, label, framework = "static
|
|
|
143
266
|
framework,
|
|
144
267
|
expiresAt,
|
|
145
268
|
publishError: error,
|
|
146
|
-
warnings
|
|
269
|
+
warnings,
|
|
270
|
+
localSummary,
|
|
271
|
+
emitProgress
|
|
147
272
|
});
|
|
148
273
|
}
|
|
149
274
|
}
|
|
@@ -12,12 +12,12 @@ import {
|
|
|
12
12
|
profileStatusExitCode,
|
|
13
13
|
resolveRiddleProofProfileTargetUrl,
|
|
14
14
|
resolveRiddleProofProfileTimeoutSec
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-Z2LCVROU.js";
|
|
16
16
|
import {
|
|
17
17
|
createRiddleApiClient,
|
|
18
18
|
isTerminalRiddleJobStatus,
|
|
19
19
|
parseRiddleViewport
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-DI2XNGEZ.js";
|
|
21
21
|
import {
|
|
22
22
|
createDisabledRiddleProofAgentAdapter,
|
|
23
23
|
readRiddleProofRunStatus,
|
|
@@ -140,7 +140,7 @@ function usage() {
|
|
|
140
140
|
" riddle-proof-loop regression-pack run [--pack oc-flow-regression|--pack-file <file>] [--local-core true|false; default true] [--hosted-riddle true|false; default false] [--format json|markdown|compact-json; default json] [--output <dir>|--output-dir <dir>]",
|
|
141
141
|
" riddle-proof-loop profile-body-assertions --artifact <file|url|-> --candidates-json <file|json|-> [--required-json <file|json|->] [--format json|body-contains]",
|
|
142
142
|
" riddle-proof-loop profile-http-status-preflight --profile <file|json|-> --url <base-url> [--format json|summary]",
|
|
143
|
-
" riddle-proof-loop riddle-preview-deploy <build-dir> <label> [--framework spa|static]",
|
|
143
|
+
" riddle-proof-loop riddle-preview-deploy <build-dir> <label> [--framework spa|static] [--quiet]",
|
|
144
144
|
" riddle-proof-loop riddle-server-preview <directory> --script-file <file> [--path /route] [--wait-for-selector selector]",
|
|
145
145
|
" riddle-proof-loop riddle-run-script --url <url> --script-file <file> [--viewport 1280x720] [--strict true|false]",
|
|
146
146
|
" riddle-proof-loop riddle-poll <job-id> [--wait] [--attempts n] [--quiet]",
|
|
@@ -909,6 +909,18 @@ function formatPollDuration(ms) {
|
|
|
909
909
|
const remainder = seconds % 60;
|
|
910
910
|
return minutes > 0 ? `${minutes}m${String(remainder).padStart(2, "0")}s` : `${seconds}s`;
|
|
911
911
|
}
|
|
912
|
+
function formatByteCount(bytes) {
|
|
913
|
+
if (typeof bytes !== "number" || !Number.isFinite(bytes)) return "n/a";
|
|
914
|
+
if (bytes < 1024) return `${bytes}B`;
|
|
915
|
+
const units = ["KB", "MB", "GB", "TB"];
|
|
916
|
+
let value = bytes / 1024;
|
|
917
|
+
let unitIndex = 0;
|
|
918
|
+
while (value >= 1024 && unitIndex < units.length - 1) {
|
|
919
|
+
value /= 1024;
|
|
920
|
+
unitIndex += 1;
|
|
921
|
+
}
|
|
922
|
+
return `${value >= 10 ? value.toFixed(0) : value.toFixed(1)}${units[unitIndex]}`;
|
|
923
|
+
}
|
|
912
924
|
function riddlePollProgressLine(snapshot) {
|
|
913
925
|
const submittedAt = snapshot.submitted_at || "not-submitted";
|
|
914
926
|
const queuePart = snapshot.running_without_submission ? ` waiting_for_submit=${formatPollDuration(snapshot.pre_submission_elapsed_ms)}${snapshot.queue_elapsed_ms !== null ? ` queued_for=${formatPollDuration(snapshot.queue_elapsed_ms)}` : ""}` : snapshot.queue_elapsed_ms !== null ? ` queue=${formatPollDuration(snapshot.queue_elapsed_ms)}` : "";
|
|
@@ -922,6 +934,18 @@ function riddlePollProgressLine(snapshot) {
|
|
|
922
934
|
`submitted_at=${submittedAt}${queuePart}${terminalPart}`
|
|
923
935
|
].join(" ");
|
|
924
936
|
}
|
|
937
|
+
function riddlePreviewProgressLine(snapshot) {
|
|
938
|
+
const idPart = snapshot.id ? ` id=${snapshot.id}` : "";
|
|
939
|
+
const statusPart = snapshot.status ? ` status=${snapshot.status}` : "";
|
|
940
|
+
const attemptPart = snapshot.attempt && snapshot.attempts ? ` attempt=${snapshot.attempt}/${snapshot.attempts}` : "";
|
|
941
|
+
const previewPart = snapshot.preview_url ? ` url=${snapshot.preview_url}` : "";
|
|
942
|
+
const filePart = typeof snapshot.file_count === "number" ? ` files=${snapshot.file_count}` : "";
|
|
943
|
+
const totalPart = typeof snapshot.total_bytes === "number" ? ` bytes=${formatByteCount(snapshot.total_bytes)}` : "";
|
|
944
|
+
const archivePart = typeof snapshot.tarball_bytes === "number" ? ` archive=${formatByteCount(snapshot.tarball_bytes)}` : "";
|
|
945
|
+
const recoveryPart = snapshot.publish_error ? ` publish_error=${JSON.stringify(snapshot.publish_error)}` : "";
|
|
946
|
+
const messagePart = snapshot.message ? ` ${snapshot.message}` : "";
|
|
947
|
+
return `[riddle-preview] ${snapshot.stage}${idPart}${statusPart}${attemptPart} elapsed=${formatPollDuration(snapshot.elapsed_ms)} label=${snapshot.label} framework=${snapshot.framework}${filePart}${totalPart}${archivePart}${previewPart}${recoveryPart}${messagePart}`;
|
|
948
|
+
}
|
|
925
949
|
function readJsonValue(value, label) {
|
|
926
950
|
if (!value) throw new Error(`${label} is required.`);
|
|
927
951
|
const raw = value === "-" ? readStdin() : existsSync(value) ? readFileSync(value, "utf-8") : value;
|
|
@@ -4597,7 +4621,14 @@ async function main() {
|
|
|
4597
4621
|
if (command === "riddle-preview-deploy") {
|
|
4598
4622
|
const buildDir = positional[1];
|
|
4599
4623
|
const label = positional[2];
|
|
4600
|
-
const
|
|
4624
|
+
const clientConfig = riddleClientConfig(options);
|
|
4625
|
+
if (options.quiet !== true) {
|
|
4626
|
+
clientConfig.onPreviewProgress = (snapshot) => {
|
|
4627
|
+
process.stderr.write(`${riddlePreviewProgressLine(snapshot)}
|
|
4628
|
+
`);
|
|
4629
|
+
};
|
|
4630
|
+
}
|
|
4631
|
+
const result = await createRiddleApiClient(clientConfig).deployPreview(buildDir, label, previewFrameworkOption(options));
|
|
4601
4632
|
for (const warning of result.warnings ?? []) {
|
|
4602
4633
|
process.stderr.write(`Warning: ${warning}
|
|
4603
4634
|
`);
|
|
@@ -1331,6 +1331,8 @@ function normalizeSetupAction(input, index) {
|
|
|
1331
1331
|
expect_changed: booleanValue(valueFromOwn(input, "expect_changed", "expectChanged", "should_change", "shouldChange", "changed")),
|
|
1332
1332
|
until_path: untilPath,
|
|
1333
1333
|
until_expected_value: hasUntilExpectedValue ? toJsonValue(valueFromOwn(input, "until_expected_value", "untilExpectedValue", "until_expected", "untilExpected", "until_value", "untilValue", "expected_value", "expectedValue", "expected")) : void 0,
|
|
1334
|
+
expected_path: stringFromOwn(input, "expected_path", "expectedPath", "expected_terminal_path", "expectedTerminalPath"),
|
|
1335
|
+
expected_url: stringFromOwn(input, "expected_url", "expectedUrl", "expected_terminal_url", "expectedTerminalUrl"),
|
|
1334
1336
|
max_calls: maxCalls,
|
|
1335
1337
|
tap_burst_size: tapBurstSize,
|
|
1336
1338
|
settle_ms: settleMs,
|
|
@@ -3688,6 +3690,80 @@ function routePathMatches(observed, expected, targetUrl) {
|
|
|
3688
3690
|
if (normalizedObserved === normalizedExpected) return true;
|
|
3689
3691
|
return normalizedObserved === normalizeRoutePath(mountedExpectedRoutePath(targetUrl, expected));
|
|
3690
3692
|
}
|
|
3693
|
+
function setupActionExpectedRoute(action) {
|
|
3694
|
+
const expectedUrl = typeof action.expected_url === "string" && action.expected_url.trim()
|
|
3695
|
+
? action.expected_url.trim()
|
|
3696
|
+
: typeof action.expectedUrl === "string" && action.expectedUrl.trim()
|
|
3697
|
+
? action.expectedUrl.trim()
|
|
3698
|
+
: "";
|
|
3699
|
+
const expectedPath = typeof action.expected_path === "string" && action.expected_path.trim()
|
|
3700
|
+
? action.expected_path.trim()
|
|
3701
|
+
: typeof action.expectedPath === "string" && action.expectedPath.trim()
|
|
3702
|
+
? action.expectedPath.trim()
|
|
3703
|
+
: "";
|
|
3704
|
+
if (!expectedUrl && !expectedPath) return null;
|
|
3705
|
+
return { expected_url: expectedUrl || undefined, expected_path: expectedPath || undefined };
|
|
3706
|
+
}
|
|
3707
|
+
function setupUrlMatchesExpectedRoute(href, expected) {
|
|
3708
|
+
if (!expected) return true;
|
|
3709
|
+
let observedUrl;
|
|
3710
|
+
try {
|
|
3711
|
+
observedUrl = new URL(href, targetUrl);
|
|
3712
|
+
} catch {
|
|
3713
|
+
return false;
|
|
3714
|
+
}
|
|
3715
|
+
if (expected.expected_url) {
|
|
3716
|
+
let expectedUrl;
|
|
3717
|
+
try {
|
|
3718
|
+
expectedUrl = new URL(expected.expected_url, targetUrl);
|
|
3719
|
+
} catch {
|
|
3720
|
+
return false;
|
|
3721
|
+
}
|
|
3722
|
+
return observedUrl.href === expectedUrl.href;
|
|
3723
|
+
}
|
|
3724
|
+
const expectedPath = expected.expected_path || "/";
|
|
3725
|
+
if (/[?#]/.test(expectedPath)) {
|
|
3726
|
+
const observedRoute = observedUrl.pathname + observedUrl.search + observedUrl.hash;
|
|
3727
|
+
const normalizedObservedRoute = observedRoute === "/" ? "/" : observedRoute.replace(/\/+(?=[?#]|$)/, "");
|
|
3728
|
+
const normalizedExpectedRoute = expectedPath === "/" ? "/" : expectedPath.replace(/\/+(?=[?#]|$)/, "");
|
|
3729
|
+
return normalizedObservedRoute === normalizedExpectedRoute;
|
|
3730
|
+
}
|
|
3731
|
+
return routePathMatches(observedUrl.pathname, expectedPath, targetUrl);
|
|
3732
|
+
}
|
|
3733
|
+
function setupObservedRouteEvidence(expected, waitError) {
|
|
3734
|
+
let observedUrl = page.url();
|
|
3735
|
+
let observedPath = "";
|
|
3736
|
+
let observedRoute = "";
|
|
3737
|
+
try {
|
|
3738
|
+
const url = new URL(observedUrl, targetUrl);
|
|
3739
|
+
observedUrl = url.href;
|
|
3740
|
+
observedPath = url.pathname;
|
|
3741
|
+
observedRoute = url.pathname + url.search + url.hash;
|
|
3742
|
+
} catch {
|
|
3743
|
+
observedPath = "";
|
|
3744
|
+
observedRoute = "";
|
|
3745
|
+
}
|
|
3746
|
+
return {
|
|
3747
|
+
expected_url: expected && expected.expected_url || undefined,
|
|
3748
|
+
expected_path: expected && expected.expected_path || undefined,
|
|
3749
|
+
observed_url: observedUrl,
|
|
3750
|
+
observed_path: observedPath,
|
|
3751
|
+
observed_route: observedRoute,
|
|
3752
|
+
route_matched: setupUrlMatchesExpectedRoute(observedUrl, expected),
|
|
3753
|
+
route_wait_error: waitError ? String(waitError && waitError.message ? waitError.message : waitError).slice(0, 1000) : undefined,
|
|
3754
|
+
};
|
|
3755
|
+
}
|
|
3756
|
+
async function waitForSetupActionRoute(action, timeout) {
|
|
3757
|
+
const expected = setupActionExpectedRoute(action);
|
|
3758
|
+
if (!expected) return null;
|
|
3759
|
+
let waitError;
|
|
3760
|
+
try {
|
|
3761
|
+
await page.waitForURL((url) => setupUrlMatchesExpectedRoute(url.href, expected), { timeout: Math.min(timeout, 20000) });
|
|
3762
|
+
} catch (error) {
|
|
3763
|
+
waitError = error;
|
|
3764
|
+
}
|
|
3765
|
+
return setupObservedRouteEvidence(expected, waitError);
|
|
3766
|
+
}
|
|
3691
3767
|
function routeOk(route, targetUrl) {
|
|
3692
3768
|
return Boolean(route && (route.matched || routePathMatches(route.observed, route.expected_path, targetUrl)) && !route.error && (route.http_status == null || route.http_status < 400));
|
|
3693
3769
|
}
|
|
@@ -6581,11 +6657,22 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
6581
6657
|
const prepared = await resolveSetupTapTarget(action, base, scope, timeout);
|
|
6582
6658
|
if (prepared.result) return prepared.result;
|
|
6583
6659
|
await dispatchSetupTapPoint(prepared.target.point, prepared.target.pointerType, prepared.target.durationMs);
|
|
6660
|
+
const routeEvidence = await waitForSetupActionRoute(action, timeout);
|
|
6661
|
+
if (routeEvidence && !routeEvidence.route_matched) {
|
|
6662
|
+
return {
|
|
6663
|
+
...base,
|
|
6664
|
+
...setupScopeEvidence(scope),
|
|
6665
|
+
...setupTapTargetEvidence(prepared.target),
|
|
6666
|
+
...routeEvidence,
|
|
6667
|
+
reason: "expected_route_not_reached",
|
|
6668
|
+
};
|
|
6669
|
+
}
|
|
6584
6670
|
return {
|
|
6585
6671
|
...base,
|
|
6586
6672
|
...setupScopeEvidence(scope),
|
|
6587
6673
|
ok: true,
|
|
6588
6674
|
...setupTapTargetEvidence(prepared.target),
|
|
6675
|
+
...routeEvidence,
|
|
6589
6676
|
};
|
|
6590
6677
|
}
|
|
6591
6678
|
if (type === "tap_until") {
|
|
@@ -7446,6 +7533,26 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
7446
7533
|
: { x: box.x + box.width / 2, y: box.y + box.height / 2 };
|
|
7447
7534
|
if (clickCount > 1) await page.mouse.click(fallbackPoint.x, fallbackPoint.y, { clickCount });
|
|
7448
7535
|
else await page.mouse.click(fallbackPoint.x, fallbackPoint.y);
|
|
7536
|
+
const routeEvidence = await waitForSetupActionRoute(action, timeout);
|
|
7537
|
+
if (routeEvidence && !routeEvidence.route_matched) {
|
|
7538
|
+
return {
|
|
7539
|
+
...base,
|
|
7540
|
+
...setupScopeEvidence(scope),
|
|
7541
|
+
count,
|
|
7542
|
+
target_index: targetIndex,
|
|
7543
|
+
text: matchedText,
|
|
7544
|
+
force: action.force === true || undefined,
|
|
7545
|
+
fallback_to_tap: true,
|
|
7546
|
+
input_dispatch: "playwright_mouse",
|
|
7547
|
+
click_error: String(error && error.message ? error.message : error).slice(0, 1000),
|
|
7548
|
+
click_count: clickCount > 1 ? clickCount : undefined,
|
|
7549
|
+
coordinate_mode: mode,
|
|
7550
|
+
x: position ? fromX : undefined,
|
|
7551
|
+
y: position ? fromY : undefined,
|
|
7552
|
+
...routeEvidence,
|
|
7553
|
+
reason: "expected_route_not_reached",
|
|
7554
|
+
};
|
|
7555
|
+
}
|
|
7449
7556
|
return {
|
|
7450
7557
|
...base,
|
|
7451
7558
|
...setupScopeEvidence(scope),
|
|
@@ -7461,6 +7568,24 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
7461
7568
|
coordinate_mode: mode,
|
|
7462
7569
|
x: position ? fromX : undefined,
|
|
7463
7570
|
y: position ? fromY : undefined,
|
|
7571
|
+
...routeEvidence,
|
|
7572
|
+
};
|
|
7573
|
+
}
|
|
7574
|
+
const routeEvidence = await waitForSetupActionRoute(action, timeout);
|
|
7575
|
+
if (routeEvidence && !routeEvidence.route_matched) {
|
|
7576
|
+
return {
|
|
7577
|
+
...base,
|
|
7578
|
+
...setupScopeEvidence(scope),
|
|
7579
|
+
count,
|
|
7580
|
+
target_index: targetIndex,
|
|
7581
|
+
text: matchedText,
|
|
7582
|
+
force: action.force === true || undefined,
|
|
7583
|
+
click_count: clickCount > 1 ? clickCount : undefined,
|
|
7584
|
+
coordinate_mode: mode,
|
|
7585
|
+
x: position ? fromX : undefined,
|
|
7586
|
+
y: position ? fromY : undefined,
|
|
7587
|
+
...routeEvidence,
|
|
7588
|
+
reason: "expected_route_not_reached",
|
|
7464
7589
|
};
|
|
7465
7590
|
}
|
|
7466
7591
|
return {
|
|
@@ -7475,6 +7600,7 @@ async function executeSetupAction(action, ordinal, viewport) {
|
|
|
7475
7600
|
coordinate_mode: mode,
|
|
7476
7601
|
x: position ? fromX : undefined,
|
|
7477
7602
|
y: position ? fromY : undefined,
|
|
7603
|
+
...routeEvidence,
|
|
7478
7604
|
};
|
|
7479
7605
|
}
|
|
7480
7606
|
if (type === "fill" || type === "set_input_value") {
|
package/dist/cli/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import "../chunk-
|
|
2
|
-
import "../chunk-
|
|
3
|
-
import "../chunk-
|
|
1
|
+
import "../chunk-F4HKK2YH.js";
|
|
2
|
+
import "../chunk-Z2LCVROU.js";
|
|
3
|
+
import "../chunk-DI2XNGEZ.js";
|
|
4
4
|
import "../chunk-ZREWMTFA.js";
|
|
5
5
|
import "../chunk-ZQWVXQKJ.js";
|
|
6
6
|
import "../chunk-RDPG554T.js";
|