waygraph 0.10.1 → 0.10.3
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 +2 -2
- package/dist/auto-explore-run.js +7 -1
- package/dist/auto-explore.js +38 -3
- package/dist/cli.js +50 -16
- package/dist/graph.js +6 -1
- package/package.json +1 -1
- package/templates/quickstart/package.json +1 -1
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.2` — CLI less-is-more (`auto` / `demo` / `run` + flags). Page hubs still as in 0.9.0.
|
|
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
|
|
@@ -262,7 +262,7 @@ Deliberately **not yet implemented** (tracked on the project board):
|
|
|
262
262
|
Mermaid) is `waygraph graph [project]` (`--mermaid`). Unattended JSON execution is
|
|
263
263
|
`chain` + `WAYGRAPH_JSON=1`.
|
|
264
264
|
|
|
265
|
-
**Friendly demo / run / auto (0.10.
|
|
265
|
+
**Friendly demo / run / auto (0.10.2 — less is more):**
|
|
266
266
|
|
|
267
267
|
| Want | Command |
|
|
268
268
|
|------|---------|
|
package/dist/auto-explore-run.js
CHANGED
|
@@ -538,8 +538,14 @@ export async function runAutoExplore(projectDir, options = {}) {
|
|
|
538
538
|
if (cli)
|
|
539
539
|
console.error(`waygraph auto: ${menu.flat.length} move(s) available`);
|
|
540
540
|
if (menu.flat.length === 0) {
|
|
541
|
+
const fromHere = graph.edges.filter((e) => e.from === here).map((e) => e.block);
|
|
542
|
+
const missing = [...new Set(fromHere)].filter((b) => !library.byName.has(b));
|
|
541
543
|
console.error(here
|
|
542
|
-
? `waygraph auto: no runnable Blocks on "${here}"
|
|
544
|
+
? `waygraph auto: no runnable Blocks on "${here}"` +
|
|
545
|
+
(fromHere.length
|
|
546
|
+
? ` (graph has: ${[...new Set(fromHere)].join(", ")}${missing.length ? `; not loaded: ${missing.join(", ")}` : ""})`
|
|
547
|
+
: " - nothing on this page matches the graph.") +
|
|
548
|
+
(cli ? "" : " Tip: waygraph auto --cli")
|
|
543
549
|
: "waygraph auto: location unknown - pick nav-login (Start here) if shown.");
|
|
544
550
|
if (cli)
|
|
545
551
|
break;
|
package/dist/auto-explore.js
CHANGED
|
@@ -85,14 +85,18 @@ export async function loadBlockLibrary(projectDir) {
|
|
|
85
85
|
const byName = new Map();
|
|
86
86
|
const navBlocks = [];
|
|
87
87
|
for (const file of walkDir(projectDir, /\.block\.ts$/)) {
|
|
88
|
+
const relFile = relative(projectDir, file);
|
|
88
89
|
let mod;
|
|
89
90
|
try {
|
|
90
91
|
mod = await importModule(file);
|
|
91
92
|
}
|
|
92
|
-
catch {
|
|
93
|
+
catch (err) {
|
|
94
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
95
|
+
if (/second time|playwright/i.test(msg)) {
|
|
96
|
+
console.error(`waygraph auto: skip ${relFile}: ${msg.split("\n")[0]}`);
|
|
97
|
+
}
|
|
93
98
|
continue;
|
|
94
99
|
}
|
|
95
|
-
const relFile = relative(projectDir, file);
|
|
96
100
|
for (const [exportName, exported] of Object.entries(mod)) {
|
|
97
101
|
if (!isBlockLike(exported))
|
|
98
102
|
continue;
|
|
@@ -284,9 +288,40 @@ export async function buildExploreMenu(page, graph, library, here) {
|
|
|
284
288
|
}
|
|
285
289
|
}
|
|
286
290
|
const flat = sections.flatMap((s) => s.edges);
|
|
291
|
+
// Stuck screen: graph knows actions from `here` but none made it into the menu
|
|
292
|
+
// (failed library load, empty instanceOptions, etc.). Surface them so LoginPage
|
|
293
|
+
// never shows a dead "No moves" when submit-login is in the graph.
|
|
294
|
+
if (here !== null && flat.length === 0) {
|
|
295
|
+
const rescue = [];
|
|
296
|
+
const rescued = new Set();
|
|
297
|
+
for (const edge of graph.edges) {
|
|
298
|
+
if (edge.kind !== "action" || edge.from !== here)
|
|
299
|
+
continue;
|
|
300
|
+
if (rescued.has(edge.block))
|
|
301
|
+
continue;
|
|
302
|
+
const entry = library.byName.get(edge.block);
|
|
303
|
+
if (!entry)
|
|
304
|
+
continue;
|
|
305
|
+
if (entry.block.instanceOptions)
|
|
306
|
+
continue; // still need live rows
|
|
307
|
+
rescued.add(edge.block);
|
|
308
|
+
rescue.push(edge);
|
|
309
|
+
}
|
|
310
|
+
if (rescue.length > 0) {
|
|
311
|
+
sections.push({
|
|
312
|
+
title: `Methods from ${here}`,
|
|
313
|
+
edges: rescue.sort((a, b) => a.block.localeCompare(b.block)),
|
|
314
|
+
});
|
|
315
|
+
return { here, sections, flat: sections.flatMap((s) => s.edges) };
|
|
316
|
+
}
|
|
317
|
+
}
|
|
287
318
|
return { here, sections, flat };
|
|
288
319
|
}
|
|
289
320
|
export async function buildExploreContext(projectDir) {
|
|
290
|
-
|
|
321
|
+
// Sequential: parallel import of the same *.block.ts tree raced Playwright's
|
|
322
|
+
// dual-copy guard in some installs and left graph edges without library entries
|
|
323
|
+
// (LoginPage → "No moves").
|
|
324
|
+
const library = await loadBlockLibrary(projectDir);
|
|
325
|
+
const graph = await discoverGraph(projectDir);
|
|
291
326
|
return { graph, library };
|
|
292
327
|
}
|
package/dist/cli.js
CHANGED
|
@@ -2548,24 +2548,41 @@ async function runTryDemo() {
|
|
|
2548
2548
|
"Permanent full example in this package: examples/saucedemo\n" +
|
|
2549
2549
|
"Keep a permanent scaffold in your tree: waygraph init my-app\n");
|
|
2550
2550
|
}
|
|
2551
|
+
const TRY_AUTO_DATA = '{"saucedemo.credentials":{"username":"standard_user","password":"secret_sauce"}}';
|
|
2551
2552
|
/**
|
|
2552
|
-
* `waygraph try auto` -
|
|
2553
|
-
*
|
|
2553
|
+
* `waygraph try auto` / `try auto:cli` - temp Sauce Demo explore.
|
|
2554
|
+
* Default is CLI menu (same as `npm run auto:cli`). Pass `--headed` for the browser panel.
|
|
2555
|
+
*
|
|
2556
|
+
* Runs as a child in the temp project so Block imports share that install's
|
|
2557
|
+
* `@playwright/test`. In-process explore from the outer CLI against a packed
|
|
2558
|
+
* `file:*.tgz` copy double-loads Playwright and silently yields 0 graph edges
|
|
2559
|
+
* ("LoginPage / No moves").
|
|
2554
2560
|
*/
|
|
2555
|
-
async function runTryAuto() {
|
|
2561
|
+
async function runTryAuto(opts = { cli: true }) {
|
|
2556
2562
|
const destDir = await prepareTryQuickstart("waygraph-try-auto");
|
|
2557
2563
|
if (!destDir)
|
|
2558
2564
|
return;
|
|
2559
2565
|
process.env.WAYGRAPH_BASE_URL ??= "https://www.saucedemo.com";
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
"
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
+
const cli = opts.cli !== false;
|
|
2567
|
+
console.log(cli
|
|
2568
|
+
? "waygraph try auto: CLI explore on Sauce Demo (temp dir).\n" +
|
|
2569
|
+
" Creds pre-seeded (saucedemo.credentials).\n" +
|
|
2570
|
+
" Pick [1] submit-login, then inventory Add/Remove / Open details.\n" +
|
|
2571
|
+
" Type q to quit. Headed panel: waygraph try auto --headed\n"
|
|
2572
|
+
: "waygraph try auto: headed explore on Sauce Demo (temp dir).\n" +
|
|
2573
|
+
" Creds pre-seeded. Prefer CLI: waygraph try auto:cli\n" +
|
|
2574
|
+
" Pick submit-login, then inventory menus. Quit from the panel.\n");
|
|
2575
|
+
const bin = join(destDir, "node_modules", ".bin", "waygraph");
|
|
2576
|
+
const args = ["auto"];
|
|
2577
|
+
if (cli)
|
|
2578
|
+
args.push("--cli");
|
|
2579
|
+
args.push("--data", TRY_AUTO_DATA);
|
|
2580
|
+
const code = await runInherited(bin, args, destDir);
|
|
2581
|
+
if (code !== 0)
|
|
2582
|
+
process.exitCode = code;
|
|
2566
2583
|
console.log("\nwaygraph try auto: explorer closed.\n\n" +
|
|
2567
2584
|
`Temp project:\n ${destDir}\n\n` +
|
|
2568
|
-
"Run again
|
|
2585
|
+
"Run again:\n" +
|
|
2569
2586
|
` cd ${destDir} && npm run auto:cli\n` +
|
|
2570
2587
|
` cd ${destDir} && npm run auto\n\n` +
|
|
2571
2588
|
"In-package: examples/saucedemo\n" +
|
|
@@ -2781,6 +2798,9 @@ function parseRunFlags(argv) {
|
|
|
2781
2798
|
else if (a === "--cli") {
|
|
2782
2799
|
out.cli = true;
|
|
2783
2800
|
}
|
|
2801
|
+
else if (a === "--headed") {
|
|
2802
|
+
out.headed = true;
|
|
2803
|
+
}
|
|
2784
2804
|
else if (a === "--mermaid") {
|
|
2785
2805
|
out.mermaid = true;
|
|
2786
2806
|
}
|
|
@@ -2971,10 +2991,12 @@ Primary (less is more):
|
|
|
2971
2991
|
|
|
2972
2992
|
Also:
|
|
2973
2993
|
waygraph list | nav | validate | check | graph | init <name>
|
|
2974
|
-
waygraph try [demo|auto]
|
|
2994
|
+
waygraph try [demo|auto|auto:cli] One-shot saucedemo in a temp dir
|
|
2995
|
+
try auto --headed Browser panel instead of CLI
|
|
2975
2996
|
|
|
2976
2997
|
Examples:
|
|
2977
|
-
waygraph auto
|
|
2998
|
+
waygraph try auto:cli
|
|
2999
|
+
waygraph auto --cli --data '{"saucedemo.credentials":{...}}'
|
|
2978
3000
|
waygraph auto --blocks LoginPage OrderComplete
|
|
2979
3001
|
waygraph demo --blocks shopFlow --auto-next
|
|
2980
3002
|
waygraph demo --blocks cartBulkFlow --data '{"saucedemo.credentials":{...}}' --auto-play-video
|
|
@@ -3170,15 +3192,27 @@ async function main() {
|
|
|
3170
3192
|
case "try": {
|
|
3171
3193
|
const flags = parseRunFlags(args.slice(1));
|
|
3172
3194
|
applyRunFlags(flags);
|
|
3173
|
-
const
|
|
3174
|
-
|
|
3175
|
-
|
|
3195
|
+
const modeRaw = (flags.positionals[0] ?? "demo").toLowerCase();
|
|
3196
|
+
// auto:cli / auto-cli = CLI explore; auto --headed = browser panel; auto = CLI default
|
|
3197
|
+
const mode = modeRaw === "auto:cli" || modeRaw === "auto-cli"
|
|
3198
|
+
? "auto:cli"
|
|
3199
|
+
: modeRaw === "auto"
|
|
3200
|
+
? "auto"
|
|
3201
|
+
: modeRaw;
|
|
3202
|
+
if (mode === "auto" || mode === "auto:cli") {
|
|
3203
|
+
// CLI is the default for try auto (same menus as headed). --headed = panel.
|
|
3204
|
+
const cli = mode === "auto:cli" || flags.cli === true
|
|
3205
|
+
? true
|
|
3206
|
+
: flags.headed === true || flags.nonHeadless === true
|
|
3207
|
+
? false
|
|
3208
|
+
: true;
|
|
3209
|
+
await runTryAuto({ cli });
|
|
3176
3210
|
}
|
|
3177
3211
|
else if (mode === "demo" || mode === "") {
|
|
3178
3212
|
await runTryDemo();
|
|
3179
3213
|
}
|
|
3180
3214
|
else {
|
|
3181
|
-
console.error(`waygraph try: unknown mode "${
|
|
3215
|
+
console.error(`waygraph try: unknown mode "${modeRaw}" - use "demo", "auto", or "auto:cli"`);
|
|
3182
3216
|
process.exitCode = 1;
|
|
3183
3217
|
}
|
|
3184
3218
|
break;
|
package/dist/graph.js
CHANGED
|
@@ -307,7 +307,12 @@ export async function discoverGraph(projectDir) {
|
|
|
307
307
|
try {
|
|
308
308
|
mod = await importModule(file);
|
|
309
309
|
}
|
|
310
|
-
catch {
|
|
310
|
+
catch (err) {
|
|
311
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
312
|
+
// Dual @playwright/test installs fail here - surface instead of empty graph.
|
|
313
|
+
if (/second time|playwright/i.test(msg)) {
|
|
314
|
+
console.error(`waygraph graph: skip ${relFile}: ${msg.split("\n")[0]}`);
|
|
315
|
+
}
|
|
311
316
|
continue;
|
|
312
317
|
}
|
|
313
318
|
const src = readFileSync(file, "utf-8");
|
package/package.json
CHANGED