waygraph 0.10.5 → 0.10.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cli.js +97 -24
- package/package.json +1 -1
- package/templates/quickstart/package.json +1 -1
- package/templates/scaffold/package.json +6 -4
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
A typed graph of reusable Blocks for driving a browser through E2E flows, in place of a
|
|
4
4
|
flat pile of ad hoc helper functions.
|
|
5
5
|
|
|
6
|
-
**Current:** `0.10.
|
|
6
|
+
**Current:** `0.10.6` — `try auto` headed by default; `init` / create-waygraph scaffolds on 0.10 + `.flow.ts` scripts.
|
|
7
7
|
|
|
8
8
|
This repo is the `waygraph` npm package itself. The full live **Sauce Demo** example
|
|
9
9
|
(Page inventory hub, Effect Add/Remove, MemNav Open details, `waygraph auto`) ships
|
package/dist/cli.js
CHANGED
|
@@ -1286,10 +1286,12 @@ function extractVerifyHighlights(block, resultTag) {
|
|
|
1286
1286
|
* __wgNext no-ops once already consumed - but looked live when it wasn't).
|
|
1287
1287
|
* Disables the button and mem-key textareas, and swaps whichever gate
|
|
1288
1288
|
* text was showing (manual button or "Auto-advancing...") to "Running...".
|
|
1289
|
+
* When autoCollapsePanel is set (QA video / autoplay), tuck the stepper
|
|
1290
|
+
* away so ring captions + the app fill the frame - Dan: stepper + auto panels.
|
|
1289
1291
|
*/
|
|
1290
|
-
async function markStepRunning(page) {
|
|
1292
|
+
async function markStepRunning(page, opts?: { autoCollapsePanel?: boolean }) {
|
|
1291
1293
|
await page
|
|
1292
|
-
.evaluate(() => {
|
|
1294
|
+
.evaluate(({ autoCollapsePanel }) => {
|
|
1293
1295
|
const runBtn = document.getElementById("wg-run");
|
|
1294
1296
|
if (runBtn) {
|
|
1295
1297
|
runBtn.disabled = true;
|
|
@@ -1300,7 +1302,15 @@ async function markStepRunning(page) {
|
|
|
1300
1302
|
document.querySelectorAll("#wg-panel textarea[data-key]").forEach((ta) => {
|
|
1301
1303
|
ta.disabled = true;
|
|
1302
1304
|
});
|
|
1303
|
-
|
|
1305
|
+
if (autoCollapsePanel) {
|
|
1306
|
+
const panel = document.getElementById("wg-panel");
|
|
1307
|
+
if (panel) {
|
|
1308
|
+
panel.classList.add("wg-collapsed");
|
|
1309
|
+
const toggle = panel.querySelector("[data-wg-toggle]");
|
|
1310
|
+
if (toggle) toggle.textContent = "Show";
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
}, { autoCollapsePanel: !!opts?.autoCollapsePanel })
|
|
1304
1314
|
.catch(() => {});
|
|
1305
1315
|
}
|
|
1306
1316
|
|
|
@@ -1815,7 +1825,9 @@ async function runStepMode(engine, start, end, context, page, mem, resolved, slo
|
|
|
1815
1825
|
}
|
|
1816
1826
|
}
|
|
1817
1827
|
}
|
|
1818
|
-
|
|
1828
|
+
const recordingVideo = !!process.env.WAYGRAPH_VIDEO;
|
|
1829
|
+
const autoCollapsePanel = recordingVideo || (await currentAutoplay());
|
|
1830
|
+
await markStepRunning(page, { autoCollapsePanel });
|
|
1819
1831
|
// NavBlock click-nav: label the upcoming Locator.click demo cursor as
|
|
1820
1832
|
// "nav: <block>" so pia/demo watchers see cursor+pulse on click nav
|
|
1821
1833
|
// (not only on regular Block clicks).
|
|
@@ -1997,6 +2009,18 @@ async function runChainedFlows(chainFlow, chainFlows, context, mem, page) {
|
|
|
1997
2009
|
}
|
|
1998
2010
|
}
|
|
1999
2011
|
|
|
2012
|
+
/** Parses WAYGRAPH_VIDEO_VIEWPORT / --video-viewport: "1920x1080" or "1920,1080". */
|
|
2013
|
+
function parseVideoViewport(raw: string | undefined): { width: number; height: number } | null {
|
|
2014
|
+
if (!raw?.trim()) return null;
|
|
2015
|
+
const m = raw.trim().match(/^(\d{3,5})[xX,](\d{3,5})$/);
|
|
2016
|
+
if (!m) return null;
|
|
2017
|
+
const width = Number(m[1]);
|
|
2018
|
+
const height = Number(m[2]);
|
|
2019
|
+
if (!Number.isFinite(width) || !Number.isFinite(height)) return null;
|
|
2020
|
+
if (width < 320 || height < 240 || width > 7680 || height > 4320) return null;
|
|
2021
|
+
return { width, height };
|
|
2022
|
+
}
|
|
2023
|
+
|
|
2000
2024
|
async function main() {
|
|
2001
2025
|
const projectDir = process.argv[2];
|
|
2002
2026
|
const spec = process.argv[3];
|
|
@@ -2170,6 +2194,13 @@ async function main() {
|
|
|
2170
2194
|
videoDir = videoEnv === "1" ? join(projectDir, ".waygraph-videos") : videoEnv;
|
|
2171
2195
|
mkdirSync(videoDir, { recursive: true });
|
|
2172
2196
|
}
|
|
2197
|
+
/** Fixed 16:9 capture for --video (demo QA and headless run). Step+video no longer maximizes. */
|
|
2198
|
+
const DEFAULT_VIDEO_VIEWPORT = { width: 1920, height: 1080 };
|
|
2199
|
+
const DEFAULT_RUN_VIDEO_VIEWPORT = { width: 1280, height: 720 };
|
|
2200
|
+
const videoViewportParsed = parseVideoViewport(process.env.WAYGRAPH_VIDEO_VIEWPORT);
|
|
2201
|
+
const fixedVideoViewport = videoDir
|
|
2202
|
+
? (videoViewportParsed ?? (step ? DEFAULT_VIDEO_VIEWPORT : DEFAULT_RUN_VIDEO_VIEWPORT))
|
|
2203
|
+
: null;
|
|
2173
2204
|
const engine = new Engine({ headless: !headed, slowMo });
|
|
2174
2205
|
let result;
|
|
2175
2206
|
// Non-interactive execution (no --step) runs the whole chain as one
|
|
@@ -2200,14 +2231,20 @@ async function main() {
|
|
|
2200
2231
|
const browser = await chromium.launch({
|
|
2201
2232
|
headless: !headed,
|
|
2202
2233
|
slowMo,
|
|
2203
|
-
|
|
2234
|
+
// Maximized only for interactive step mode WITHOUT a fixed video viewport -
|
|
2235
|
+
// recording uses a locked 16:9 viewport so .webm has no gray letterboxing.
|
|
2236
|
+
args: step && !fixedVideoViewport ? ["--start-maximized"] : [],
|
|
2204
2237
|
...(executablePath ? { executablePath } : {}),
|
|
2205
2238
|
});
|
|
2206
|
-
const contextOpts =
|
|
2207
|
-
? { baseURL, viewport:
|
|
2208
|
-
:
|
|
2239
|
+
const contextOpts = fixedVideoViewport
|
|
2240
|
+
? { baseURL, viewport: fixedVideoViewport }
|
|
2241
|
+
: step
|
|
2242
|
+
? { baseURL, viewport: null }
|
|
2243
|
+
: { baseURL, viewport: { width: 1280, height: 720 } };
|
|
2209
2244
|
if (videoDir) {
|
|
2210
|
-
contextOpts.recordVideo =
|
|
2245
|
+
contextOpts.recordVideo = fixedVideoViewport
|
|
2246
|
+
? { dir: videoDir, size: fixedVideoViewport }
|
|
2247
|
+
: { dir: videoDir };
|
|
2211
2248
|
}
|
|
2212
2249
|
const context = await browser.newContext(contextOpts);
|
|
2213
2250
|
let pageForVideo = null;
|
|
@@ -2557,26 +2594,27 @@ async function runTryDemo() {
|
|
|
2557
2594
|
const TRY_AUTO_DATA = '{"saucedemo.credentials":{"username":"standard_user","password":"secret_sauce"}}';
|
|
2558
2595
|
/**
|
|
2559
2596
|
* `waygraph try auto` / `try auto:cli` - temp Sauce Demo explore.
|
|
2560
|
-
* Default is
|
|
2597
|
+
* Default is the **headed** browser panel. Pass `auto:cli` or `--cli` for the
|
|
2598
|
+
* terminal menu (same rows).
|
|
2561
2599
|
*
|
|
2562
2600
|
* Runs as a child in the temp project so Block imports share that install's
|
|
2563
2601
|
* `@playwright/test`. In-process explore from the outer CLI against a packed
|
|
2564
2602
|
* `file:*.tgz` copy double-loads Playwright and silently yields 0 graph edges
|
|
2565
2603
|
* ("LoginPage / No moves").
|
|
2566
2604
|
*/
|
|
2567
|
-
async function runTryAuto(opts = { cli:
|
|
2605
|
+
async function runTryAuto(opts = { cli: false }) {
|
|
2568
2606
|
const destDir = await prepareTryQuickstart("waygraph-try-auto");
|
|
2569
2607
|
if (!destDir)
|
|
2570
2608
|
return;
|
|
2571
2609
|
process.env.WAYGRAPH_BASE_URL ??= "https://www.saucedemo.com";
|
|
2572
|
-
const cli = opts.cli
|
|
2610
|
+
const cli = opts.cli === true;
|
|
2573
2611
|
console.log(cli
|
|
2574
2612
|
? "waygraph try auto: CLI explore on Sauce Demo (temp dir).\n" +
|
|
2575
2613
|
" Creds pre-seeded (saucedemo.credentials).\n" +
|
|
2576
2614
|
" Pick [1] submit-login, then inventory Add/Remove / Open details.\n" +
|
|
2577
|
-
" Type q to quit. Headed panel: waygraph try auto
|
|
2615
|
+
" Type q to quit. Headed panel: waygraph try auto\n"
|
|
2578
2616
|
: "waygraph try auto: headed explore on Sauce Demo (temp dir).\n" +
|
|
2579
|
-
" Creds pre-seeded.
|
|
2617
|
+
" Creds pre-seeded. CLI menu: waygraph try auto:cli\n" +
|
|
2580
2618
|
" Pick submit-login, then inventory menus. Quit from the panel.\n");
|
|
2581
2619
|
const bin = join(destDir, "node_modules", ".bin", "waygraph");
|
|
2582
2620
|
const args = ["auto"];
|
|
@@ -2589,8 +2627,8 @@ async function runTryAuto(opts = { cli: true }) {
|
|
|
2589
2627
|
console.log("\nwaygraph try auto: explorer closed.\n\n" +
|
|
2590
2628
|
`Temp project:\n ${destDir}\n\n` +
|
|
2591
2629
|
"Run again:\n" +
|
|
2592
|
-
` cd ${destDir} && npm run auto
|
|
2593
|
-
` cd ${destDir} && npm run auto\n\n` +
|
|
2630
|
+
` cd ${destDir} && npm run auto\n` +
|
|
2631
|
+
` cd ${destDir} && npm run auto:cli\n\n` +
|
|
2594
2632
|
"In-package: examples/saucedemo\n" +
|
|
2595
2633
|
"Docs: https://deviate-dv8.github.io/waygraph/auto.html\n");
|
|
2596
2634
|
}
|
|
@@ -2692,6 +2730,7 @@ function initCommand(projectName) {
|
|
|
2692
2730
|
process.exit(1);
|
|
2693
2731
|
}
|
|
2694
2732
|
const targetDir = resolve(process.cwd(), projectName);
|
|
2733
|
+
const pkgName = basename(targetDir);
|
|
2695
2734
|
if (existsSync(targetDir)) {
|
|
2696
2735
|
const entries = readdirSync(targetDir);
|
|
2697
2736
|
if (entries.length > 0) {
|
|
@@ -2714,15 +2753,18 @@ function initCommand(projectName) {
|
|
|
2714
2753
|
rmSync(gitignoreSrc);
|
|
2715
2754
|
}
|
|
2716
2755
|
const packageJsonPath = join(targetDir, "package.json");
|
|
2717
|
-
writeFileSync(packageJsonPath, readFileSync(packageJsonPath, "utf-8").replaceAll("__PROJECT_NAME__",
|
|
2718
|
-
console.log(`Scaffolded ${
|
|
2756
|
+
writeFileSync(packageJsonPath, readFileSync(packageJsonPath, "utf-8").replaceAll("__PROJECT_NAME__", pkgName));
|
|
2757
|
+
console.log(`Scaffolded ${pkgName}/`);
|
|
2719
2758
|
console.log("");
|
|
2720
|
-
console.log(` cd ${
|
|
2759
|
+
console.log(` cd ${relative(process.cwd(), targetDir) || pkgName}`);
|
|
2721
2760
|
console.log(" npm install");
|
|
2722
2761
|
console.log(" npx playwright install chromium");
|
|
2723
2762
|
console.log(" npm test");
|
|
2763
|
+
console.log(" waygraph list # .flow.ts → export map");
|
|
2724
2764
|
console.log(" waygraph check # nav hygiene + orphan Blocks");
|
|
2725
|
-
console.log(" waygraph auto # interactive explore (
|
|
2765
|
+
console.log(" waygraph auto # interactive explore (headed panel)");
|
|
2766
|
+
console.log(" waygraph auto --cli # same menus in the terminal");
|
|
2767
|
+
console.log(" waygraph demo src/flows/example.flow.ts");
|
|
2726
2768
|
console.log(" waygraph graph # static state graph JSON");
|
|
2727
2769
|
}
|
|
2728
2770
|
async function checkCommand(projectDir) {
|
|
@@ -2843,6 +2885,11 @@ function parseRunFlags(argv) {
|
|
|
2843
2885
|
}
|
|
2844
2886
|
}
|
|
2845
2887
|
}
|
|
2888
|
+
else if (a === "--video-viewport" || a.startsWith("--video-viewport=")) {
|
|
2889
|
+
const t = takeFlagValue(argv, i, a, "--video-viewport");
|
|
2890
|
+
out.videoViewport = t.value;
|
|
2891
|
+
i = t.nextI;
|
|
2892
|
+
}
|
|
2846
2893
|
else if (a === "--blocks" || a.startsWith("--blocks=")) {
|
|
2847
2894
|
if (a.startsWith("--blocks=")) {
|
|
2848
2895
|
out.blocks = a.slice("--blocks=".length);
|
|
@@ -2869,6 +2916,21 @@ function parseRunFlags(argv) {
|
|
|
2869
2916
|
}
|
|
2870
2917
|
return out;
|
|
2871
2918
|
}
|
|
2919
|
+
/** Parses WAYGRAPH_VIDEO_VIEWPORT / --video-viewport: "1920x1080" or "1920,1080". */
|
|
2920
|
+
function parseVideoViewportFlag(raw) {
|
|
2921
|
+
if (!raw?.trim())
|
|
2922
|
+
return null;
|
|
2923
|
+
const m = raw.trim().match(/^(\d{3,5})[xX,](\d{3,5})$/);
|
|
2924
|
+
if (!m)
|
|
2925
|
+
return null;
|
|
2926
|
+
const width = Number(m[1]);
|
|
2927
|
+
const height = Number(m[2]);
|
|
2928
|
+
if (!Number.isFinite(width) || !Number.isFinite(height))
|
|
2929
|
+
return null;
|
|
2930
|
+
if (width < 320 || height < 240 || width > 7680 || height > 4320)
|
|
2931
|
+
return null;
|
|
2932
|
+
return { width, height };
|
|
2933
|
+
}
|
|
2872
2934
|
/** Writes flag values into process.env so the chain child inherits them. Flags beat prior env. */
|
|
2873
2935
|
function applyRunFlags(flags, opts) {
|
|
2874
2936
|
if (flags.autoPlayVideo) {
|
|
@@ -2908,6 +2970,13 @@ function applyRunFlags(flags, opts) {
|
|
|
2908
2970
|
if (flags.video !== undefined) {
|
|
2909
2971
|
process.env.WAYGRAPH_VIDEO = flags.video || "1";
|
|
2910
2972
|
}
|
|
2973
|
+
if (flags.videoViewport !== undefined) {
|
|
2974
|
+
if (!parseVideoViewportFlag(flags.videoViewport)) {
|
|
2975
|
+
console.error('waygraph: --video-viewport must look like "1920x1080"');
|
|
2976
|
+
process.exit(1);
|
|
2977
|
+
}
|
|
2978
|
+
process.env.WAYGRAPH_VIDEO_VIEWPORT = flags.videoViewport;
|
|
2979
|
+
}
|
|
2911
2980
|
if (flags.data !== undefined) {
|
|
2912
2981
|
process.env.WAYGRAPH_DATA = flags.data;
|
|
2913
2982
|
}
|
|
@@ -3067,22 +3136,27 @@ Primary (less is more):
|
|
|
3067
3136
|
--data '{...}' Mem seed JSON (or inline flow({...}))
|
|
3068
3137
|
--auto-next Auto-advance steps (alias: --autoplay)
|
|
3069
3138
|
--auto-play-video QA: --auto-next + --video (+ step)
|
|
3139
|
+
--video-viewport WxH Recording size (default demo: 1920x1080)
|
|
3070
3140
|
--title / --base-url
|
|
3071
3141
|
waygraph run [--blocks <flow|file|spec>] Execute (no overlay unless --step)
|
|
3072
3142
|
--data '{...}'
|
|
3073
3143
|
--non-headless Show browser
|
|
3074
3144
|
--video [dir] Record .webm
|
|
3145
|
+
--video-viewport WxH Recording size (default run: 1280x720)
|
|
3075
3146
|
|
|
3076
3147
|
Also:
|
|
3077
3148
|
waygraph list | nav | validate | check | graph | init <name>
|
|
3078
3149
|
waygraph try [demo|auto|auto:cli] One-shot saucedemo in a temp dir
|
|
3079
|
-
try auto
|
|
3150
|
+
try auto Headed browser panel (default)
|
|
3151
|
+
try auto:cli / --cli Terminal menu instead
|
|
3152
|
+
try auto --headed Same as try auto (compat)
|
|
3080
3153
|
|
|
3081
3154
|
Examples:
|
|
3082
3155
|
waygraph list # file → export map
|
|
3083
3156
|
waygraph run src/flows/shop.flow.ts --data '{...}'
|
|
3084
3157
|
waygraph run --blocks shopFlow --non-headless --video
|
|
3085
3158
|
waygraph demo --blocks src/flows/cart-bulk.flow.ts --auto-next
|
|
3159
|
+
waygraph try auto
|
|
3086
3160
|
waygraph try auto:cli
|
|
3087
3161
|
waygraph auto src/flows/shop.flow.ts --data '{...}' # run by file (same as run)
|
|
3088
3162
|
waygraph auto --cli --data '{"saucedemo.credentials":{...}}'
|
|
@@ -3310,19 +3384,18 @@ async function main() {
|
|
|
3310
3384
|
const flags = parseRunFlags(args.slice(1));
|
|
3311
3385
|
applyRunFlags(flags);
|
|
3312
3386
|
const modeRaw = (flags.positionals[0] ?? "demo").toLowerCase();
|
|
3313
|
-
// auto:cli /
|
|
3387
|
+
// auto:cli / --cli = CLI; bare try auto = headed panel
|
|
3314
3388
|
const mode = modeRaw === "auto:cli" || modeRaw === "auto-cli"
|
|
3315
3389
|
? "auto:cli"
|
|
3316
3390
|
: modeRaw === "auto"
|
|
3317
3391
|
? "auto"
|
|
3318
3392
|
: modeRaw;
|
|
3319
3393
|
if (mode === "auto" || mode === "auto:cli") {
|
|
3320
|
-
// CLI is the default for try auto (same menus as headed). --headed = panel.
|
|
3321
3394
|
const cli = mode === "auto:cli" || flags.cli === true
|
|
3322
3395
|
? true
|
|
3323
3396
|
: flags.headed === true || flags.nonHeadless === true
|
|
3324
3397
|
? false
|
|
3325
|
-
:
|
|
3398
|
+
: false; // try auto default = headed
|
|
3326
3399
|
await runTryAuto({ cli });
|
|
3327
3400
|
}
|
|
3328
3401
|
else if (mode === "demo" || mode === "") {
|
package/package.json
CHANGED
|
@@ -6,17 +6,19 @@
|
|
|
6
6
|
"scripts": {
|
|
7
7
|
"typecheck": "tsc --noEmit",
|
|
8
8
|
"test": "playwright test",
|
|
9
|
-
"
|
|
9
|
+
"list": "waygraph list",
|
|
10
10
|
"check": "waygraph check",
|
|
11
11
|
"auto": "waygraph auto",
|
|
12
|
-
"
|
|
13
|
-
"demo": "waygraph demo
|
|
12
|
+
"auto:cli": "waygraph auto --cli",
|
|
13
|
+
"demo": "waygraph demo src/flows/example.flow.ts",
|
|
14
|
+
"run": "waygraph run src/flows/example.flow.ts",
|
|
15
|
+
"graph": "waygraph graph"
|
|
14
16
|
},
|
|
15
17
|
"waygraph": {
|
|
16
18
|
"baseUrl": "https://example.com"
|
|
17
19
|
},
|
|
18
20
|
"dependencies": {
|
|
19
|
-
"waygraph": "^0.
|
|
21
|
+
"waygraph": "^0.10.6"
|
|
20
22
|
},
|
|
21
23
|
"devDependencies": {
|
|
22
24
|
"@playwright/test": "^1.55.0",
|