waygraph 0.15.38 → 0.15.40
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/flags.d.ts +4 -0
- package/dist/cli/flags.js +12 -0
- package/dist/cli/usage.js +5 -0
- package/dist/pilot-overlay/fixtures.d.ts +5 -1
- package/dist/pilot-overlay/fixtures.js +69 -60
- package/dist/pilot-overlay/shell.js +4 -0
- package/dist/runner/device-stage.d.ts +9 -0
- package/dist/runner/inpage/device.d.ts +3 -0
- package/dist/runner/main.js +51 -1
- package/dist/runner/overlay-css.d.ts +3 -0
- package/examples/saucedemo/.waygraph-auto/3a8674d5.log +6 -0
- package/examples/saucedemo/.waygraph-auto/4ad09ece.log +0 -0
- package/examples/saucedemo/.waygraph-auto/70c97639.log +0 -0
- package/examples/saucedemo/.waygraph-auto/849ed45d.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/b75168f7.log +1 -0
- package/examples/saucedemo/.waygraph-auto/c52bac6d.log +0 -0
- package/examples/saucedemo/.waygraph-auto/c851cc53.log +6 -0
- package/examples/saucedemo/.waygraph-auto/cb05d223.log +0 -0
- package/examples/saucedemo/.waygraph-auto/ce584949.log +5 -0
- package/examples/saucedemo/.waygraph-auto/cf34b895.log +2 -0
- package/examples/saucedemo/.waygraph-auto/d4afe93f.log +5 -0
- package/examples/saucedemo/.waygraph-auto/dddd057c.log +20 -0
- package/examples/saucedemo/.waygraph-auto/f1f38eeb.log +22 -0
- package/examples/saucedemo/.waygraph-auto/f24b2915.log +0 -0
- package/package.json +1 -1
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)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BannerPos, BannerUiOpts, DevicePreset, DeviceState, HighlightTone, TodoDockUiOpts } from "../highlights.js";
|
|
1
|
+
import type { BannerPos, BannerUiOpts, DevicePreset, DeviceState, HighlightTone, TodoDockUiOpts, TodoListStyle, WaygraphTodoGroupInput } from "../highlights.js";
|
|
2
2
|
import type { Page } from "@playwright/test";
|
|
3
3
|
/** One ring the Pilot agent wants painted (same fields as demo stub rings). */
|
|
4
4
|
export type PilotFixtureRing = {
|
|
@@ -40,6 +40,10 @@ export type PilotHighlightFixtures = {
|
|
|
40
40
|
todoTitle?: string;
|
|
41
41
|
/** Todo dock side. Default `right`. */
|
|
42
42
|
todoPos?: "left" | "right";
|
|
43
|
+
/** Presentation: `sequential` (default, arrow walkthrough) | `checklist` | `bullets`. Same as ctx.todoStyle. */
|
|
44
|
+
todoStyle?: TodoListStyle;
|
|
45
|
+
/** Multiple titled lists (FR/Scenarios/ACs, same as ctx.todoGroups) - replaces {@link todos} when set. */
|
|
46
|
+
todoGroups?: readonly WaygraphTodoGroupInput[];
|
|
43
47
|
/**
|
|
44
48
|
* Todo-dock UX (compact / collision / behind-ring). Defaults smart-on;
|
|
45
49
|
* pass false fields to opt out. See {@link TodoDockUiOpts}.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Split out of the former 950-line pilot-overlay.ts (see src/ARCHITECTURE.md). Behavior unchanged.
|
|
2
|
-
import { formatHighlightCaption, normalizeHighlightSize, normalizeHighlightTone, normalizeHighlightWeight, resolveDeviceState, resolveTodoDockUi } from "../highlights.js";
|
|
2
|
+
import { buildTodoDock, formatHighlightCaption, normalizeHighlightSize, normalizeHighlightTone, normalizeHighlightWeight, resolveDeviceState, resolveTodoDockUi } from "../highlights.js";
|
|
3
3
|
import { ensureInstalled } from "./shell.js";
|
|
4
4
|
/**
|
|
5
5
|
* Paint (or clear) agent-authored highlight fixtures on the live page.
|
|
@@ -38,11 +38,24 @@ export async function showPilotFixtures(page, fixtures) {
|
|
|
38
38
|
focus: r.focus === true,
|
|
39
39
|
};
|
|
40
40
|
});
|
|
41
|
-
const todos = fixtures.clear ? [] : (fixtures.todos ?? []);
|
|
42
41
|
const todoIndex = fixtures.todoIndex ?? 0;
|
|
43
42
|
const todoTitle = fixtures.todoTitle ?? "Plan";
|
|
44
43
|
const todoPos = fixtures.todoPos === "left" ? "left" : "right";
|
|
45
44
|
const todoUi = resolveTodoDockUi(fixtures.todoUi ?? null);
|
|
45
|
+
// Real TodoDockState (groups/style), same builder the demo runner uses - not a flat string[]
|
|
46
|
+
// re-implementation, so a Block/agent that authors ctx.todoGroups()/ctx.todoStyle() looks the
|
|
47
|
+
// same on Pilot as it does in `waygraph demo`.
|
|
48
|
+
const todoDock = fixtures.clear
|
|
49
|
+
? undefined
|
|
50
|
+
: buildTodoDock({
|
|
51
|
+
todos: fixtures.todos,
|
|
52
|
+
todoIndex,
|
|
53
|
+
todoTitle,
|
|
54
|
+
todoStyle: fixtures.todoStyle,
|
|
55
|
+
todoGroups: fixtures.todoGroups,
|
|
56
|
+
todoPos,
|
|
57
|
+
});
|
|
58
|
+
const todoGroups = todoDock?.groups ?? [];
|
|
46
59
|
// Effective zoom: phase zoom, else last ring that authored zoom.
|
|
47
60
|
let zoom = fixtures.clear === true
|
|
48
61
|
? 1
|
|
@@ -70,34 +83,29 @@ export async function showPilotFixtures(page, fixtures) {
|
|
|
70
83
|
if (hit?.zoomOut !== undefined)
|
|
71
84
|
zoomOut = hit.zoomOut !== false;
|
|
72
85
|
}
|
|
73
|
-
// Device viewport
|
|
86
|
+
// Device viewport - same runner/device-stage.js + inpage/device.js every other surface uses
|
|
87
|
+
// (toast + persistent chip + touch mode), not a separate, simpler Pilot-only chip.
|
|
74
88
|
if (fixtures.clear === true) {
|
|
75
|
-
|
|
89
|
+
const { applyDeviceToPage } = await import("../runner/device-stage.js");
|
|
90
|
+
await applyDeviceToPage(page, undefined, "clear").catch(() => { });
|
|
76
91
|
}
|
|
77
92
|
else if (fixtures.device !== undefined) {
|
|
78
93
|
const d = resolveDeviceState(fixtures.device);
|
|
79
94
|
if (d) {
|
|
80
|
-
await
|
|
81
|
-
.
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
})
|
|
85
|
-
|
|
95
|
+
const [{ applyDeviceToPage }, { installDevice }] = await Promise.all([
|
|
96
|
+
import("../runner/device-stage.js"),
|
|
97
|
+
import("../runner/inpage/device.js"),
|
|
98
|
+
]);
|
|
99
|
+
await page.evaluate(installDevice, {}).catch(() => { });
|
|
100
|
+
await applyDeviceToPage(page, d, "set").catch(() => { });
|
|
86
101
|
}
|
|
87
102
|
}
|
|
88
|
-
const deviceLabel = fixtures.clear === true
|
|
89
|
-
? ""
|
|
90
|
-
: fixtures.device === undefined
|
|
91
|
-
? ""
|
|
92
|
-
: typeof fixtures.device === "string"
|
|
93
|
-
? fixtures.device
|
|
94
|
-
: fixtures.device.preset || "device";
|
|
95
103
|
const bannerTitle = fixtures.clear ? undefined : fixtures.title;
|
|
96
104
|
const bannerPos = fixtures.clear ? undefined : fixtures.titlePos;
|
|
97
105
|
const bannerHidden = !!fixtures.clear || !!fixtures.bannerUi?.hidden;
|
|
98
106
|
const bannerCollision = fixtures.bannerUi?.collision !== false;
|
|
99
107
|
return page
|
|
100
|
-
.evaluate(({ rings,
|
|
108
|
+
.evaluate(({ rings, todoGroups, todoPos, holdMs, zoom, zoomSelector, zoomOut, clearAll, todoUi, bannerTitle, bannerPos, bannerHidden, bannerCollision, }) => {
|
|
101
109
|
// Same #wg-banner element/CSS the demo runner paints (ui/css/banner.css, already in the
|
|
102
110
|
// shared bundle) - so ctx.title / ctx.titlePos / ctx.bannerUi behave identically on a Pilot
|
|
103
111
|
// session, not a separate re-implementation.
|
|
@@ -178,16 +186,6 @@ export async function showPilotFixtures(page, fixtures) {
|
|
|
178
186
|
root.style.removeProperty("transition");
|
|
179
187
|
__wgById("wg-pilot-fx-zoom")?.remove();
|
|
180
188
|
};
|
|
181
|
-
const setDeviceChip = (label) => {
|
|
182
|
-
__wgById("wg-pilot-fx-device")?.remove();
|
|
183
|
-
if (!label)
|
|
184
|
-
return;
|
|
185
|
-
const chip = document.createElement("div");
|
|
186
|
-
chip.id = "wg-pilot-fx-device";
|
|
187
|
-
chip.dataset.preset = label;
|
|
188
|
-
chip.textContent = `device \u00b7 ${label}`;
|
|
189
|
-
__wgAdd(chip);
|
|
190
|
-
};
|
|
191
189
|
w.__wgPilotFxZoomOutOnHide = zoomOut;
|
|
192
190
|
const clearFx = () => {
|
|
193
191
|
__wgQA(".wg-pilot-fx-ring, .wg-pilot-fx-label").forEach((el) => el.remove());
|
|
@@ -196,7 +194,6 @@ export async function showPilotFixtures(page, fixtures) {
|
|
|
196
194
|
if (w.__wgPilotFxZoomOutOnHide !== false || clearAll)
|
|
197
195
|
clearZoom();
|
|
198
196
|
if (clearAll) {
|
|
199
|
-
__wgById("wg-pilot-fx-device")?.remove();
|
|
200
197
|
clearZoom();
|
|
201
198
|
}
|
|
202
199
|
};
|
|
@@ -261,42 +258,59 @@ export async function showPilotFixtures(page, fixtures) {
|
|
|
261
258
|
focusBox = { x: rect.left, y: rect.top, width: rect.width, height: rect.height };
|
|
262
259
|
}
|
|
263
260
|
}
|
|
264
|
-
|
|
261
|
+
// Real TodoDockState groups (same shape/builder the demo runner uses) - a group's own
|
|
262
|
+
// style (sequential/checklist/bullets) and its own done/current flags drive rendering here,
|
|
263
|
+
// not a re-derived index over a flattened string list.
|
|
264
|
+
const flat = todoGroups.flatMap((g) => g.items);
|
|
265
|
+
if (flat.length > 0) {
|
|
265
266
|
const dock = document.createElement("div");
|
|
266
267
|
dock.id = "wg-pilot-fx-todos";
|
|
267
268
|
dock.dataset.pos = todoPos;
|
|
268
|
-
const title = document.createElement("div");
|
|
269
|
-
title.className = "wg-pilot-fx-todo-title";
|
|
270
|
-
title.textContent = todoTitle;
|
|
271
|
-
dock.appendChild(title);
|
|
272
269
|
const WINDOW = todoUi.cap > 0 ? todoUi.cap : 5;
|
|
273
|
-
const compact = todoUi.compact !== false &&
|
|
270
|
+
const compact = todoUi.compact !== false && flat.length > WINDOW;
|
|
274
271
|
if (compact)
|
|
275
272
|
dock.dataset.compact = "1";
|
|
273
|
+
const currentFlat = Math.max(0, flat.findIndex((it) => it.current));
|
|
276
274
|
let start = 0;
|
|
277
|
-
let end =
|
|
275
|
+
let end = flat.length;
|
|
278
276
|
if (compact) {
|
|
279
|
-
start = Math.max(0,
|
|
280
|
-
end = Math.min(
|
|
277
|
+
start = Math.max(0, currentFlat - Math.floor((WINDOW - 1) / 2));
|
|
278
|
+
end = Math.min(flat.length, start + WINDOW);
|
|
281
279
|
start = Math.max(0, end - WINDOW);
|
|
282
280
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
281
|
+
let flatIdx = 0;
|
|
282
|
+
let shown = 0;
|
|
283
|
+
for (const group of todoGroups) {
|
|
284
|
+
if (group.items.length === 0)
|
|
285
|
+
continue;
|
|
286
|
+
if (group.title) {
|
|
287
|
+
const title = document.createElement("div");
|
|
288
|
+
title.className = "wg-pilot-fx-todo-title";
|
|
289
|
+
title.textContent = group.title;
|
|
290
|
+
dock.appendChild(title);
|
|
291
|
+
}
|
|
292
|
+
const ol = document.createElement("ol");
|
|
293
|
+
const marker = group.style === "checklist" ? (done) => (done ? "\u2611 " : "\u2610 ") : group.style === "bullets" ? () => "\u2022 " : () => "";
|
|
294
|
+
for (const item of group.items) {
|
|
295
|
+
const i = flatIdx++;
|
|
296
|
+
const li = document.createElement("li");
|
|
297
|
+
li.textContent = marker(!!item.done) + item.text;
|
|
298
|
+
if (item.done)
|
|
299
|
+
li.className = "wg-pilot-fx-todo-done";
|
|
300
|
+
else if (item.current)
|
|
301
|
+
li.className = "wg-pilot-fx-todo-now";
|
|
302
|
+
if (compact && (i < start || i >= end))
|
|
303
|
+
li.classList.add("wg-todo-fold");
|
|
304
|
+
else
|
|
305
|
+
shown++;
|
|
306
|
+
ol.appendChild(li);
|
|
307
|
+
}
|
|
308
|
+
dock.appendChild(ol);
|
|
309
|
+
}
|
|
310
|
+
if (compact && flat.length - shown > 0) {
|
|
297
311
|
const more = document.createElement("div");
|
|
298
312
|
more.className = "wg-todo-more";
|
|
299
|
-
more.textContent = "+" + (
|
|
313
|
+
more.textContent = "+" + (flat.length - shown) + " more";
|
|
300
314
|
dock.appendChild(more);
|
|
301
315
|
}
|
|
302
316
|
__wgAdd(dock);
|
|
@@ -342,25 +356,20 @@ export async function showPilotFixtures(page, fixtures) {
|
|
|
342
356
|
else if (zoom > 1.001) {
|
|
343
357
|
setZoomBadge(zoom);
|
|
344
358
|
}
|
|
345
|
-
if (deviceLabel)
|
|
346
|
-
setDeviceChip(deviceLabel);
|
|
347
359
|
if (holdMs > 0 &&
|
|
348
|
-
(painted > 0 ||
|
|
360
|
+
(painted > 0 || todoGroups.some((g) => g.items.length > 0) || zoom > 1.001)) {
|
|
349
361
|
w.__wgPilotFxHideTimer = setTimeout(() => clearFx(), holdMs);
|
|
350
362
|
}
|
|
351
363
|
return { painted, missing };
|
|
352
364
|
}, {
|
|
353
365
|
rings,
|
|
354
|
-
|
|
355
|
-
todoIndex,
|
|
356
|
-
todoTitle,
|
|
366
|
+
todoGroups,
|
|
357
367
|
todoPos,
|
|
358
368
|
holdMs,
|
|
359
369
|
zoom,
|
|
360
370
|
zoomSelector: zoomSelector ?? "",
|
|
361
371
|
zoomOut,
|
|
362
372
|
clearAll: fixtures.clear === true,
|
|
363
|
-
deviceLabel,
|
|
364
373
|
todoUi,
|
|
365
374
|
bannerTitle,
|
|
366
375
|
bannerPos,
|
|
@@ -149,6 +149,10 @@ export async function installPersistentPilotOverlay(context) {
|
|
|
149
149
|
export async function ensureInstalled(page) {
|
|
150
150
|
await ensureShadowRoot(page);
|
|
151
151
|
await page.evaluate(installPilotOverlayShell, OVERLAY_CSS).catch(() => { });
|
|
152
|
+
// Device toast/chip CSS (runner/overlay-css.js's RUNNER_EXTRA_CSS) - same rules the demo runner
|
|
153
|
+
// uses, reused here (not re-authored) so a device fixture looks identical on Pilot.
|
|
154
|
+
const { RUNNER_EXTRA_CSS } = await import("../runner/overlay-css.js");
|
|
155
|
+
await page.evaluate(([css, key]) => __wgCss(css, key), [RUNNER_EXTRA_CSS, "wg-runner-css"]).catch(() => { });
|
|
152
156
|
}
|
|
153
157
|
/**
|
|
154
158
|
* Bottom-left transient toast, separate from the persistent bottom-right
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Page } from "@playwright/test";
|
|
2
|
+
import type { DeviceState } from "../highlights.js";
|
|
3
|
+
|
|
4
|
+
export function applyDeviceToPage(
|
|
5
|
+
page: Page,
|
|
6
|
+
device: DeviceState | undefined,
|
|
7
|
+
sync: "set" | "clear" | "keep",
|
|
8
|
+
): Promise<void>;
|
|
9
|
+
export function applyVideoDeviceStage(page: Page, shell: unknown, viewport: unknown, opts?: unknown): Promise<void>;
|
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
|
+
[11:37:39.688] waygraph pilot: stub.before ctx.title("Signing in · mobile")
|
|
2
|
+
[11:37:39.688] waygraph pilot: stub.before ctx.todos n=6 index=0
|
|
3
|
+
[11:37:39.688] waygraph pilot: stub.before ctx.device(mobile)
|
|
4
|
+
[11:37:39.688] waygraph pilot: stub.before ctx.zoom(1.35)
|
|
5
|
+
[11:37:39.688] waygraph pilot: stub.before ring #user-name tone=info label="Username"
|
|
6
|
+
[11:37:41.397] waygraph pilot: stub.after ctx.todos n=6 index=1
|
|
File without changes
|
|
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 @@
|
|
|
1
|
+
[11:36:30.657] waygraph pilot: highlight ctx.todos n=3 index=1
|
|
File without changes
|
|
@@ -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
|
|
File without changes
|
|
@@ -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"
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
[11:36:57.309] waygraph pilot: highlight ctx.todos n=3 index=0
|
|
2
|
+
[11:36:57.309] waygraph pilot: highlight ring #user-name tone=planned label="Username"
|
|
3
|
+
[11:36:57.310] waygraph pilot: highlight ring #password tone=info label="Password"
|
|
4
|
+
[11:37:00.472] waygraph pilot: highlight ring #no-such-element-waygraph tone=danger label="Gone"
|
|
5
|
+
[11:37:04.621] waygraph pilot: highlight ring #login-button tone=success label="Login"
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
[11:37:16.027] waygraph pilot: stub.before ctx.title("Signing in · mobile")
|
|
2
|
+
[11:37:16.027] waygraph pilot: stub.before ctx.todos n=6 index=0
|
|
3
|
+
[11:37:16.027] waygraph pilot: stub.before ctx.device(mobile)
|
|
4
|
+
[11:37:16.027] waygraph pilot: stub.before ctx.zoom(1.35)
|
|
5
|
+
[11:37:16.027] waygraph pilot: stub.before ring #user-name tone=info label="Username"
|
|
6
|
+
[11:37:17.582] waygraph pilot: stub.after ctx.todos n=6 index=1
|
|
7
|
+
[11:37:19.508] waygraph pilot: stub.before ring #password tone=planned label="Password"
|
|
8
|
+
[11:37:19.699] waygraph pilot: stub.after ctx.todos n=6 index=2
|
|
9
|
+
[11:37:21.435] waygraph pilot: stub.before ring #login-button tone=warning label="Login"
|
|
10
|
+
[11:37:21.669] waygraph pilot: stub.after ctx.title("Inventory · landscape")
|
|
11
|
+
[11:37:21.669] waygraph pilot: stub.after ctx.todos n=6 index=3
|
|
12
|
+
[11:37:21.669] waygraph pilot: stub.after ctx.device(mobile)
|
|
13
|
+
[11:37:21.669] waygraph pilot: stub.after ring .inventory_list tone=success label="Product shelf"
|
|
14
|
+
[11:37:25.741] waygraph pilot: stub.before ctx.title("Open cart · landscape")
|
|
15
|
+
[11:37:25.741] waygraph pilot: stub.before ctx.todos n=6 index=5
|
|
16
|
+
[11:37:25.741] waygraph pilot: stub.before ctx.device(mobile)
|
|
17
|
+
[11:37:25.741] waygraph pilot: stub.before ctx.zoom(1.4)
|
|
18
|
+
[11:37:25.741] waygraph pilot: stub.before ring .shopping_cart_link tone=planned label="Cart"
|
|
19
|
+
[11:37:26.102] waygraph pilot: stub.after ctx.title("Your cart · desktop")
|
|
20
|
+
[11:37:26.102] waygraph pilot: stub.after ring .cart_item tone=success label="Cart items"
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
[11:37:25.914] waygraph pilot: stub.before ctx.title("Signing in · mobile")
|
|
2
|
+
[11:37:25.915] waygraph pilot: stub.before ctx.todos n=6 index=0
|
|
3
|
+
[11:37:25.915] waygraph pilot: stub.before ctx.device(mobile)
|
|
4
|
+
[11:37:25.915] waygraph pilot: stub.before ctx.zoom(1.35)
|
|
5
|
+
[11:37:25.915] waygraph pilot: stub.before ring #user-name tone=info label="Username"
|
|
6
|
+
[11:37:27.864] waygraph pilot: stub.after ctx.todos n=6 index=1
|
|
7
|
+
[11:37:31.358] waygraph pilot: stub.before ring #password tone=planned label="Password"
|
|
8
|
+
[11:37:31.685] waygraph pilot: stub.after ctx.todos n=6 index=2
|
|
9
|
+
[11:37:35.206] waygraph pilot: stub.before ring #login-button tone=warning label="Login"
|
|
10
|
+
[11:37:35.729] waygraph pilot: stub.after ctx.title("Inventory · landscape")
|
|
11
|
+
[11:37:35.729] waygraph pilot: stub.after ctx.todos n=6 index=3
|
|
12
|
+
[11:37:35.729] waygraph pilot: stub.after ctx.device(mobile)
|
|
13
|
+
[11:37:35.729] waygraph pilot: stub.after ring .inventory_list tone=success label="Product shelf"
|
|
14
|
+
[11:37:43.407] waygraph pilot: stub.before ctx.title("Pick a product · tablet")
|
|
15
|
+
[11:37:43.407] waygraph pilot: stub.before ctx.todos n=6 index=3
|
|
16
|
+
[11:37:43.407] waygraph pilot: stub.before ctx.device(tablet)
|
|
17
|
+
[11:37:43.407] waygraph pilot: stub.before ctx.zoom(1.35)
|
|
18
|
+
[11:37:43.407] 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:37:43.407] waygraph pilot: stub.before ring [data-test="add-to-cart-sauce-labs-backpack"] tone=success label="Add to cart"
|
|
20
|
+
[11:37:44.906] waygraph pilot: stub.after ctx.title("In the cart")
|
|
21
|
+
[11:37:44.906] waygraph pilot: stub.after ctx.todos n=6 index=4
|
|
22
|
+
[11:37:44.906] waygraph pilot: stub.after ring .shopping_cart_badge tone=success label="Cart badge"
|
|
File without changes
|