waygraph 0.15.37 → 0.15.39
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/auto-session/session.d.ts +2 -0
- package/dist/auto-session/session.js +16 -1
- package/dist/cli/flags.d.ts +4 -0
- package/dist/cli/flags.js +12 -0
- package/dist/cli/usage.js +5 -0
- package/dist/pilot-overlay/overlay-fixtures.d.ts +9 -0
- package/dist/pilot-overlay/overlay-fixtures.js +60 -0
- package/dist/runner/main.js +51 -1
- package/examples/saucedemo/.waygraph-auto/2b831907.log +6 -0
- package/examples/saucedemo/.waygraph-auto/3c1e5fe0.log +22 -0
- package/examples/saucedemo/.waygraph-auto/4ad09ece.log +0 -0
- package/examples/saucedemo/.waygraph-auto/70c97639.log +0 -0
- package/examples/saucedemo/.waygraph-auto/7b226350.log +5 -0
- package/examples/saucedemo/.waygraph-auto/7effd5b2.log +20 -0
- package/examples/saucedemo/.waygraph-auto/849ed45d.log +0 -0
- package/examples/saucedemo/.waygraph-auto/9761c4c4.log +6 -0
- package/examples/saucedemo/.waygraph-auto/9dd78c5e.log +0 -0
- package/examples/saucedemo/.waygraph-auto/aa1beafb.log +0 -0
- package/examples/saucedemo/.waygraph-auto/aaae4fb0.log +20 -0
- package/examples/saucedemo/.waygraph-auto/b2d2dbb2.log +22 -0
- package/examples/saucedemo/.waygraph-auto/c851cc53.log +6 -0
- package/examples/saucedemo/.waygraph-auto/ce584949.log +5 -0
- package/examples/saucedemo/.waygraph-auto/ddf975e6.log +0 -0
- package/package.json +1 -1
|
@@ -72,6 +72,8 @@ export declare class AutoSession {
|
|
|
72
72
|
* fallback when a Block's own `resolve()` doesn't set `__state` - same
|
|
73
73
|
* behavior `applyPick` always had, just factored out, not changed.
|
|
74
74
|
*/
|
|
75
|
+
/** Paint + log a Block's authored waygraph overlay fixtures (same as demo does), best-effort. */
|
|
76
|
+
private paintStubPhase;
|
|
75
77
|
private runNamedBlock;
|
|
76
78
|
/** Applies exactly one pick: runs at most one Block, returns the resulting state. */
|
|
77
79
|
applyPick(raw: string): Promise<ApplyPickResult>;
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
// Split out of the former 1,078-line auto-session.ts (see src/ARCHITECTURE.md). Behavior unchanged.
|
|
2
2
|
import { CONSOLE_LOG_MAX_ENTRIES, FULL_MODE_DEFAULT_DEPTH, FULL_MODE_MAX_NODES, FULL_MODE_MAX_TEXT_LENGTH, TRACE_MAX_STEPS, buildSessionSnapshot, parsePick, stubFilePath, stubPhaseHasContent, walkFullDom } from "./helpers.js";
|
|
3
|
-
import { instrumentPilotActions, installPersistentPilotOverlay, showPilotActivity, showPilotFixtures, showPilotVision, updatePilotOverlay } from "../pilot-overlay.js";
|
|
3
|
+
import { instrumentPilotActions, installPersistentPilotOverlay, showPilotActivity, showPilotFixtures, showPilotVision, phaseToOverlayFixtures, describeOverlayFixtures, updatePilotOverlay } from "../pilot-overlay.js";
|
|
4
4
|
import { buildExploreContext, buildExploreMenu } from "../auto-explore.js";
|
|
5
5
|
import { MemPage } from "../mem-page.js";
|
|
6
6
|
import { Engine } from "../engine.js";
|
|
7
7
|
import { detectHere, ensureLivePage, ensureMem, resolveBaseUrl, runOneBlock, seedDefaultMem } from "../auto-explore-run.js";
|
|
8
8
|
import { collectKnownInteractionSelectors, unmappedInteractionsPageScript } from "../coverage-gap.js";
|
|
9
9
|
import { runStubPhase } from "../highlights.js";
|
|
10
|
+
import { verboseLog } from "../verbose-log.js";
|
|
10
11
|
import { findBlockPathDetailed } from "../graph.js";
|
|
11
12
|
/**
|
|
12
13
|
* Non-interactive explore session: same graph/library/mem/browser setup
|
|
@@ -328,9 +329,19 @@ export class AutoSession {
|
|
|
328
329
|
* fallback when a Block's own `resolve()` doesn't set `__state` - same
|
|
329
330
|
* behavior `applyPick` always had, just factored out, not changed.
|
|
330
331
|
*/
|
|
332
|
+
/** Paint + log a Block's authored waygraph overlay fixtures (same as demo does), best-effort. */
|
|
333
|
+
async paintStubPhase(tag, phase, holdMs) {
|
|
334
|
+
if (!this.page || !stubPhaseHasContent(phase))
|
|
335
|
+
return;
|
|
336
|
+
const fixtures = phaseToOverlayFixtures(phase, holdMs);
|
|
337
|
+
for (const line of describeOverlayFixtures(tag, fixtures))
|
|
338
|
+
verboseLog("pilot", line);
|
|
339
|
+
await showPilotFixtures(this.page, fixtures).catch(() => { });
|
|
340
|
+
}
|
|
331
341
|
async runNamedBlock(entry, expectedTo, instanceOption) {
|
|
332
342
|
const from = this.here;
|
|
333
343
|
const stubBeforeResult = await runStubPhase(entry.block, "stubBefore");
|
|
344
|
+
await this.paintStubPhase("stub.before", stubBeforeResult, 6000);
|
|
334
345
|
const stepBase = {
|
|
335
346
|
block: entry.block.name,
|
|
336
347
|
from,
|
|
@@ -348,6 +359,7 @@ export class AutoSession {
|
|
|
348
359
|
this.here = result.__state ?? expectedTo;
|
|
349
360
|
this.lastRunNote = `${entry.block.name} -> ${this.here}`;
|
|
350
361
|
const stubAfterResult = await runStubPhase(entry.block, "stubAfter", { out: result });
|
|
362
|
+
await this.paintStubPhase("stub.after", stubAfterResult, 6000);
|
|
351
363
|
this.pushTrace({
|
|
352
364
|
...stepBase,
|
|
353
365
|
to: this.here,
|
|
@@ -358,6 +370,7 @@ export class AutoSession {
|
|
|
358
370
|
this.lastRunNote = `${entry.block.name} failed`;
|
|
359
371
|
const message = err instanceof Error ? err.message : String(err);
|
|
360
372
|
const stubOnErrorResult = await runStubPhase(entry.block, "stubOnError", { error: err });
|
|
373
|
+
await this.paintStubPhase("stub.error", stubOnErrorResult, 8000);
|
|
361
374
|
this.pushTrace({
|
|
362
375
|
...stepBase,
|
|
363
376
|
error: message,
|
|
@@ -588,6 +601,8 @@ export class AutoSession {
|
|
|
588
601
|
// Same bottom-left activity toast as Running (Dom)/(Block) - agent narration.
|
|
589
602
|
await showPilotActivity(this.page, `Highlighting: ${detail}`);
|
|
590
603
|
try {
|
|
604
|
+
for (const line of describeOverlayFixtures("highlight", fixtures))
|
|
605
|
+
verboseLog("pilot", line);
|
|
591
606
|
const { painted, missing } = await showPilotFixtures(this.page, fixtures);
|
|
592
607
|
const menu = await this.currentMenu();
|
|
593
608
|
this.lastRunNote = fixtures.clear
|
package/dist/cli/flags.d.ts
CHANGED
|
@@ -15,6 +15,10 @@ interface RunFlags {
|
|
|
15
15
|
data?: string;
|
|
16
16
|
/** Fill any requires key with no --data coverage from registerMemStub's registry (--mem-stub). */
|
|
17
17
|
memStub?: boolean;
|
|
18
|
+
/** run only: explore every .branch() path (runBranchRegression), cloning the session at each branch point. */
|
|
19
|
+
allBranches?: boolean;
|
|
20
|
+
/** --all-branches only: one shared session (no cloning) - follows the single live-dispatch path instead. */
|
|
21
|
+
sharedSession?: boolean;
|
|
18
22
|
/** Flow/chain spec from --blocks <spec>. */
|
|
19
23
|
blocks?: string;
|
|
20
24
|
/** auto path-find: --blocks <fromCheckpoint> <toCheckpoint>. */
|
package/dist/cli/flags.js
CHANGED
|
@@ -141,6 +141,12 @@ export function parseRunFlags(argv) {
|
|
|
141
141
|
else if (a === "--mem-stub") {
|
|
142
142
|
out.memStub = true;
|
|
143
143
|
}
|
|
144
|
+
else if (a === "--all-branches") {
|
|
145
|
+
out.allBranches = true;
|
|
146
|
+
}
|
|
147
|
+
else if (a === "--shared-session") {
|
|
148
|
+
out.sharedSession = true;
|
|
149
|
+
}
|
|
144
150
|
else if (a === "--video" || a.startsWith("--video=")) {
|
|
145
151
|
if (a.startsWith("--video=")) {
|
|
146
152
|
out.video = a.slice("--video=".length);
|
|
@@ -271,6 +277,12 @@ export function applyRunFlags(flags, opts) {
|
|
|
271
277
|
if (flags.memStub) {
|
|
272
278
|
process.env.WAYGRAPH_MEM_STUB = "1";
|
|
273
279
|
}
|
|
280
|
+
if (flags.allBranches) {
|
|
281
|
+
process.env.WAYGRAPH_ALL_BRANCHES = "1";
|
|
282
|
+
}
|
|
283
|
+
if (flags.sharedSession) {
|
|
284
|
+
process.env.WAYGRAPH_SHARED_SESSION = "1";
|
|
285
|
+
}
|
|
274
286
|
if (flags.fast) {
|
|
275
287
|
process.env.WAYGRAPH_DEMO_FAST = "1";
|
|
276
288
|
}
|
package/dist/cli/usage.js
CHANGED
|
@@ -162,6 +162,11 @@ Primary (less is more):
|
|
|
162
162
|
waygraph run [--blocks <flow|file|spec>] Execute (no overlay unless --step)
|
|
163
163
|
--data '{...}'
|
|
164
164
|
--mem-stub Same as demo's --mem-stub
|
|
165
|
+
--all-branches Bare Flow ref only: explore every MapBuilder.branch()
|
|
166
|
+
path, cloning the session (storageState+URL) at each
|
|
167
|
+
branch point - see runBranchRegression()
|
|
168
|
+
--shared-session With --all-branches: one shared session instead of
|
|
169
|
+
cloning (follows only the live-dispatch path)
|
|
165
170
|
--non-headless Show browser
|
|
166
171
|
--video [dir] Record .webm
|
|
167
172
|
--video-viewport WxH Recording size (default run: 1280x720)
|
|
@@ -7,3 +7,12 @@ import type { PilotHighlightFixtures } from "./fixtures.js";
|
|
|
7
7
|
* Not Playwright test fixtures - these describe what the waygraph overlay paints on the page under test.
|
|
8
8
|
*/
|
|
9
9
|
export declare function overlayFixturesToPhase(f: PilotHighlightFixtures): Promise<StubPhaseResult>;
|
|
10
|
+
/**
|
|
11
|
+
* The reverse: a resolved stub phase (what `runStubPhase` returns for a Block's stubBefore/After/OnError)
|
|
12
|
+
* -> what the Pilot painter takes. Lets `auto/browser/pilot send` paint a Block's authored waygraph overlay
|
|
13
|
+
* fixtures (rings, todos, device, zoom, title/banner) the way `waygraph demo` does, instead of only recording
|
|
14
|
+
* them in the trace.
|
|
15
|
+
*/
|
|
16
|
+
export declare function phaseToOverlayFixtures(phase: StubPhaseResult, holdMs?: number): PilotHighlightFixtures;
|
|
17
|
+
/** One verbose line per authored overlay fixture - same wording on every surface so a log reader (or an AI with no eyes) can tell what was painted. */
|
|
18
|
+
export declare function describeOverlayFixtures(tag: string, f: PilotHighlightFixtures): string[];
|
|
@@ -43,3 +43,63 @@ export async function overlayFixturesToPhase(f) {
|
|
|
43
43
|
};
|
|
44
44
|
return runStubPhase({ name: "overlay-fixtures", stubBefore: lifecycle }, "stubBefore");
|
|
45
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* The reverse: a resolved stub phase (what `runStubPhase` returns for a Block's stubBefore/After/OnError)
|
|
48
|
+
* -> what the Pilot painter takes. Lets `auto/browser/pilot send` paint a Block's authored waygraph overlay
|
|
49
|
+
* fixtures (rings, todos, device, zoom, title/banner) the way `waygraph demo` does, instead of only recording
|
|
50
|
+
* them in the trace.
|
|
51
|
+
*/
|
|
52
|
+
export function phaseToOverlayFixtures(phase, holdMs = 6000) {
|
|
53
|
+
const items = phase.todoDock?.groups[0]?.items ?? phase.todos;
|
|
54
|
+
const idx = items.findIndex((t) => t.current) >= 0 ? items.findIndex((t) => t.current) : items.findIndex((t) => !t.done);
|
|
55
|
+
return {
|
|
56
|
+
rings: phase.highlights.map((h) => ({
|
|
57
|
+
selector: h.selector,
|
|
58
|
+
label: h.label ?? "",
|
|
59
|
+
...(h.detail ? { detail: h.detail } : {}),
|
|
60
|
+
...(h.tag ? { tag: h.tag } : {}),
|
|
61
|
+
...(h.tone ? { tone: h.tone } : {}),
|
|
62
|
+
...(h.size ? { size: h.size } : {}),
|
|
63
|
+
...(h.weight ? { weight: h.weight } : {}),
|
|
64
|
+
...(h.color ? { color: h.color } : {}),
|
|
65
|
+
...(h.zoom !== undefined ? { zoom: h.zoom } : {}),
|
|
66
|
+
...(h.zoomOut !== undefined ? { zoomOut: h.zoomOut } : {}),
|
|
67
|
+
...(h.focus ? { focus: true } : {}),
|
|
68
|
+
})),
|
|
69
|
+
...(phase.todoSync === "set" && items.length
|
|
70
|
+
? {
|
|
71
|
+
todos: items.map((t) => t.text),
|
|
72
|
+
todoIndex: idx < 0 ? items.length : idx,
|
|
73
|
+
...(phase.todoDock?.groups[0]?.title ? { todoTitle: phase.todoDock.groups[0].title } : {}),
|
|
74
|
+
...(phase.todoPos ? { todoPos: phase.todoPos } : {}),
|
|
75
|
+
}
|
|
76
|
+
: {}),
|
|
77
|
+
...(phase.todoDockUi ? { todoDockUi: phase.todoDockUi } : {}),
|
|
78
|
+
...(phase.deviceSync === "set" && phase.device ? { device: phase.device } : {}),
|
|
79
|
+
...(phase.zoom !== undefined ? { zoom: phase.zoom } : {}),
|
|
80
|
+
...(phase.zoomOut !== undefined ? { zoomOut: phase.zoomOut } : {}),
|
|
81
|
+
...(phase.title ? { title: phase.title } : {}),
|
|
82
|
+
...(phase.titlePos ? { titlePos: phase.titlePos } : {}),
|
|
83
|
+
...(phase.bannerUi ? { bannerUi: phase.bannerUi } : {}),
|
|
84
|
+
holdMs,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/** One verbose line per authored overlay fixture - same wording on every surface so a log reader (or an AI with no eyes) can tell what was painted. */
|
|
88
|
+
export function describeOverlayFixtures(tag, f) {
|
|
89
|
+
const out = [];
|
|
90
|
+
if (f.title)
|
|
91
|
+
out.push(`${tag} ctx.title(${JSON.stringify(f.title)})${f.titlePos ? ` pos=${f.titlePos}` : ""}`);
|
|
92
|
+
if (f.bannerUi)
|
|
93
|
+
out.push(`${tag} ctx.bannerUi(${JSON.stringify(f.bannerUi)})`);
|
|
94
|
+
if (f.todos?.length)
|
|
95
|
+
out.push(`${tag} ctx.todos n=${f.todos.length} index=${f.todoIndex ?? 0}${f.todoPos ? ` pos=${f.todoPos}` : ""}`);
|
|
96
|
+
if (f.todoDockUi ?? f.todoUi)
|
|
97
|
+
out.push(`${tag} ctx.todoDockUi(${JSON.stringify(f.todoDockUi ?? f.todoUi)})`);
|
|
98
|
+
if (f.device)
|
|
99
|
+
out.push(`${tag} ctx.device(${typeof f.device === "string" ? f.device : f.device.preset ?? "custom"})`);
|
|
100
|
+
if (f.zoom)
|
|
101
|
+
out.push(`${tag} ctx.zoom(${f.zoom})`);
|
|
102
|
+
for (const r of f.rings ?? [])
|
|
103
|
+
out.push(`${tag} ring ${r.selector} tone=${r.tone ?? "planned"} label=${JSON.stringify(r.label)}`);
|
|
104
|
+
return out;
|
|
105
|
+
}
|
package/dist/runner/main.js
CHANGED
|
@@ -8,7 +8,7 @@ import { isExpectedChainFailure, parseVideoViewport, runChainedFlows, runJsonRep
|
|
|
8
8
|
import { runStepMode } from "./step-mode.js";
|
|
9
9
|
import { connect } from "../types.js";
|
|
10
10
|
import { MemPage } from "../mem-page.js";
|
|
11
|
-
import { Engine, start, end, chainFlow, isFastForwardBlock } from "../engine.js";
|
|
11
|
+
import { Engine, start, end, chainFlow, isFastForwardBlock, branchRoutes, runBranchRegression } from "../engine.js";
|
|
12
12
|
|
|
13
13
|
async function main() {
|
|
14
14
|
const projectDir = process.argv[2];
|
|
@@ -275,6 +275,9 @@ async function main() {
|
|
|
275
275
|
if (r.seedMem) r.seedMem();
|
|
276
276
|
}
|
|
277
277
|
}
|
|
278
|
+
if (process.env.WAYGRAPH_ALL_BRANCHES === "1") {
|
|
279
|
+
return runAllBranchesMode(chainFlows, mem, baseURL, headed, engine);
|
|
280
|
+
}
|
|
278
281
|
if (step || jsonReport || baseURL || videoDir) {
|
|
279
282
|
const { chromium } = await import("@playwright/test");
|
|
280
283
|
// --start-maximized (step mode only): viewport: null alone only made
|
|
@@ -389,6 +392,53 @@ async function main() {
|
|
|
389
392
|
}
|
|
390
393
|
}
|
|
391
394
|
|
|
395
|
+
/**
|
|
396
|
+
* `waygraph run --blocks <flowName> --all-branches`: explore every path through that flow's own
|
|
397
|
+
* `.branch()` tree (see src/engine/branch-regression.ts), not just whichever one the live state
|
|
398
|
+
* would dispatch to. Needs a single, bare Flow reference - a multi-segment chain spec has no one
|
|
399
|
+
* Flow to walk. `--shared-session` opts out of session cloning (WAYGRAPH_SHARED_SESSION=1).
|
|
400
|
+
*/
|
|
401
|
+
async function runAllBranchesMode(chainFlows, mem, baseURL, headed, engine) {
|
|
402
|
+
if (!chainFlows || chainFlows.length !== 1) {
|
|
403
|
+
console.error(
|
|
404
|
+
"waygraph run --all-branches: needs a single Flow reference (e.g. --blocks loginFlow), " +
|
|
405
|
+
"not a multi-segment chain spec - nothing else has one branch tree to explore.",
|
|
406
|
+
);
|
|
407
|
+
process.exitCode = 1;
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
const flow = chainFlows[0];
|
|
411
|
+
if (!branchRoutes(flow)) {
|
|
412
|
+
console.error(
|
|
413
|
+
"waygraph run --all-branches: this Flow was not built with MapBuilder.branch() - " +
|
|
414
|
+
"there is no branch tree to explore. Run it normally instead.",
|
|
415
|
+
);
|
|
416
|
+
process.exitCode = 1;
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
const { chromium } = await import("@playwright/test");
|
|
420
|
+
const browser = await chromium.launch({ headless: !headed });
|
|
421
|
+
const cloneSession = process.env.WAYGRAPH_SHARED_SESSION !== "1";
|
|
422
|
+
try {
|
|
423
|
+
const context = await browser.newContext(baseURL ? { baseURL } : undefined);
|
|
424
|
+
const results = await runBranchRegression(flow, context, mem, { cloneSession });
|
|
425
|
+
for (const r of results) {
|
|
426
|
+
const line = `waygraph run --all-branches: ${r.path || "(root)"} -> ${r.status}` +
|
|
427
|
+
(r.result ? ` (${JSON.stringify(r.result)})` : "") +
|
|
428
|
+
(r.error ? ` - ${r.error}` : "");
|
|
429
|
+
console.log(line);
|
|
430
|
+
}
|
|
431
|
+
const failed = results.filter((r) => r.status === "failed");
|
|
432
|
+
if (failed.length) {
|
|
433
|
+
console.error(`waygraph run --all-branches: ${failed.length}/${results.length} path(s) failed`);
|
|
434
|
+
process.exitCode = 1;
|
|
435
|
+
}
|
|
436
|
+
} finally {
|
|
437
|
+
await browser.close();
|
|
438
|
+
}
|
|
439
|
+
void engine;
|
|
440
|
+
}
|
|
441
|
+
|
|
392
442
|
export function startRunner() {
|
|
393
443
|
main().catch((err) => {
|
|
394
444
|
console.error(err && err.stack ? err.stack : String(err));
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
[21:45:47.529] waygraph pilot: stub.before ctx.title("Signing in · mobile")
|
|
2
|
+
[21:45:47.529] waygraph pilot: stub.before ctx.todos n=6 index=0
|
|
3
|
+
[21:45:47.529] waygraph pilot: stub.before ctx.device(mobile)
|
|
4
|
+
[21:45:47.529] waygraph pilot: stub.before ctx.zoom(1.35)
|
|
5
|
+
[21:45:47.529] waygraph pilot: stub.before ring #user-name tone=info label="Username"
|
|
6
|
+
[21:45:47.633] waygraph pilot: stub.after ctx.todos n=6 index=1
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
[21:46:29.741] waygraph pilot: stub.before ctx.title("Signing in · mobile")
|
|
2
|
+
[21:46:29.741] waygraph pilot: stub.before ctx.todos n=6 index=0
|
|
3
|
+
[21:46:29.741] waygraph pilot: stub.before ctx.device(mobile)
|
|
4
|
+
[21:46:29.741] waygraph pilot: stub.before ctx.zoom(1.35)
|
|
5
|
+
[21:46:29.741] waygraph pilot: stub.before ring #user-name tone=info label="Username"
|
|
6
|
+
[21:46:29.866] waygraph pilot: stub.after ctx.todos n=6 index=1
|
|
7
|
+
[21:46:31.935] waygraph pilot: stub.before ring #password tone=planned label="Password"
|
|
8
|
+
[21:46:31.998] waygraph pilot: stub.after ctx.todos n=6 index=2
|
|
9
|
+
[21:46:33.773] waygraph pilot: stub.before ring #login-button tone=warning label="Login"
|
|
10
|
+
[21:46:33.961] waygraph pilot: stub.after ctx.title("Inventory · landscape")
|
|
11
|
+
[21:46:33.961] waygraph pilot: stub.after ctx.todos n=6 index=3
|
|
12
|
+
[21:46:33.961] waygraph pilot: stub.after ctx.device(mobile)
|
|
13
|
+
[21:46:33.961] waygraph pilot: stub.after ring .inventory_list tone=success label="Product shelf"
|
|
14
|
+
[21:46:37.277] waygraph pilot: stub.before ctx.title("Pick a product · tablet")
|
|
15
|
+
[21:46:37.277] waygraph pilot: stub.before ctx.todos n=6 index=3
|
|
16
|
+
[21:46:37.277] waygraph pilot: stub.before ctx.device(tablet)
|
|
17
|
+
[21:46:37.277] waygraph pilot: stub.before ctx.zoom(1.35)
|
|
18
|
+
[21:46:37.277] waygraph pilot: stub.before ring div.inventory_item:has(button[data-test="add-to-cart-sauce-labs-backpack"], button[data-test="remove-sauce-labs-backpack"]) .inventory_item_name tone=info label="Sauce Labs Backpack"
|
|
19
|
+
[21:46:37.277] waygraph pilot: stub.before ring [data-test="add-to-cart-sauce-labs-backpack"] tone=success label="Add to cart"
|
|
20
|
+
[21:46:37.375] waygraph pilot: stub.after ctx.title("In the cart")
|
|
21
|
+
[21:46:37.376] waygraph pilot: stub.after ctx.todos n=6 index=4
|
|
22
|
+
[21:46:37.376] waygraph pilot: stub.after ring .shopping_cart_badge tone=success label="Cart badge"
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
[21:46:10.717] waygraph pilot: highlight ctx.todos n=3 index=0
|
|
2
|
+
[21:46:10.717] waygraph pilot: highlight ring #user-name tone=planned label="Username"
|
|
3
|
+
[21:46:10.717] waygraph pilot: highlight ring #password tone=info label="Password"
|
|
4
|
+
[21:46:12.774] waygraph pilot: highlight ring #no-such-element-waygraph tone=danger label="Gone"
|
|
5
|
+
[21:46:14.903] waygraph pilot: highlight ring #login-button tone=success label="Login"
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
[21:46:24.561] waygraph pilot: stub.before ctx.title("Signing in · mobile")
|
|
2
|
+
[21:46:24.562] waygraph pilot: stub.before ctx.todos n=6 index=0
|
|
3
|
+
[21:46:24.562] waygraph pilot: stub.before ctx.device(mobile)
|
|
4
|
+
[21:46:24.562] waygraph pilot: stub.before ctx.zoom(1.35)
|
|
5
|
+
[21:46:24.562] waygraph pilot: stub.before ring #user-name tone=info label="Username"
|
|
6
|
+
[21:46:24.751] waygraph pilot: stub.after ctx.todos n=6 index=1
|
|
7
|
+
[21:46:25.895] waygraph pilot: stub.before ring #password tone=planned label="Password"
|
|
8
|
+
[21:46:25.977] waygraph pilot: stub.after ctx.todos n=6 index=2
|
|
9
|
+
[21:46:27.278] waygraph pilot: stub.before ring #login-button tone=warning label="Login"
|
|
10
|
+
[21:46:27.476] waygraph pilot: stub.after ctx.title("Inventory · landscape")
|
|
11
|
+
[21:46:27.476] waygraph pilot: stub.after ctx.todos n=6 index=3
|
|
12
|
+
[21:46:27.476] waygraph pilot: stub.after ctx.device(mobile)
|
|
13
|
+
[21:46:27.476] waygraph pilot: stub.after ring .inventory_list tone=success label="Product shelf"
|
|
14
|
+
[21:46:28.988] waygraph pilot: stub.before ctx.title("Open cart · landscape")
|
|
15
|
+
[21:46:28.988] waygraph pilot: stub.before ctx.todos n=6 index=5
|
|
16
|
+
[21:46:28.988] waygraph pilot: stub.before ctx.device(mobile)
|
|
17
|
+
[21:46:28.988] waygraph pilot: stub.before ctx.zoom(1.4)
|
|
18
|
+
[21:46:28.988] waygraph pilot: stub.before ring .shopping_cart_link tone=planned label="Cart"
|
|
19
|
+
[21:46:29.115] waygraph pilot: stub.after ctx.title("Your cart · desktop")
|
|
20
|
+
[21:46:29.116] waygraph pilot: stub.after ring .cart_item tone=success label="Cart items"
|
|
File without changes
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
[21:46:28.846] waygraph pilot: stub.before ctx.title("Signing in · mobile")
|
|
2
|
+
[21:46:28.846] waygraph pilot: stub.before ctx.todos n=6 index=0
|
|
3
|
+
[21:46:28.846] waygraph pilot: stub.before ctx.device(mobile)
|
|
4
|
+
[21:46:28.847] waygraph pilot: stub.before ctx.zoom(1.35)
|
|
5
|
+
[21:46:28.847] waygraph pilot: stub.before ring #user-name tone=info label="Username"
|
|
6
|
+
[21:46:29.003] waygraph pilot: stub.after ctx.todos n=6 index=1
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
[11:12:59.725] waygraph pilot: stub.before ctx.title("Signing in · mobile")
|
|
2
|
+
[11:12:59.725] waygraph pilot: stub.before ctx.todos n=6 index=0
|
|
3
|
+
[11:12:59.725] waygraph pilot: stub.before ctx.device(mobile)
|
|
4
|
+
[11:12:59.725] waygraph pilot: stub.before ctx.zoom(1.35)
|
|
5
|
+
[11:12:59.725] waygraph pilot: stub.before ring #user-name tone=info label="Username"
|
|
6
|
+
[11:13:00.015] waygraph pilot: stub.after ctx.todos n=6 index=1
|
|
7
|
+
[11:13:01.590] waygraph pilot: stub.before ring #password tone=planned label="Password"
|
|
8
|
+
[11:13:01.964] waygraph pilot: stub.after ctx.todos n=6 index=2
|
|
9
|
+
[11:13:03.710] waygraph pilot: stub.before ring #login-button tone=warning label="Login"
|
|
10
|
+
[11:13:03.904] waygraph pilot: stub.after ctx.title("Inventory · landscape")
|
|
11
|
+
[11:13:03.904] waygraph pilot: stub.after ctx.todos n=6 index=3
|
|
12
|
+
[11:13:03.904] waygraph pilot: stub.after ctx.device(mobile)
|
|
13
|
+
[11:13:03.904] waygraph pilot: stub.after ring .inventory_list tone=success label="Product shelf"
|
|
14
|
+
[11:13:06.313] waygraph pilot: stub.before ctx.title("Open cart · landscape")
|
|
15
|
+
[11:13:06.313] waygraph pilot: stub.before ctx.todos n=6 index=5
|
|
16
|
+
[11:13:06.313] waygraph pilot: stub.before ctx.device(mobile)
|
|
17
|
+
[11:13:06.313] waygraph pilot: stub.before ctx.zoom(1.4)
|
|
18
|
+
[11:13:06.313] waygraph pilot: stub.before ring .shopping_cart_link tone=planned label="Cart"
|
|
19
|
+
[11:13:06.502] waygraph pilot: stub.after ctx.title("Your cart · desktop")
|
|
20
|
+
[11:13:06.502] waygraph pilot: stub.after ring .cart_item tone=success label="Cart items"
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
[11:13:06.492] waygraph pilot: stub.before ctx.title("Signing in · mobile")
|
|
2
|
+
[11:13:06.493] waygraph pilot: stub.before ctx.todos n=6 index=0
|
|
3
|
+
[11:13:06.493] waygraph pilot: stub.before ctx.device(mobile)
|
|
4
|
+
[11:13:06.493] waygraph pilot: stub.before ctx.zoom(1.35)
|
|
5
|
+
[11:13:06.493] waygraph pilot: stub.before ring #user-name tone=info label="Username"
|
|
6
|
+
[11:13:06.696] waygraph pilot: stub.after ctx.todos n=6 index=1
|
|
7
|
+
[11:13:09.771] waygraph pilot: stub.before ring #password tone=planned label="Password"
|
|
8
|
+
[11:13:09.947] waygraph pilot: stub.after ctx.todos n=6 index=2
|
|
9
|
+
[11:13:12.614] waygraph pilot: stub.before ring #login-button tone=warning label="Login"
|
|
10
|
+
[11:13:12.755] waygraph pilot: stub.after ctx.title("Inventory · landscape")
|
|
11
|
+
[11:13:12.756] waygraph pilot: stub.after ctx.todos n=6 index=3
|
|
12
|
+
[11:13:12.756] waygraph pilot: stub.after ctx.device(mobile)
|
|
13
|
+
[11:13:12.756] waygraph pilot: stub.after ring .inventory_list tone=success label="Product shelf"
|
|
14
|
+
[11:13:16.803] waygraph pilot: stub.before ctx.title("Pick a product · tablet")
|
|
15
|
+
[11:13:16.803] waygraph pilot: stub.before ctx.todos n=6 index=3
|
|
16
|
+
[11:13:16.803] waygraph pilot: stub.before ctx.device(tablet)
|
|
17
|
+
[11:13:16.803] waygraph pilot: stub.before ctx.zoom(1.35)
|
|
18
|
+
[11:13:16.803] waygraph pilot: stub.before ring div.inventory_item:has(button[data-test="add-to-cart-sauce-labs-backpack"], button[data-test="remove-sauce-labs-backpack"]) .inventory_item_name tone=info label="Sauce Labs Backpack"
|
|
19
|
+
[11:13:16.803] waygraph pilot: stub.before ring [data-test="add-to-cart-sauce-labs-backpack"] tone=success label="Add to cart"
|
|
20
|
+
[11:13:17.007] waygraph pilot: stub.after ctx.title("In the cart")
|
|
21
|
+
[11:13:17.007] waygraph pilot: stub.after ctx.todos n=6 index=4
|
|
22
|
+
[11:13:17.010] waygraph pilot: stub.after ring .shopping_cart_badge tone=success label="Cart badge"
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
[11:12:58.813] waygraph pilot: stub.before ctx.title("Signing in · mobile")
|
|
2
|
+
[11:12:58.815] waygraph pilot: stub.before ctx.todos n=6 index=0
|
|
3
|
+
[11:12:58.816] waygraph pilot: stub.before ctx.device(mobile)
|
|
4
|
+
[11:12:58.816] waygraph pilot: stub.before ctx.zoom(1.35)
|
|
5
|
+
[11:12:58.816] waygraph pilot: stub.before ring #user-name tone=info label="Username"
|
|
6
|
+
[11:12:59.236] waygraph pilot: stub.after ctx.todos n=6 index=1
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
[11:12:42.451] waygraph pilot: highlight ctx.todos n=3 index=0
|
|
2
|
+
[11:12:42.451] waygraph pilot: highlight ring #user-name tone=planned label="Username"
|
|
3
|
+
[11:12:42.452] waygraph pilot: highlight ring #password tone=info label="Password"
|
|
4
|
+
[11:12:45.225] waygraph pilot: highlight ring #no-such-element-waygraph tone=danger label="Gone"
|
|
5
|
+
[11:12:48.220] waygraph pilot: highlight ring #login-button tone=success label="Login"
|
|
File without changes
|