waygraph 0.15.53 → 0.16.0
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 +8 -3
- package/bin/waygraph +2 -2
- package/dist/analysis/check.d.ts +38 -0
- package/dist/analysis/check.js +87 -0
- package/dist/analysis/coverage-gap.d.ts +1 -1
- package/dist/analysis/coverage-gap.js +14 -37
- package/dist/analysis/flow-source.d.ts +9 -0
- package/dist/analysis/flow-source.js +25 -0
- package/dist/analysis/graph.d.ts +13 -14
- package/dist/analysis/graph.js +48 -371
- package/dist/analysis/map-check.js +4 -39
- package/dist/analysis/practices-check.d.ts +1 -1
- package/dist/analysis/practices-check.js +24 -45
- package/dist/cli/args.d.ts +23 -0
- package/dist/cli/args.js +20 -0
- package/dist/{cli.d.ts → cli/cli.d.ts} +0 -1
- package/dist/{cli.js → cli/cli.js} +10 -9
- package/dist/{commands → cli/commands}/agent-dive-scaffold.js +35 -64
- package/dist/cli/commands/agent-dive.js +42 -0
- package/dist/{commands → cli/commands}/check.d.ts +0 -1
- package/dist/cli/commands/check.js +104 -0
- package/dist/cli/commands/codemod-checkpoints.d.ts +18 -0
- package/dist/cli/commands/codemod-checkpoints.js +186 -0
- package/dist/cli/commands/codemod-flows.d.ts +18 -0
- package/dist/cli/commands/codemod-flows.js +284 -0
- package/dist/cli/commands/codemod-stubs.d.ts +10 -0
- package/dist/cli/commands/codemod-stubs.js +187 -0
- package/dist/{commands → cli/commands}/extensions.js +5 -4
- package/dist/{commands → cli/commands}/init.js +1 -2
- package/dist/{commands → cli/commands}/list.js +9 -7
- package/dist/cli/commands/manifest.d.ts +2 -0
- package/dist/cli/commands/manifest.js +20 -0
- package/dist/cli/commands/map.js +57 -0
- package/dist/{commands → cli/commands}/run.d.ts +0 -1
- package/dist/cli/commands/run.js +64 -0
- package/dist/{commands → cli/commands}/session.js +61 -88
- package/dist/{commands → cli/commands}/test.js +11 -14
- package/dist/cli/commands/traverse.js +105 -0
- package/dist/{commands → cli/commands}/try.js +29 -25
- package/dist/{commands → cli/commands}/upgrade.js +40 -4
- package/dist/cli/flags.d.ts +193 -16
- package/dist/cli/flags.js +179 -234
- package/dist/cli/run-chain.d.ts +1 -0
- package/dist/cli/run-chain.js +42 -7
- package/dist/cli/usage.d.ts +1 -1
- package/dist/cli/usage.js +21 -53
- package/dist/cli/util.d.ts +2 -2
- package/dist/cli/util.js +2 -3
- package/dist/{highlights → demo/narration}/css.d.ts +1 -1
- package/dist/{highlights → demo/narration}/css.js +2 -3
- package/dist/{highlights → demo/narration}/demo-pace.d.ts +7 -11
- package/dist/{highlights → demo/narration}/demo-pace.js +9 -11
- package/dist/{highlights → demo/narration}/device.d.ts +4 -2
- package/dist/{highlights → demo/narration}/device.js +3 -1
- package/dist/demo/narration/merge.d.ts +8 -0
- package/dist/demo/narration/merge.js +71 -0
- package/dist/{highlights/run-phase.d.ts → demo/narration/narration.d.ts} +10 -14
- package/dist/{highlights/run-phase.js → demo/narration/narration.js} +25 -94
- package/dist/{highlights → demo/narration}/shorthand.d.ts +1 -1
- package/dist/demo/narration/stub-ctx.d.ts +8 -0
- package/dist/demo/narration/stub-ctx.js +164 -0
- package/dist/{highlights → demo/narration}/style.d.ts +1 -7
- package/dist/{highlights → demo/narration}/style.js +1 -41
- package/dist/{highlights → demo/narration}/todo-dock.d.ts +3 -3
- package/dist/{highlights → demo/narration}/todo-dock.js +13 -30
- package/dist/demo/overlay/auto-chrome.d.ts +7 -0
- package/dist/demo/overlay/auto-chrome.js +97 -0
- package/dist/{session/overlay-beacon.d.ts → demo/overlay/beacon.d.ts} +7 -0
- package/dist/{session/overlay-beacon.js → demo/overlay/beacon.js} +5 -0
- package/dist/demo/overlay/cursor.d.ts +12 -0
- package/dist/demo/overlay/cursor.js +142 -0
- package/dist/demo/overlay/device-stage.d.ts +13 -0
- package/dist/demo/overlay/device-stage.js +396 -0
- package/dist/demo/overlay/inpage/banner.d.ts +1 -0
- package/dist/demo/overlay/inpage/banner.js +160 -0
- package/dist/demo/overlay/inpage/caption.d.ts +2 -0
- package/dist/demo/overlay/inpage/caption.js +24 -0
- package/dist/demo/overlay/inpage/core.d.ts +1 -0
- package/dist/demo/overlay/inpage/core.js +345 -0
- package/dist/demo/overlay/inpage/device-chip.d.ts +1 -0
- package/dist/demo/overlay/inpage/device-chip.js +191 -0
- package/dist/demo/overlay/inpage/network.d.ts +9 -0
- package/dist/demo/overlay/inpage/network.js +200 -0
- package/dist/demo/overlay/inpage/panel-chrome.d.ts +1 -0
- package/dist/demo/overlay/inpage/panel-chrome.js +203 -0
- package/dist/demo/overlay/inpage/stamp.d.ts +1 -0
- package/dist/demo/overlay/inpage/stamp.js +46 -0
- package/dist/demo/overlay/inpage/swipe-zoom.d.ts +1 -0
- package/dist/demo/overlay/inpage/swipe-zoom.js +220 -0
- package/dist/demo/overlay/inpage/todos.d.ts +1 -0
- package/dist/demo/overlay/inpage/todos.js +294 -0
- package/dist/demo/overlay/locator-theater.d.ts +25 -0
- package/dist/demo/overlay/locator-theater.js +76 -0
- package/dist/demo/overlay/network-capture.d.ts +22 -0
- package/dist/demo/overlay/network-capture.js +127 -0
- package/dist/demo/overlay/overlay-css.d.ts +3 -0
- package/dist/demo/overlay/overlay-css.js +369 -0
- package/dist/demo/overlay/overlay-stage.d.ts +23 -0
- package/dist/demo/overlay/overlay-stage.js +106 -0
- package/dist/demo/overlay/overlay.d.ts +10 -0
- package/dist/demo/overlay/overlay.js +89 -0
- package/dist/{pilot-overlay/overlay-fixtures.d.ts → demo/overlay/phase-fixtures.d.ts} +2 -2
- package/dist/{pilot-overlay/overlay-fixtures.js → demo/overlay/phase-fixtures.js} +2 -2
- package/dist/{pilot-overlay/action-ring.js → demo/overlay/pilot/actions.js} +2 -1
- package/dist/{pilot-overlay → demo/overlay/pilot}/fixtures.d.ts +6 -5
- package/dist/{pilot-overlay → demo/overlay/pilot}/fixtures.js +19 -18
- package/dist/{pilot-overlay → demo/overlay/pilot}/shell.d.ts +2 -2
- package/dist/{pilot-overlay → demo/overlay/pilot}/shell.js +13 -22
- package/dist/demo/overlay/reattach.d.ts +7 -0
- package/dist/demo/overlay/reattach.js +23 -0
- package/dist/demo/overlay/rings.d.ts +33 -0
- package/dist/demo/overlay/rings.js +448 -0
- package/dist/{ui → demo/overlay/ui}/components/ring.js +2 -2
- package/dist/{ui → demo/overlay/ui}/overlay.css +4 -4
- package/dist/{ui → demo/overlay/ui}/shadow.d.ts +1 -1
- package/dist/{ui → demo/overlay/ui}/shadow.js +39 -2
- package/dist/demo/stepper/after.d.ts +3 -0
- package/dist/demo/stepper/after.js +113 -0
- package/dist/demo/stepper/banner-log.d.ts +37 -0
- package/dist/demo/stepper/banner-log.js +63 -0
- package/dist/demo/stepper/before.d.ts +4 -0
- package/dist/demo/stepper/before.js +110 -0
- package/dist/demo/stepper/demo-log.d.ts +31 -0
- package/dist/demo/stepper/demo-log.js +309 -0
- package/dist/demo/stepper/gate.d.ts +11 -0
- package/dist/demo/stepper/gate.js +78 -0
- package/dist/demo/stepper/interaction-patch.d.ts +3 -0
- package/dist/demo/stepper/interaction-patch.js +323 -0
- package/dist/demo/stepper/pacing.d.ts +21 -0
- package/dist/demo/stepper/pacing.js +23 -0
- package/dist/demo/stepper/slides.d.ts +11 -0
- package/dist/demo/stepper/slides.js +233 -0
- package/dist/demo/stepper/step-panels.d.ts +21 -0
- package/dist/demo/stepper/step-panels.js +589 -0
- package/dist/demo/stepper/stepper.d.ts +24 -0
- package/dist/demo/stepper/stepper.js +122 -0
- package/dist/demo/stepper/teardown.d.ts +48 -0
- package/dist/demo/stepper/teardown.js +179 -0
- package/dist/demo/stepper/todo-advance.d.ts +14 -0
- package/dist/demo/stepper/todo-advance.js +110 -0
- package/dist/demo/stepper/view.d.ts +68 -0
- package/dist/demo/stepper/view.js +31 -0
- package/dist/demo/types.d.ts +17 -0
- package/dist/demo/verbose-log.js +15 -0
- package/dist/{types.d.ts → engine/block/block.d.ts} +106 -91
- package/dist/{core → engine/block}/block.js +10 -53
- package/dist/{core → engine/block}/compose.d.ts +10 -7
- package/dist/{core → engine/block}/compose.js +1 -1
- package/dist/{core/blocks → engine/block/kinds}/api.d.ts +17 -12
- package/dist/{core/blocks → engine/block/kinds}/api.js +26 -18
- package/dist/{core/blocks → engine/block/kinds}/effect.d.ts +13 -18
- package/dist/engine/block/kinds/effect.js +17 -0
- package/dist/{core/blocks → engine/block/kinds}/method.d.ts +19 -29
- package/dist/{core/blocks → engine/block/kinds}/method.js +7 -21
- package/dist/{core/blocks → engine/block/kinds}/nav.d.ts +22 -31
- package/dist/{core/blocks → engine/block/kinds}/nav.js +6 -12
- package/dist/{core/blocks → engine/block/kinds}/page.d.ts +15 -20
- package/dist/{core/blocks → engine/block/kinds}/page.js +5 -7
- package/dist/engine/checkpoint/checkpoint.d.ts +22 -0
- package/dist/engine/checkpoint/checkpoint.js +8 -0
- package/dist/engine/checkpoint/route.d.ts +28 -0
- package/dist/engine/checkpoint/route.js +28 -0
- package/dist/{core → engine}/config.d.ts +7 -2
- package/dist/engine/config.js +6 -0
- package/dist/engine/engine.d.ts +45 -0
- package/dist/{core → engine}/engine.js +6 -10
- package/dist/engine/env.d.ts +59 -0
- package/dist/engine/env.js +83 -0
- package/dist/{errors.d.ts → engine/errors.d.ts} +23 -22
- package/dist/{errors.js → engine/errors.js} +22 -22
- package/dist/{core → engine/flow}/branch-regression.d.ts +8 -7
- package/dist/{core → engine/flow}/branch-regression.js +4 -3
- package/dist/engine/flow/flow.d.ts +162 -0
- package/dist/engine/flow/flow.js +244 -0
- package/dist/{core → engine/flow}/map-builder.d.ts +42 -40
- package/dist/{core → engine/flow}/map-builder.js +46 -48
- package/dist/{core → engine}/locate.d.ts +1 -1
- package/dist/{core → engine}/locate.js +1 -2
- package/dist/{mem-stub.d.ts → engine/mem/mem-stub.d.ts} +9 -8
- package/dist/{mem-stub.js → engine/mem/mem-stub.js} +2 -2
- package/dist/{mem-page.d.ts → engine/mem/mem.d.ts} +1 -1
- package/dist/{mem-page.js → engine/mem/mem.js} +2 -1
- package/dist/engine/page-gone.d.ts +5 -0
- package/dist/engine/page-gone.js +20 -0
- package/dist/engine/run/connect.d.ts +28 -0
- package/dist/{types.js → engine/run/connect.js} +11 -10
- package/dist/engine/run/events.d.ts +67 -0
- package/dist/engine/run/events.js +90 -0
- package/dist/engine/run/hooks.d.ts +16 -0
- package/dist/engine/run/hooks.js +8 -0
- package/dist/engine/run/launch.d.ts +13 -0
- package/dist/engine/run/launch.js +27 -0
- package/dist/{core/run-graph.d.ts → engine/run/run.d.ts} +9 -11
- package/dist/{core/run-graph.js → engine/run/run.js} +22 -11
- package/dist/engine/stub/pace.d.ts +12 -0
- package/dist/engine/stub/pace.js +2 -0
- package/dist/engine/stub/ring.d.ts +130 -0
- package/dist/engine/stub/ring.js +41 -0
- package/dist/engine/stub/stub.d.ts +268 -0
- package/dist/engine/stub/stub.js +1 -0
- package/dist/engine/stub/todos.d.ts +104 -0
- package/dist/engine/stub/todos.js +2 -0
- package/dist/engine/stub/viewport.d.ts +26 -0
- package/dist/engine/stub/viewport.js +2 -0
- package/dist/{trait.d.ts → engine/trait/trait.d.ts} +1 -1
- package/dist/index.d.ts +84 -36
- package/dist/index.js +44 -19
- package/dist/{session/auto-explore-run.d.ts → live/auto/auto.d.ts} +10 -16
- package/dist/{session/auto-explore-run.js → live/auto/auto.js} +164 -248
- package/dist/{session/auto-explore.d.ts → live/auto/explore.d.ts} +4 -14
- package/dist/{session/auto-explore.js → live/auto/explore.js} +21 -127
- package/dist/{auto-session/session.d.ts → live/auto-session/auto-session.d.ts} +1 -1
- package/dist/{auto-session/session.js → live/auto-session/auto-session.js} +27 -24
- package/dist/{auto-session → live/auto-session}/helpers.d.ts +16 -5
- package/dist/{auto-session → live/auto-session}/helpers.js +1 -1
- package/dist/{session/auto-session-ipc.d.ts → live/auto-session/ipc.d.ts} +7 -5
- package/dist/{session/auto-session-ipc.js → live/auto-session/ipc.js} +31 -16
- package/dist/{session/browser.d.ts → live/auto-session/start.d.ts} +1 -2
- package/dist/{session/browser.js → live/auto-session/start.js} +2 -3
- package/dist/{pilot-overlay → live/pilot}/panel.d.ts +1 -1
- package/dist/{pilot-overlay → live/pilot}/panel.js +23 -31
- package/dist/{session → live/pilot}/pilot.d.ts +4 -3
- package/dist/{session → live/pilot}/pilot.js +4 -4
- package/dist/{traverse → live/traverse}/coverage.d.ts +4 -0
- package/dist/{traverse → live/traverse}/coverage.js +3 -0
- package/dist/{traverse → live/traverse}/lease.d.ts +1 -0
- package/dist/{traverse → live/traverse}/lease.js +1 -0
- package/dist/{traverse/run.d.ts → live/traverse/traverse.d.ts} +4 -1
- package/dist/{traverse/run.js → live/traverse/traverse.js} +26 -43
- package/dist/manifest/manifest.d.ts +52 -0
- package/dist/manifest/manifest.js +93 -0
- package/dist/manifest/map-imports.d.ts +7 -0
- package/dist/manifest/map-imports.js +22 -0
- package/dist/manifest/maps.d.ts +33 -0
- package/dist/manifest/maps.js +62 -0
- package/dist/manifest/pack.d.ts +21 -0
- package/dist/manifest/pack.js +109 -0
- package/dist/manifest/project.d.ts +60 -0
- package/dist/manifest/project.js +101 -0
- package/dist/{session/block-inject.js → manifest/roots.js} +1 -18
- package/dist/manifest/scan.d.ts +19 -0
- package/dist/manifest/scan.js +57 -0
- package/dist/{blocks-select.d.ts → manifest/select.d.ts} +3 -0
- package/dist/{blocks-select.js → manifest/select.js} +2 -0
- package/dist/manifest/source.d.ts +23 -0
- package/dist/manifest/source.js +86 -0
- package/dist/runner/mode.d.ts +71 -0
- package/dist/runner/mode.js +1 -0
- package/dist/runner/modes/branches.d.ts +5 -0
- package/dist/runner/modes/branches.js +37 -0
- package/dist/runner/modes/demo.d.ts +3 -0
- package/dist/runner/modes/demo.js +13 -0
- package/dist/runner/modes/report.d.ts +2 -0
- package/dist/runner/modes/report.js +54 -0
- package/dist/runner/modes/run.d.ts +2 -0
- package/dist/runner/modes/run.js +3 -0
- package/dist/runner/options.d.ts +31 -0
- package/dist/runner/options.js +42 -0
- package/dist/runner/plan/find.d.ts +18 -0
- package/dist/runner/plan/find.js +65 -0
- package/dist/runner/plan/plan.d.ts +11 -0
- package/dist/runner/plan/plan.js +97 -0
- package/dist/runner/plan/seed-mem.d.ts +12 -0
- package/dist/runner/plan/seed-mem.js +98 -0
- package/dist/runner/plan/spec.d.ts +5 -0
- package/dist/runner/plan/spec.js +17 -0
- package/dist/runner/play-steps.d.ts +2 -0
- package/dist/runner/play-steps.js +59 -0
- package/dist/runner/runner.d.ts +4 -0
- package/dist/runner/runner.js +64 -0
- package/dist/runner/session.d.ts +9 -0
- package/dist/runner/session.js +87 -0
- package/dist/{browser.js → runtime/browser.js} +4 -2
- package/dist/{env-file.js → runtime/env-file.js} +7 -12
- package/dist/{extensions.d.ts → runtime/extensions.d.ts} +2 -5
- package/dist/{extensions.js → runtime/extensions.js} +3 -1
- package/dist/runtime/full-launch.d.ts +1 -0
- package/dist/runtime/full-launch.js +34 -0
- package/dist/runtime/global-flag.d.ts +5 -0
- package/dist/runtime/global-flag.js +18 -0
- package/dist/{playwright-config.d.ts → runtime/playwright-config.d.ts} +1 -1
- package/dist/{playwright.config.js → runtime/playwright.config.js} +3 -2
- package/dist/runtime/run-log.d.ts +2 -0
- package/dist/runtime/run-log.js +17 -0
- package/dist/{video-dir.js → runtime/video-dir.js} +3 -2
- package/dist/{config.d.ts → runtime/waygraph-config.d.ts} +8 -9
- package/dist/{config.js → runtime/waygraph-config.js} +21 -51
- package/dist/{webserver.js → runtime/webserver.js} +5 -30
- package/examples/routed-demo/config/waygraph.config.ts +20 -0
- package/examples/routed-demo/package.json +1 -4
- package/examples/routed-demo/scripts/fixture-server.mjs +1 -1
- package/examples/routed-demo/src/flows/routed-demo-map.flow.ts +2 -4
- package/examples/routed-demo/src/flows/routed-demo.flow.ts +2 -3
- package/examples/routed-demo/src/map/(app_base)/dashboard/_methods/click-widget.block.ts +5 -4
- package/examples/routed-demo/src/map/(app_base)/dashboard/_nav.block.ts +3 -3
- package/examples/routed-demo/src/map/(app_base)/dashboard/_page.block.ts +3 -3
- package/examples/routed-demo/src/map/(external)/docs/_nav.block.ts +3 -3
- package/examples/routed-demo/src/map/(external)/docs/_page.block.ts +3 -3
- package/examples/routed-demo/src/states/routed-demo.states.ts +5 -3
- package/examples/routed-demo/tests/routed-demo.spec.ts +4 -4
- package/examples/routed-demo/tsconfig.json +1 -1
- package/examples/saucedemo/README.md +11 -12
- package/examples/saucedemo/config/waygraph.config.ts +17 -0
- package/examples/saucedemo/docs/CONVENTION.md +5 -7
- package/examples/saucedemo/docs/HELPERS.md +12 -12
- package/examples/saucedemo/package-lock.json +10 -3
- package/examples/saucedemo/package.json +12 -29
- package/examples/saucedemo/src/blocks/SITE-MAP.md +0 -1
- package/examples/saucedemo/src/blocks/saucedemo-web/NAV.md +1 -5
- package/examples/saucedemo/src/blocks/saucedemo-web/cart/nav-cart.block.ts +3 -52
- package/examples/saucedemo/src/blocks/saucedemo-web/cart/nav-checkout-info.block.ts +3 -3
- package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/fill-first-name.method.block.ts +5 -4
- package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/fill-last-name.method.block.ts +5 -4
- package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/fill-postal-code.method.block.ts +5 -4
- package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/submit-checkout-info.method.block.ts +5 -4
- package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.ts +21 -27
- package/examples/saucedemo/src/blocks/saucedemo-web/inventory/inventory.page.block.ts +3 -9
- package/examples/saucedemo/src/blocks/saucedemo-web/inventory/methods/add-all-to-cart.method.block.ts +4 -6
- package/examples/saucedemo/src/blocks/saucedemo-web/inventory/methods/add-to-cart.effect.block.ts +10 -76
- package/examples/saucedemo/src/blocks/saucedemo-web/inventory/methods/remove-all-from-cart.method.block.ts +4 -6
- package/examples/saucedemo/src/blocks/saucedemo-web/inventory/methods/remove-from-cart.effect.block.ts +4 -3
- package/examples/saucedemo/src/blocks/saucedemo-web/inventory/nav-item-detail.block.ts +3 -3
- package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/nav-back-to-inventory.block.ts +3 -3
- package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/nav-back-to-products.block.ts +3 -3
- package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/nav-continue-shopping.block.ts +3 -3
- package/examples/saucedemo/src/blocks/saucedemo-web/methods/fill-password.method.block.ts +5 -29
- package/examples/saucedemo/src/blocks/saucedemo-web/methods/fill-username.method.block.ts +5 -48
- package/examples/saucedemo/src/blocks/saucedemo-web/methods/submit-login.method.block.ts +13 -77
- package/examples/saucedemo/src/blocks/saucedemo-web/methods/submit-logout.method.block.ts +5 -4
- package/examples/saucedemo/src/blocks/saucedemo-web/nav-login.block.ts +3 -3
- package/examples/saucedemo/src/flows/api-demo.flow.ts +26 -18
- package/examples/saucedemo/src/flows/cart-bulk.flow.ts +19 -14
- package/examples/saucedemo/src/flows/cart-continue.flow.ts +10 -8
- package/examples/saucedemo/src/flows/cart-mem.flow.ts +7 -7
- package/examples/saucedemo/src/flows/catalog-logout.flow.ts +13 -8
- package/examples/saucedemo/src/flows/checkout-then-browse-again.flow.ts +26 -48
- package/examples/saucedemo/src/flows/checkout.flow.ts +70 -86
- package/examples/saucedemo/src/flows/device-showcase.flow.ts +24 -25
- package/examples/saucedemo/src/flows/login.flow.ts +11 -18
- package/examples/saucedemo/src/flows/mem-stub-demo.flow.ts +9 -20
- package/examples/saucedemo/src/flows/shop.flow.ts +15 -20
- package/examples/saucedemo/src/flows/smoke.flow.ts +12 -27
- package/examples/saucedemo/src/flows/stub-on-error.flow.ts +24 -43
- package/examples/saucedemo/src/flows/viewer-blocked.flow.ts +26 -34
- package/examples/saucedemo/src/states/checkout.mem-stubs.ts +11 -0
- package/examples/saucedemo/src/states/checkout.states.ts +21 -11
- package/examples/saucedemo/src/stubs/device-showcase.ts +191 -0
- package/examples/saucedemo/src/stubs/login.ts +37 -0
- package/examples/saucedemo/tests/auto-graph.spec.ts +4 -12
- package/examples/saucedemo/tests/chain-flow-episodes.spec.ts +7 -9
- package/examples/saucedemo/tests/submit-login-branch.spec.ts +18 -5
- package/package.json +12 -7
- package/templates/agents/waygraph-planner.agent.md +2 -2
- package/templates/quickstart/README.md +4 -7
- package/templates/quickstart/config/waygraph.config.ts +17 -0
- package/templates/quickstart/docs/CONVENTION.md +5 -6
- package/templates/quickstart/docs/HELPERS.md +11 -9
- package/templates/quickstart/package.json +14 -17
- package/templates/quickstart/src/blocks/SITE-MAP.md +13 -3
- package/templates/quickstart/src/blocks/saucedemo-web/NAV.md +1 -5
- package/templates/quickstart/src/blocks/saucedemo-web/cart/nav-cart.block.ts +3 -52
- package/templates/quickstart/src/blocks/saucedemo-web/cart/nav-checkout-info.block.ts +3 -3
- package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/fill-first-name.method.block.ts +5 -4
- package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/fill-last-name.method.block.ts +5 -4
- package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/fill-postal-code.method.block.ts +5 -4
- package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/submit-checkout-info.method.block.ts +5 -4
- package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.ts +21 -27
- package/templates/quickstart/src/blocks/saucedemo-web/inventory/inventory.page.block.ts +3 -9
- package/templates/quickstart/src/blocks/saucedemo-web/inventory/methods/add-all-to-cart.method.block.ts +4 -6
- package/templates/quickstart/src/blocks/saucedemo-web/inventory/methods/add-to-cart.effect.block.ts +10 -76
- package/templates/quickstart/src/blocks/saucedemo-web/inventory/methods/remove-all-from-cart.method.block.ts +4 -6
- package/templates/quickstart/src/blocks/saucedemo-web/inventory/methods/remove-from-cart.effect.block.ts +4 -3
- package/templates/quickstart/src/blocks/saucedemo-web/inventory/nav-item-detail.block.ts +3 -3
- package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/nav-back-to-inventory.block.ts +3 -3
- package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/nav-back-to-products.block.ts +3 -3
- package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/nav-continue-shopping.block.ts +3 -3
- package/templates/quickstart/src/blocks/saucedemo-web/methods/fill-password.method.block.ts +5 -29
- package/templates/quickstart/src/blocks/saucedemo-web/methods/fill-username.method.block.ts +5 -48
- package/templates/quickstart/src/blocks/saucedemo-web/methods/submit-login.method.block.ts +13 -77
- package/templates/quickstart/src/blocks/saucedemo-web/methods/submit-logout.method.block.ts +5 -4
- package/templates/quickstart/src/blocks/saucedemo-web/nav-login.block.ts +3 -3
- package/templates/quickstart/src/flows/api-demo.flow.ts +45 -0
- package/templates/quickstart/src/flows/cart-bulk.flow.ts +19 -14
- package/templates/quickstart/src/flows/cart-continue.flow.ts +10 -8
- package/templates/quickstart/src/flows/cart-mem.flow.ts +7 -7
- package/templates/quickstart/src/flows/catalog-logout.flow.ts +13 -8
- package/templates/quickstart/src/flows/checkout-then-browse-again.flow.ts +26 -48
- package/templates/quickstart/src/flows/checkout.flow.ts +70 -63
- package/templates/quickstart/src/flows/device-showcase.flow.ts +24 -25
- package/templates/quickstart/src/flows/login.flow.ts +11 -18
- package/templates/quickstart/src/flows/mem-stub-demo.flow.ts +12 -0
- package/templates/quickstart/src/flows/shop.flow.ts +15 -20
- package/templates/quickstart/src/flows/smoke.flow.ts +12 -27
- package/templates/quickstart/src/flows/stub-on-error.flow.ts +31 -0
- package/templates/quickstart/src/flows/viewer-blocked.flow.ts +26 -34
- package/templates/quickstart/src/states/checkout.mem-stubs.ts +11 -0
- package/templates/quickstart/src/states/checkout.states.ts +21 -11
- package/templates/quickstart/src/stubs/device-showcase.ts +191 -0
- package/templates/quickstart/src/stubs/login.ts +37 -0
- package/templates/quickstart/tests/chain-flow.spec.ts +7 -10
- package/templates/scaffold/README.md +2 -1
- package/templates/scaffold/STRUCTURE.md +5 -4
- package/templates/scaffold/config/waygraph.config.ts +1 -0
- package/templates/scaffold/gitignore +1 -0
- package/templates/scaffold/src/flows/README.md +2 -2
- package/templates/scaffold/src/map/(app_base)/docs/_nav.block.ts +3 -3
- package/templates/scaffold/src/map/(app_base)/docs/_page.block.ts +3 -3
- package/templates/scaffold/src/map/(app_base)/home/_methods/add-item.effect.block.ts +4 -4
- package/templates/scaffold/src/map/(app_base)/home/_methods/assert-hello.method.block.ts +3 -3
- package/templates/scaffold/src/map/(app_base)/home/_methods/assert-item-added.method.block.ts +3 -3
- package/templates/scaffold/src/map/(app_base)/home/_methods/clear-cart.method.block.ts +5 -4
- package/templates/scaffold/src/map/(app_base)/home/_methods/remove-item.effect.block.ts +4 -4
- package/templates/scaffold/src/map/(app_base)/home/_nav.block.ts +3 -3
- package/templates/scaffold/src/map/(app_base)/home/_page.block.ts +3 -3
- package/templates/scaffold/src/map/(app_base)/home/nav-verification-link.block.ts +4 -4
- package/templates/scaffold/src/map/(external)/hoppscotch/_keys.ts +21 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/assert-response-body.method.block.ts +4 -4
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/assert-response-header.method.block.ts +4 -4
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/assert-status.method.block.ts +4 -4
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/pick-extension-interceptor.method.block.ts +5 -4
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/read-response-body.method.block.ts +6 -5
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/read-response-headers.method.block.ts +6 -5
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/send-request.method.block.ts +5 -4
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-bearer-token.method.block.ts +6 -5
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-headers.method.block.ts +6 -5
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-json-body.method.block.ts +6 -5
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-method.method.block.ts +6 -5
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-query-params.method.block.ts +6 -5
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-url.method.block.ts +6 -5
- package/templates/scaffold/src/map/(external)/hoppscotch/_nav.block.ts +3 -3
- package/templates/scaffold/src/map/(external)/hoppscotch/_page.block.ts +3 -3
- package/templates/scaffold/src/map/(external)/hoppscotch/_states.ts +6 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/settings/_nav.block.ts +3 -3
- package/templates/scaffold/src/map/(external)/mailpit/_keys.ts +13 -0
- package/templates/scaffold/src/map/(external)/mailpit/_methods/assert-email-content.method.block.ts +4 -4
- package/templates/scaffold/src/map/(external)/mailpit/_methods/assert-email-received.method.block.ts +4 -4
- package/templates/scaffold/src/map/(external)/mailpit/_methods/extract-email-link.method.block.ts +6 -5
- package/templates/scaffold/src/map/(external)/mailpit/_methods/open-message.method.block.ts +6 -5
- package/templates/scaffold/src/map/(external)/mailpit/_nav.block.ts +3 -3
- package/templates/scaffold/src/map/(external)/mailpit/_page.block.ts +3 -3
- package/templates/scaffold/src/map/(external)/mailpit/_states.ts +9 -0
- package/templates/scaffold/src/map/README.md +7 -0
- package/templates/scaffold/src/states/README.md +4 -1
- package/templates/scaffold/src/states/demo.mem-keys.ts +1 -29
- package/templates/scaffold/src/states/demo.states.ts +14 -20
- package/templates/scaffold/tests/hoppscotch.spec.ts +1 -11
- package/templates/scaffold/tests/mail-verify.spec.ts +2 -2
- package/templates/skills/waygraph-blind-pilot.skill.md +2 -6
- package/templates/skills/waygraph-convention.skill.md +23 -14
- package/templates/skills/waygraph-pilot.skill.md +7 -4
- package/dist/auto-session/verbose-log.js +0 -16
- package/dist/auto-session.d.ts +0 -2
- package/dist/auto-session.js +0 -3
- package/dist/cli/discover.d.ts +0 -40
- package/dist/cli/discover.js +0 -148
- package/dist/commands/agent-dive.js +0 -52
- package/dist/commands/check.js +0 -192
- package/dist/commands/map.js +0 -29
- package/dist/commands/run.js +0 -104
- package/dist/commands/traverse.js +0 -177
- package/dist/core/block.d.ts +0 -109
- package/dist/core/blocks/effect.js +0 -23
- package/dist/core/config.js +0 -17
- package/dist/core/engine.d.ts +0 -198
- package/dist/core/flow.d.ts +0 -293
- package/dist/core/flow.js +0 -432
- package/dist/core.d.ts +0 -14
- package/dist/core.js +0 -15
- package/dist/highlights/merge.d.ts +0 -8
- package/dist/highlights/merge.js +0 -173
- package/dist/highlights/stub-ctx.d.ts +0 -10
- package/dist/highlights/stub-ctx.js +0 -331
- package/dist/highlights/types.d.ts +0 -607
- package/dist/highlights.d.ts +0 -9
- package/dist/highlights.js +0 -10
- package/dist/pilot-overlay.d.ts +0 -5
- package/dist/pilot-overlay.js +0 -6
- package/dist/runner/banner-log.js +0 -63
- package/dist/runner/chain-run.js +0 -102
- package/dist/runner/cursor.js +0 -140
- package/dist/runner/demo-log.js +0 -316
- package/dist/runner/device-stage.d.ts +0 -9
- package/dist/runner/device-stage.js +0 -420
- package/dist/runner/discovery.js +0 -105
- package/dist/runner/index.js +0 -2
- package/dist/runner/inpage/banner.d.ts +0 -21
- package/dist/runner/inpage/banner.js +0 -156
- package/dist/runner/inpage/caption.d.ts +0 -3
- package/dist/runner/inpage/caption.js +0 -23
- package/dist/runner/inpage/core.d.ts +0 -4
- package/dist/runner/inpage/core.js +0 -316
- package/dist/runner/inpage/device.d.ts +0 -3
- package/dist/runner/inpage/device.js +0 -211
- package/dist/runner/inpage/network.d.ts +0 -15
- package/dist/runner/inpage/network.js +0 -217
- package/dist/runner/inpage/panel-chrome.js +0 -192
- package/dist/runner/inpage/stamp.js +0 -46
- package/dist/runner/inpage/swipe-zoom.js +0 -220
- package/dist/runner/inpage/todos.js +0 -337
- package/dist/runner/interaction-patch.js +0 -384
- package/dist/runner/main.js +0 -469
- package/dist/runner/network-capture.d.ts +0 -9
- package/dist/runner/network-capture.js +0 -126
- package/dist/runner/overlay-css.d.ts +0 -3
- package/dist/runner/overlay-css.js +0 -377
- package/dist/runner/overlay-install.js +0 -90
- package/dist/runner/overlay-stage.js +0 -110
- package/dist/runner/rings.js +0 -514
- package/dist/runner/seed-mem.js +0 -110
- package/dist/runner/slides.js +0 -278
- package/dist/runner/step-mode.js +0 -703
- package/dist/runner/step-panels.js +0 -729
- package/dist/runner/teardown.js +0 -202
- package/dist/runner/todo-dock.js +0 -142
- package/dist/session/step-overlay.d.ts +0 -37
- package/dist/session/step-overlay.js +0 -244
- package/examples/routed-demo/playwright.config.ts +0 -21
- package/examples/saucedemo/playwright.config.ts +0 -19
- package/examples/saucedemo/scripts/drive-auto-cli.mjs +0 -93
- package/examples/saucedemo/scripts/prove-add-to-cart-menu.mjs +0 -126
- package/examples/saucedemo/scripts/prove-auto-graph.mjs +0 -92
- package/examples/saucedemo/scripts/prove-wrong-login-runtime.mjs +0 -63
- package/examples/saucedemo/src/blocks/saucedemo-web/ff-owner-auth.block.ts +0 -22
- package/templates/quickstart/playwright.config.ts +0 -14
- package/templates/quickstart/scripts/drive-auto-cli.mjs +0 -93
- package/templates/quickstart/src/blocks/saucedemo-web/ff-owner-auth.block.ts +0 -22
- /package/dist/{commands → cli/commands}/agent-dive-scaffold.d.ts +0 -0
- /package/dist/{commands → cli/commands}/agent-dive.d.ts +0 -0
- /package/dist/{commands → cli/commands}/extensions.d.ts +0 -0
- /package/dist/{commands → cli/commands}/init.d.ts +0 -0
- /package/dist/{commands → cli/commands}/list.d.ts +0 -0
- /package/dist/{commands → cli/commands}/map.d.ts +0 -0
- /package/dist/{commands → cli/commands}/session.d.ts +0 -0
- /package/dist/{commands → cli/commands}/test.d.ts +0 -0
- /package/dist/{commands → cli/commands}/traverse.d.ts +0 -0
- /package/dist/{commands → cli/commands}/try.d.ts +0 -0
- /package/dist/{commands → cli/commands}/upgrade.d.ts +0 -0
- /package/dist/{highlights → demo/narration}/shorthand.js +0 -0
- /package/dist/{pilot-overlay/action-ring.d.ts → demo/overlay/pilot/actions.d.ts} +0 -0
- /package/dist/{ui → demo/overlay/ui}/components/ring.d.ts +0 -0
- /package/dist/{ui → demo/overlay/ui}/stylesheet.d.ts +0 -0
- /package/dist/{ui → demo/overlay/ui}/stylesheet.js +0 -0
- /package/dist/{ui → demo/overlay/ui}/tokens.d.ts +0 -0
- /package/dist/{ui → demo/overlay/ui}/tokens.js +0 -0
- /package/dist/{highlights → demo}/types.js +0 -0
- /package/dist/{auto-session → demo}/verbose-log.d.ts +0 -0
- /package/dist/{selector.d.ts → engine/trait/selector.d.ts} +0 -0
- /package/dist/{selector.js → engine/trait/selector.js} +0 -0
- /package/dist/{trait.js → engine/trait/trait.js} +0 -0
- /package/dist/{session/block-inject.d.ts → manifest/roots.d.ts} +0 -0
- /package/dist/{browser.d.ts → runtime/browser.d.ts} +0 -0
- /package/dist/{env-file.d.ts → runtime/env-file.d.ts} +0 -0
- /package/dist/{playwright-config.js → runtime/playwright-config.js} +0 -0
- /package/dist/{playwright.config.d.ts → runtime/playwright.config.d.ts} +0 -0
- /package/dist/{video-dir.d.ts → runtime/video-dir.d.ts} +0 -0
- /package/dist/{webserver.d.ts → runtime/webserver.d.ts} +0 -0
package/dist/runner/main.js
DELETED
|
@@ -1,469 +0,0 @@
|
|
|
1
|
-
// Moved verbatim from the former CHAIN_RUNNER_SCRIPT template string in cli.ts (see src/ARCHITECTURE.md).
|
|
2
|
-
// Runs inside the target project's own waygraph copy - keep it dependency-light and self-contained.
|
|
3
|
-
import { findBlock, findFlow, parseChainSpec } from "./discovery.js";
|
|
4
|
-
import { seedMemForBlock, seedMemForFlow } from "./seed-mem.js";
|
|
5
|
-
import { join } from "node:path";
|
|
6
|
-
import { mkdirSync } from "node:fs";
|
|
7
|
-
import { isExpectedChainFailure, parseVideoViewport, runChainedFlows, runJsonReportMode } from "./chain-run.js";
|
|
8
|
-
import { runStepMode } from "./step-mode.js";
|
|
9
|
-
import { connect } from "../types.js";
|
|
10
|
-
import { MemPage } from "../mem-page.js";
|
|
11
|
-
import { Engine, start, end, chainFlow, isFastForwardBlock, branchRoutes, runBranchRegression } from "../core.js";
|
|
12
|
-
import { withWebServer } from "../webserver.js";
|
|
13
|
-
import { resolveVideoDir } from "../video-dir.js";
|
|
14
|
-
import { chromiumExecutablePath, extensionPathsFromEnv, launchContext } from "../browser.js";
|
|
15
|
-
|
|
16
|
-
async function runMain() {
|
|
17
|
-
const projectDir = process.argv[2];
|
|
18
|
-
const spec = process.argv[3];
|
|
19
|
-
const mem = new MemPage();
|
|
20
|
-
// Computed early - JSON-report mode's stdout is meant to be ONE parseable
|
|
21
|
-
// JSON object for whatever's reading it afterward (a script, an agent),
|
|
22
|
-
// not a human's console. Every informational console.log below is
|
|
23
|
-
// skipped for it; only the final JSON report (or a thrown Error, for a
|
|
24
|
-
// truly unexpected failure outside runJsonReportMode's own try/catch)
|
|
25
|
-
// reaches stdout.
|
|
26
|
-
const jsonReport = process.env.WAYGRAPH_JSON === "1";
|
|
27
|
-
const ffExpand =
|
|
28
|
-
process.env.WAYGRAPH_FF_EXPAND === "1" || process.env.WAYGRAPH_FF_DISABLED === "1";
|
|
29
|
-
const ffDisabled = process.env.WAYGRAPH_FF_DISABLED === "1";
|
|
30
|
-
/** Expand or keep fastForwardComposeBlock units for demo/run step lists. */
|
|
31
|
-
const flattenBlockInfos = (blockInfos) => {
|
|
32
|
-
const out = [];
|
|
33
|
-
for (const bi of blockInfos) {
|
|
34
|
-
const b = bi.block;
|
|
35
|
-
if (ffExpand && isFastForwardBlock(b)) {
|
|
36
|
-
for (const step of b.steps()) {
|
|
37
|
-
out.push({
|
|
38
|
-
name: step.name,
|
|
39
|
-
block: step.block,
|
|
40
|
-
...(step.routes ? { routes: step.routes } : {}),
|
|
41
|
-
...(bi.resetSessionBefore ? { resetSessionBefore: true } : {}),
|
|
42
|
-
// Dispute / --ff-disabled: keep blitz pacing on former FF inners so
|
|
43
|
-
// wall-clock stays comparable to opaque FF (same real acts).
|
|
44
|
-
wasFastForward: true,
|
|
45
|
-
ffSource: b.name,
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
} else {
|
|
49
|
-
out.push(bi);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
return out;
|
|
53
|
-
};
|
|
54
|
-
let resolved = [];
|
|
55
|
-
let chainFlows = null;
|
|
56
|
-
// A bare identifier (no "(", no "then") might name an existing Flow
|
|
57
|
-
// that's already wired up (e.g. loginFlow) - try that FIRST so pointing
|
|
58
|
-
// at real, already-built flows needs no chain-spec typing at all. Falls
|
|
59
|
-
// through to ordinary block-chain parsing if nothing matches.
|
|
60
|
-
const bareRef = /^[A-Za-z_$][\w]*$/.test(spec.trim()) ? spec.trim() : null;
|
|
61
|
-
if (bareRef) {
|
|
62
|
-
const flow = await findFlow(projectDir, bareRef);
|
|
63
|
-
if (flow && typeof flow.blocks === "function") {
|
|
64
|
-
const blockInfos = flattenBlockInfos(flow.blocks());
|
|
65
|
-
// Same --data / WAYGRAPH_DATA seeding as the multi-segment path.
|
|
66
|
-
// Without this, `waygraph run shop.flow.ts --data '{...}'` (and bare
|
|
67
|
-
// export names) hit preflight with an empty MemPage.
|
|
68
|
-
const stubActive = flow.memStub === true || process.env.WAYGRAPH_MEM_STUB === "1";
|
|
69
|
-
const seedMem = () => seedMemForFlow(mem, blockInfos, undefined, bareRef, stubActive);
|
|
70
|
-
resolved = blockInfos.map((bi, idx) => ({
|
|
71
|
-
block: bi.block,
|
|
72
|
-
exportName: bi.name,
|
|
73
|
-
seedMem: idx === 0 ? seedMem : undefined,
|
|
74
|
-
highlightFixtures: flow.highlightFixtures,
|
|
75
|
-
demoPace: flow.demoPace,
|
|
76
|
-
highlightStyle: flow.highlightStyle,
|
|
77
|
-
expectedFailureReason:
|
|
78
|
-
flow.expectedFailureReason && idx === blockInfos.length - 1
|
|
79
|
-
? flow.expectedFailureReason
|
|
80
|
-
: undefined,
|
|
81
|
-
...(bi.wasFastForward ? { wasFastForward: true, ffSource: bi.ffSource } : {}),
|
|
82
|
-
}));
|
|
83
|
-
chainFlows = [flow];
|
|
84
|
-
if (!jsonReport) {
|
|
85
|
-
console.log(
|
|
86
|
-
'waygraph: running existing flow "' + bareRef + '" - ' +
|
|
87
|
-
resolved.map((r) => r.block.name).join(" -> ") + " (" + resolved.length + " block" +
|
|
88
|
-
(resolved.length === 1 ? "" : "s") + ", no chain spec needed)",
|
|
89
|
-
);
|
|
90
|
-
if (ffDisabled) {
|
|
91
|
-
console.error(
|
|
92
|
-
"waygraph demo: --ff-disabled - FFCompose expanded to inners (dispute / step locus); blitz pacing kept on former FF steps",
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
if (resolved.length === 0) {
|
|
99
|
-
const segments = parseChainSpec(spec);
|
|
100
|
-
if (segments.length === 0) {
|
|
101
|
-
throw new Error("waygraph chain: empty spec - give at least one block name");
|
|
102
|
-
}
|
|
103
|
-
// Each "then"-separated segment can ALSO name an existing Flow (a
|
|
104
|
-
// Flow's own requires, unioned across its Blocks, take the same
|
|
105
|
-
// JSON-payload shape a single Block's requires would), not just a
|
|
106
|
-
// Block. "loginFlow then dashboardFlow" chains two whole Flows one
|
|
107
|
-
// after another - a bare Block segment gets wrapped as its own
|
|
108
|
-
// trivial one-Block Flow so the whole spec reduces to one thing:
|
|
109
|
-
// chainFlow(...) does the actual sequencing (session-reset boundaries
|
|
110
|
-
// included) that used to be hand-rolled here - this is a thin wrapper
|
|
111
|
-
// over the real engine primitive, not a second copy of its logic.
|
|
112
|
-
const wrapEngine = new Engine();
|
|
113
|
-
const flows = [];
|
|
114
|
-
// Parallel to flows - only a REAL named Flow (found via findFlow)
|
|
115
|
-
// counts as an "episode" a human would want labeled; a bare Block
|
|
116
|
-
// segment gets wrapped as its own trivial one-Block Flow so it can
|
|
117
|
-
// still flow through chainFlow's sequencing uniformly, but it's not
|
|
118
|
-
// an authored scenario and gets no episode number - keeps the plain
|
|
119
|
-
// "quick ad hoc block chain" case free of meaningless "Episode 1"/
|
|
120
|
-
// "Episode 2" labels on things that were never episodes to begin with.
|
|
121
|
-
const flowMeta = [];
|
|
122
|
-
let episodeCounter = 0;
|
|
123
|
-
// seedMem is a closure, NOT called here - seeding every segment's own
|
|
124
|
-
// json payload eagerly, all upfront during resolution, was a real bug:
|
|
125
|
-
// mem is one shared object, so when two segments require the SAME key
|
|
126
|
-
// (e.g. two segments both requiring LoginCreds, each with a DIFFERENT
|
|
127
|
-
// payload - "login as standard_user then login as locked_out_user"),
|
|
128
|
-
// the LAST segment resolved silently overwrote the first's value
|
|
129
|
-
// before either segment had even started running - so the FIRST
|
|
130
|
-
// segment's own blocks would run against the SECOND segment's
|
|
131
|
-
// credentials. Deferred to execution time instead (runStepMode calls
|
|
132
|
-
// this exactly once, right as each segment's first block is reached -
|
|
133
|
-
// see resolved[i].seedMem below), same moment session-reset already
|
|
134
|
-
// happens for the same reason.
|
|
135
|
-
for (const seg of segments) {
|
|
136
|
-
const flow = await findFlow(projectDir, seg.ref);
|
|
137
|
-
if (flow && typeof flow.blocks === "function") {
|
|
138
|
-
flows.push(flow);
|
|
139
|
-
episodeCounter += 1;
|
|
140
|
-
const stubActive = flow.memStub === true || process.env.WAYGRAPH_MEM_STUB === "1";
|
|
141
|
-
flowMeta.push({
|
|
142
|
-
episodeNumber: episodeCounter,
|
|
143
|
-
episodeTitle: flow.title || seg.ref,
|
|
144
|
-
expectedFailureReason: flow.expectedFailureReason,
|
|
145
|
-
highlightFixtures: flow.highlightFixtures,
|
|
146
|
-
demoPace: flow.demoPace,
|
|
147
|
-
highlightStyle: flow.highlightStyle,
|
|
148
|
-
seedMem: () => seedMemForFlow(mem, flow.blocks(), seg.json, seg.ref, stubActive),
|
|
149
|
-
});
|
|
150
|
-
} else {
|
|
151
|
-
const r = await findBlock(projectDir, seg.ref);
|
|
152
|
-
flows.push(wrapEngine.defineFlow([start, r.block, end]));
|
|
153
|
-
// A bare Block segment (no Flow, no withMemStub to opt in) only gets
|
|
154
|
-
// memStub via the global --mem-stub/WAYGRAPH_MEM_STUB override.
|
|
155
|
-
const stubActive = process.env.WAYGRAPH_MEM_STUB === "1";
|
|
156
|
-
flowMeta.push({
|
|
157
|
-
episodeNumber: undefined,
|
|
158
|
-
episodeTitle: undefined,
|
|
159
|
-
highlightFixtures: undefined,
|
|
160
|
-
demoPace: undefined,
|
|
161
|
-
highlightStyle: undefined,
|
|
162
|
-
seedMem: () => seedMemForBlock(mem, r, seg.json, stubActive),
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
const combinedBlocks = flattenBlockInfos(chainFlow(...flows).blocks());
|
|
167
|
-
let fi = 0;
|
|
168
|
-
// Episode lengths must follow the same flatten so remainingInFlow stays aligned.
|
|
169
|
-
const flowLengths = flows.map((f) => flattenBlockInfos(f.blocks()).length);
|
|
170
|
-
let remainingInFlow = flowLengths[0];
|
|
171
|
-
let isFirstOfSegment = true;
|
|
172
|
-
resolved = combinedBlocks.map((bi) => {
|
|
173
|
-
while (remainingInFlow === 0) {
|
|
174
|
-
fi += 1;
|
|
175
|
-
remainingInFlow = flowLengths[fi];
|
|
176
|
-
isFirstOfSegment = true;
|
|
177
|
-
}
|
|
178
|
-
const meta = flowMeta[fi];
|
|
179
|
-
const entry = {
|
|
180
|
-
block: bi.block,
|
|
181
|
-
exportName: bi.name,
|
|
182
|
-
resetSession: bi.resetSessionBefore === true,
|
|
183
|
-
episodeNumber: meta.episodeNumber,
|
|
184
|
-
episodeTitle: meta.episodeTitle,
|
|
185
|
-
highlightFixtures: meta.highlightFixtures,
|
|
186
|
-
demoPace: meta.demoPace,
|
|
187
|
-
highlightStyle: meta.highlightStyle,
|
|
188
|
-
expectedFailureReason:
|
|
189
|
-
meta.expectedFailureReason && remainingInFlow === 1 ? meta.expectedFailureReason : undefined,
|
|
190
|
-
seedMem: isFirstOfSegment ? meta.seedMem : undefined,
|
|
191
|
-
...(bi.wasFastForward ? { wasFastForward: true, ffSource: bi.ffSource } : {}),
|
|
192
|
-
};
|
|
193
|
-
remainingInFlow -= 1;
|
|
194
|
-
isFirstOfSegment = false;
|
|
195
|
-
return entry;
|
|
196
|
-
});
|
|
197
|
-
chainFlows = flows;
|
|
198
|
-
if (!jsonReport) {
|
|
199
|
-
console.log(
|
|
200
|
-
"waygraph: chaining " + resolved.map((r) => r.block.name).join(" -> ") +
|
|
201
|
-
" (" + resolved.length + " block" + (resolved.length === 1 ? "" : "s") + ")",
|
|
202
|
-
);
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
const step = process.env.WAYGRAPH_STEP === "1";
|
|
206
|
-
// Stepping through headless defeats the point for a MANUAL demo - a
|
|
207
|
-
// human can't watch it. But an explicit WAYGRAPH_HEADED=0 always wins
|
|
208
|
-
// over that default: --auto-play-video sets STEP=1 (it still needs the
|
|
209
|
-
// overlay/narration machinery) AND HEADED=0 (unattended + recorded,
|
|
210
|
-
// nobody has to watch a live window for it to be right).
|
|
211
|
-
const headed =
|
|
212
|
-
process.env.WAYGRAPH_HEADED === "0" ? false : process.env.WAYGRAPH_HEADED === "1" || step;
|
|
213
|
-
// Step mode: blitz Playwright slowMo when any opaque FF **or** former-FF
|
|
214
|
-
// inners (--ff-disabled) are in the resolved list. Explicit WAYGRAPH_SLOWMO wins.
|
|
215
|
-
const hasFfBlitz = resolved.some(
|
|
216
|
-
(r) =>
|
|
217
|
-
r &&
|
|
218
|
-
((r.block && r.block.fastForward === true) || r.wasFastForward === true),
|
|
219
|
-
);
|
|
220
|
-
const slowMo = process.env.WAYGRAPH_SLOWMO !== undefined
|
|
221
|
-
? Number(process.env.WAYGRAPH_SLOWMO)
|
|
222
|
-
: step
|
|
223
|
-
? hasFfBlitz
|
|
224
|
-
? 0
|
|
225
|
-
: 350
|
|
226
|
-
: undefined;
|
|
227
|
-
if (step && hasFfBlitz && process.env.WAYGRAPH_SLOWMO === undefined && !jsonReport) {
|
|
228
|
-
console.error(
|
|
229
|
-
ffDisabled
|
|
230
|
-
? "waygraph demo: --ff-disabled (expanded) -> Playwright slowMo=0 on former FF steps (blitz; same acts as opaque FF)"
|
|
231
|
-
: "waygraph demo: opaque FFCompose in flow -> Playwright slowMo=0 (blitz); set WAYGRAPH_SLOWMO to override",
|
|
232
|
-
);
|
|
233
|
-
}
|
|
234
|
-
// Step (demo) mode: slowMo is waygraph's own beat after each action, not Playwright's per-operation slowMo, so a
|
|
235
|
-
// step's pace can remove it and typing is not taxed per keystroke. The browser launches at 0.
|
|
236
|
-
const launchSlowMo = step ? 0 : slowMo;
|
|
237
|
-
const baseURL = process.env.WAYGRAPH_BASE_URL;
|
|
238
|
-
const title = process.env.WAYGRAPH_TITLE;
|
|
239
|
-
// Comma-separated Block names (their real .name, e.g. "login") that
|
|
240
|
-
// should blow past the overlay's own added dwell (ring pop, cursor
|
|
241
|
-
// travel, typing delay, and that block's own gates) - "I want the login
|
|
242
|
-
// block to be faster than the rest of the demo," Dan's own phrase.
|
|
243
|
-
// FFCompose blocks get the same skipTheater automatically (no need to
|
|
244
|
-
// list them here). Distinct from --fast (gates only).
|
|
245
|
-
const fastBlockNames = new Set(
|
|
246
|
-
(process.env.WAYGRAPH_FAST_BLOCKS || "")
|
|
247
|
-
.split(",")
|
|
248
|
-
.map((s) => s.trim())
|
|
249
|
-
.filter(Boolean),
|
|
250
|
-
);
|
|
251
|
-
// Off by default - a same-user chain (login -> dashboard -> ...) needs
|
|
252
|
-
// to STAY authenticated across its own blocks. Only a chain deliberately
|
|
253
|
-
// re-visiting an auth entry point (e.g. "login" appearing twice, to
|
|
254
|
-
// demo the same flow starting fresh each time) needs this.
|
|
255
|
-
const clearSession = process.env.WAYGRAPH_CLEAR_SESSION === "1";
|
|
256
|
-
const videoEnv = process.env.WAYGRAPH_VIDEO;
|
|
257
|
-
let videoDir = null;
|
|
258
|
-
if (videoEnv) {
|
|
259
|
-
videoDir = videoEnv === "1" ? await resolveVideoDir(projectDir) : videoEnv;
|
|
260
|
-
mkdirSync(videoDir, { recursive: true });
|
|
261
|
-
}
|
|
262
|
-
/** Fixed 16:9 capture for --video (demo QA and headless run). Step+video no longer maximizes. */
|
|
263
|
-
const DEFAULT_VIDEO_VIEWPORT = { width: 1920, height: 1080 };
|
|
264
|
-
const DEFAULT_RUN_VIDEO_VIEWPORT = { width: 1280, height: 720 };
|
|
265
|
-
const videoViewportParsed = parseVideoViewport(process.env.WAYGRAPH_VIDEO_VIEWPORT);
|
|
266
|
-
const fixedVideoViewport = videoDir
|
|
267
|
-
? (videoViewportParsed ?? (step ? DEFAULT_VIDEO_VIEWPORT : DEFAULT_RUN_VIDEO_VIEWPORT))
|
|
268
|
-
: null;
|
|
269
|
-
const engine = new Engine({ headless: !headed, slowMo: launchSlowMo });
|
|
270
|
-
let result;
|
|
271
|
-
// Non-interactive execution (no --step) runs the whole chain as one
|
|
272
|
-
// composed flow with no per-block loop of its own to defer seeding
|
|
273
|
-
// into - it can't support two segments needing DIFFERENT values for the
|
|
274
|
-
// SAME mem key (e.g. two segments both requiring LoginCreds, each with
|
|
275
|
-
// its own payload). Fall back to seeding every segment eagerly, upfront -
|
|
276
|
-
// the same limitation "chain" always had; only --step's own runStepMode
|
|
277
|
-
// loop actually needs (and correctly supports, via resolved[i].seedMem)
|
|
278
|
-
// per-segment differentiated values.
|
|
279
|
-
if (!step && !jsonReport) {
|
|
280
|
-
for (const r of resolved) {
|
|
281
|
-
if (r.seedMem) r.seedMem();
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
if (process.env.WAYGRAPH_ALL_BRANCHES === "1") {
|
|
285
|
-
return runAllBranchesMode(chainFlows, mem, baseURL, headed, engine);
|
|
286
|
-
}
|
|
287
|
-
if (step || jsonReport || baseURL || videoDir) {
|
|
288
|
-
const { chromium } = await import("@playwright/test");
|
|
289
|
-
// --start-maximized (step mode only): viewport: null alone only made
|
|
290
|
-
// the PAGE content track the window - the actual browser WINDOW still
|
|
291
|
-
// launched at Chromium's own default size/position, which stayed put
|
|
292
|
-
// where it was for a previous, larger monitor and looked chopped off on
|
|
293
|
-
// a smaller one. Maximizing fills whatever screen it's actually on.
|
|
294
|
-
const executablePath = chromiumExecutablePath();
|
|
295
|
-
// Maximized for interactive step, and for fixed video viewport so the
|
|
296
|
-
// locked record size can actually fit (otherwise .webm gets grey pad).
|
|
297
|
-
const contextOpts = fixedVideoViewport
|
|
298
|
-
? {
|
|
299
|
-
baseURL,
|
|
300
|
-
viewport: fixedVideoViewport,
|
|
301
|
-
// Lock DPR so --video-viewport 800x450 stays 800x450 in the .webm
|
|
302
|
-
// (HiDPI hosts otherwise scale recordVideo to e.g. 1920x1080).
|
|
303
|
-
deviceScaleFactor: 1,
|
|
304
|
-
hasTouch: true,
|
|
305
|
-
}
|
|
306
|
-
: step
|
|
307
|
-
? { baseURL, viewport: null, hasTouch: true }
|
|
308
|
-
: { baseURL, viewport: { width: 1280, height: 720 }, hasTouch: true };
|
|
309
|
-
if (videoDir) {
|
|
310
|
-
contextOpts.recordVideo = fixedVideoViewport
|
|
311
|
-
? { dir: videoDir, size: fixedVideoViewport }
|
|
312
|
-
: { dir: videoDir };
|
|
313
|
-
}
|
|
314
|
-
const { context, close: closeBrowser } = await launchContext({
|
|
315
|
-
launcher: chromium,
|
|
316
|
-
launch: {
|
|
317
|
-
headless: !headed,
|
|
318
|
-
slowMo: launchSlowMo,
|
|
319
|
-
args: step || fixedVideoViewport ? ["--start-maximized"] : [],
|
|
320
|
-
...(executablePath ? { executablePath } : {}),
|
|
321
|
-
},
|
|
322
|
-
context: contextOpts,
|
|
323
|
-
extensions: extensionPathsFromEnv(),
|
|
324
|
-
});
|
|
325
|
-
let pageForVideo = null;
|
|
326
|
-
try {
|
|
327
|
-
if (step) {
|
|
328
|
-
const page = await context.newPage();
|
|
329
|
-
pageForVideo = page;
|
|
330
|
-
if (fixedVideoViewport) page.__wgVideoViewport = fixedVideoViewport;
|
|
331
|
-
// Step 1's "before" panel used to sit over a blank about:blank page
|
|
332
|
-
// until the human clicked Run - show the real destination first.
|
|
333
|
-
if (baseURL) {
|
|
334
|
-
await page.goto(baseURL).catch(() => {});
|
|
335
|
-
}
|
|
336
|
-
result = await runStepMode(engine, start, end, context, page, mem, resolved, slowMo, title, fastBlockNames, clearSession, baseURL);
|
|
337
|
-
} else if (jsonReport) {
|
|
338
|
-
const page = await context.newPage();
|
|
339
|
-
pageForVideo = page;
|
|
340
|
-
if (fixedVideoViewport) page.__wgVideoViewport = fixedVideoViewport;
|
|
341
|
-
if (baseURL) {
|
|
342
|
-
await page.goto(baseURL).catch(() => {});
|
|
343
|
-
}
|
|
344
|
-
const report = await runJsonReportMode(engine, start, end, context, page, mem, resolved, baseURL);
|
|
345
|
-
console.log(JSON.stringify(report, null, 2));
|
|
346
|
-
if (!report.ok) process.exitCode = 1;
|
|
347
|
-
return;
|
|
348
|
-
} else {
|
|
349
|
-
const page = await context.newPage();
|
|
350
|
-
pageForVideo = page;
|
|
351
|
-
if (fixedVideoViewport) page.__wgVideoViewport = fixedVideoViewport;
|
|
352
|
-
if (baseURL) {
|
|
353
|
-
await page.goto(baseURL).catch(() => {});
|
|
354
|
-
}
|
|
355
|
-
if (chainFlows && chainFlows.length > 0) {
|
|
356
|
-
result = await runChainedFlows(chainFlow, chainFlows, context, mem, page);
|
|
357
|
-
} else {
|
|
358
|
-
const blocks = resolved.map((r) => r.block);
|
|
359
|
-
const chained = blocks.reduce((a, b) => connect(a, b));
|
|
360
|
-
const flow = engine.defineFlow([start, chained, end]);
|
|
361
|
-
result = await flow.run(context, mem, { page, closeOnFinish: false });
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
} finally {
|
|
365
|
-
// A recorded run's last visible state (a fixture ring, the network panel, a todo dock update)
|
|
366
|
-
// gets cut off mid-fade otherwise - context.close() used to fire the instant the flow's own
|
|
367
|
-
// promise resolved, with zero trailing room. Real, confirmed case: defineApiBlock's network
|
|
368
|
-
// panel only became visible in the recording's final ~1-2s because of this.
|
|
369
|
-
if (process.env.WAYGRAPH_VIDEO && pageForVideo && !pageForVideo.isClosed()) {
|
|
370
|
-
await new Promise((r) => setTimeout(r, 1800));
|
|
371
|
-
}
|
|
372
|
-
await context.close();
|
|
373
|
-
const savedVideo =
|
|
374
|
-
pageForVideo?.video() !== null && pageForVideo?.video() !== undefined
|
|
375
|
-
? await pageForVideo.video()?.path().catch(() => null)
|
|
376
|
-
: null;
|
|
377
|
-
if (savedVideo) {
|
|
378
|
-
console.log("waygraph: video saved to " + savedVideo);
|
|
379
|
-
}
|
|
380
|
-
await closeBrowser();
|
|
381
|
-
}
|
|
382
|
-
} else {
|
|
383
|
-
if (chainFlows && chainFlows.length > 0) {
|
|
384
|
-
try {
|
|
385
|
-
result = await chainFlow(...chainFlows).run(mem);
|
|
386
|
-
} catch (err) {
|
|
387
|
-
if (isExpectedChainFailure(chainFlows, err)) {
|
|
388
|
-
result = { __expectedFailure: true, message: err && err.message ? err.message : String(err) };
|
|
389
|
-
} else {
|
|
390
|
-
throw err;
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
} else {
|
|
394
|
-
const blocks = resolved.map((r) => r.block);
|
|
395
|
-
const chained = blocks.reduce((a, b) => connect(a, b));
|
|
396
|
-
const flow = engine.defineFlow([start, chained, end]);
|
|
397
|
-
const recordVideo = videoDir ? { dir: videoDir } : undefined;
|
|
398
|
-
result = await flow.run(mem, recordVideo ? { recordVideo } : undefined);
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
if (result && result.__expectedFailure) {
|
|
402
|
-
console.log("waygraph: chain finished (expected failure on last episode) -- " + result.message);
|
|
403
|
-
} else {
|
|
404
|
-
console.log("waygraph: chain finished -- " + JSON.stringify(result));
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
/**
|
|
409
|
-
* `waygraph run --blocks <flowName> --all-branches`: explore every path through that flow's own
|
|
410
|
-
* `.branch()` tree (see src/core/branch-regression.ts), not just whichever one the live state
|
|
411
|
-
* would dispatch to. Needs a single, bare Flow reference - a multi-segment chain spec has no one
|
|
412
|
-
* Flow to walk. `--shared-session` opts out of session cloning (WAYGRAPH_SHARED_SESSION=1).
|
|
413
|
-
*/
|
|
414
|
-
async function runAllBranchesMode(chainFlows, mem, baseURL, headed, engine) {
|
|
415
|
-
if (!chainFlows || chainFlows.length !== 1) {
|
|
416
|
-
console.error(
|
|
417
|
-
"waygraph run --all-branches: needs a single Flow reference (e.g. --blocks loginFlow), " +
|
|
418
|
-
"not a multi-segment chain spec - nothing else has one branch tree to explore.",
|
|
419
|
-
);
|
|
420
|
-
process.exitCode = 1;
|
|
421
|
-
return;
|
|
422
|
-
}
|
|
423
|
-
const flow = chainFlows[0];
|
|
424
|
-
if (!branchRoutes(flow)) {
|
|
425
|
-
console.error(
|
|
426
|
-
"waygraph run --all-branches: this Flow was not built with MapBuilder.branch() - " +
|
|
427
|
-
"there is no branch tree to explore. Run it normally instead.",
|
|
428
|
-
);
|
|
429
|
-
process.exitCode = 1;
|
|
430
|
-
return;
|
|
431
|
-
}
|
|
432
|
-
if (extensionPathsFromEnv().length > 0) {
|
|
433
|
-
console.warn("waygraph run --all-branches: extensions are not loaded (branches run in cloned contexts)");
|
|
434
|
-
}
|
|
435
|
-
const { chromium } = await import("@playwright/test");
|
|
436
|
-
const browser = await chromium.launch({ headless: !headed });
|
|
437
|
-
const cloneSession = process.env.WAYGRAPH_SHARED_SESSION !== "1";
|
|
438
|
-
try {
|
|
439
|
-
const context = await browser.newContext(baseURL ? { baseURL } : undefined);
|
|
440
|
-
const results = await runBranchRegression(flow, context, mem, { cloneSession });
|
|
441
|
-
for (const r of results) {
|
|
442
|
-
const line = `waygraph run --all-branches: ${r.path || "(root)"} -> ${r.status}` +
|
|
443
|
-
(r.result ? ` (${JSON.stringify(r.result)})` : "") +
|
|
444
|
-
(r.error ? ` - ${r.error}` : "");
|
|
445
|
-
console.log(line);
|
|
446
|
-
}
|
|
447
|
-
const failed = results.filter((r) => r.status === "failed");
|
|
448
|
-
if (failed.length) {
|
|
449
|
-
console.error(`waygraph run --all-branches: ${failed.length}/${results.length} path(s) failed`);
|
|
450
|
-
process.exitCode = 1;
|
|
451
|
-
}
|
|
452
|
-
} finally {
|
|
453
|
-
await browser.close();
|
|
454
|
-
}
|
|
455
|
-
void engine;
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
// Here, not in the host CLI: importing playwright.config loads the project's own @playwright/test,
|
|
459
|
-
// which would collide with the CLI's copy.
|
|
460
|
-
async function main() {
|
|
461
|
-
await withWebServer(process.argv[2], runMain);
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
export function startRunner() {
|
|
465
|
-
main().catch((err) => {
|
|
466
|
-
console.error(err && err.stack ? err.stack : String(err));
|
|
467
|
-
process.exitCode = 1;
|
|
468
|
-
});
|
|
469
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { Page } from "@playwright/test";
|
|
2
|
-
import type { NetworkEntry } from "./inpage/network.js";
|
|
3
|
-
|
|
4
|
-
/** Records one network-tab entry (and paints it live) - see network-capture.js's own header. */
|
|
5
|
-
export function recordNetworkEntry(page: Page, entry: NetworkEntry): Promise<void>;
|
|
6
|
-
/** Replays page.__wgNetworkHistory into a freshly (re)installed panel after a navigation. */
|
|
7
|
-
export function restoreNetworkHistory(page: Page): Promise<void>;
|
|
8
|
-
/** Hooks page.on('request'/'requestfinished') to capture real page traffic into the same panel. */
|
|
9
|
-
export function installNetworkCapture(page: Page): void;
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
// Real page network traffic -> the same network-tab overlay defineApiBlock's own calls use (see
|
|
2
|
-
// inpage/network.js's own header). Playwright's page.on('request'/'requestfinished') events cover
|
|
3
|
-
// every real request the PAGE makes (XHR/fetch/navigation) - not page.request.get()-style calls,
|
|
4
|
-
// which go through a separate APIRequestContext entirely and never touch the browser at all (that
|
|
5
|
-
// side is covered by defineApiBlock's own explicit call, in src/core/blocks/api.ts).
|
|
6
|
-
import { addNetworkEntry, clearNetworkLog } from "./inpage/network.js";
|
|
7
|
-
|
|
8
|
-
// Fetch/XHR/navigation only - a real page can fire dozens of image/font/stylesheet requests per
|
|
9
|
-
// second, which would flood a panel meant to answer "what API calls did this page just made".
|
|
10
|
-
const RELEVANT_TYPES = new Set(["xhr", "fetch", "document"]);
|
|
11
|
-
// Response bodies this size or smaller, and only if they look text-ish, get captured for the
|
|
12
|
-
// detail view - a multi-MB image/video response has no business being buffered into page memory
|
|
13
|
-
// just because a demo happened to be running.
|
|
14
|
-
const MAX_BODY_BYTES = 200_000;
|
|
15
|
-
// Matches the in-page addNetworkEntry's own cap (network.js) - the Node-side history this backs
|
|
16
|
-
// stays in sync with what the panel can actually show.
|
|
17
|
-
const MAX_HISTORY = 30;
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Records one entry AND paints it live - the single place that touches page.__wgNetworkHistory,
|
|
21
|
-
* so every caller (this file's own listeners, defineApiBlock) stays in sync automatically. History
|
|
22
|
-
* lives on the Playwright `Page` object (Node side), which survives navigation - the panel DOM
|
|
23
|
-
* (page side, inside the shadow root) does not, and gets wiped on every real navigation. Without
|
|
24
|
-
* this, the "network tab" reset to empty on every step that navigated - not what a persistent
|
|
25
|
-
* Network tab is supposed to do.
|
|
26
|
-
*/
|
|
27
|
-
export function recordNetworkEntry(page, entry) {
|
|
28
|
-
page.__wgNetworkHistory = page.__wgNetworkHistory || [];
|
|
29
|
-
page.__wgNetworkHistory.push(entry);
|
|
30
|
-
while (page.__wgNetworkHistory.length > MAX_HISTORY) page.__wgNetworkHistory.shift();
|
|
31
|
-
return page.evaluate(addNetworkEntry, entry).catch(() => {});
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Replays whatever history survived the last navigation back into a freshly (re)installed panel -
|
|
36
|
-
* call this after ensureShadowRoot, every step, same as the rest of the overlay's own per-step
|
|
37
|
-
* resync (banner/todos/device), and BEFORE that step's own network activity can add anything new
|
|
38
|
-
* (installOverlay runs at the very start of a step, so this is always true in practice - no
|
|
39
|
-
* interleaving race between "replay old" and "record new" to reason about). A no-op when there's
|
|
40
|
-
* no history yet, or the panel already shows exactly as many entries as history has (nothing was
|
|
41
|
-
* wiped this step). Otherwise clears and rebuilds from scratch, in order - simpler and more
|
|
42
|
-
* obviously correct than trying to diff/append just the "missing" ones.
|
|
43
|
-
*/
|
|
44
|
-
export async function restoreNetworkHistory(page) {
|
|
45
|
-
const history = page.__wgNetworkHistory;
|
|
46
|
-
if (!history || history.length === 0) return;
|
|
47
|
-
// page.__wgNetworkNeedsRestore is set by installNetworkCapture's own framenavigated listener -
|
|
48
|
-
// skip the page.evaluate() round-trip entirely (an extra one on EVERY step otherwise, since this
|
|
49
|
-
// runs from installOverlay every step) unless a real navigation actually happened since the last
|
|
50
|
-
// successful restore. A real, caught perf regression: this used to always evaluate() a shown-count
|
|
51
|
-
// check first, which measurably slowed down every step of every test that had ever captured any
|
|
52
|
-
// traffic at all, not just ones that navigate.
|
|
53
|
-
if (!page.__wgNetworkNeedsRestore) return;
|
|
54
|
-
page.__wgNetworkNeedsRestore = false;
|
|
55
|
-
await page.evaluate(clearNetworkLog).catch(() => {});
|
|
56
|
-
for (const entry of history) {
|
|
57
|
-
await page.evaluate(addNetworkEntry, entry).catch(() => {});
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export function installNetworkCapture(page) {
|
|
62
|
-
if (page.__wgNetworkCaptureInstalled) return;
|
|
63
|
-
page.__wgNetworkCaptureInstalled = true;
|
|
64
|
-
|
|
65
|
-
// Marks history as needing a replay - see restoreNetworkHistory's own comment. Main frame only;
|
|
66
|
-
// an iframe navigating doesn't wipe the top-level shadow root the panel lives in.
|
|
67
|
-
page.on("framenavigated", (frame) => {
|
|
68
|
-
if (frame === page.mainFrame()) page.__wgNetworkNeedsRestore = true;
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
const startedAt = new Map();
|
|
72
|
-
|
|
73
|
-
page.on("request", (request) => {
|
|
74
|
-
startedAt.set(request, Date.now());
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
page.on("requestfinished", async (request) => {
|
|
78
|
-
try {
|
|
79
|
-
if (!RELEVANT_TYPES.has(request.resourceType())) return;
|
|
80
|
-
const response = await request.response();
|
|
81
|
-
if (!response) return;
|
|
82
|
-
const start = startedAt.get(request);
|
|
83
|
-
startedAt.delete(request);
|
|
84
|
-
let resBody;
|
|
85
|
-
try {
|
|
86
|
-
const contentType = (await response.headerValue("content-type")) || "";
|
|
87
|
-
if (/json|text|xml|html|javascript/.test(contentType)) {
|
|
88
|
-
const buf = await response.body();
|
|
89
|
-
if (buf.length <= MAX_BODY_BYTES) resBody = buf.toString("utf8");
|
|
90
|
-
}
|
|
91
|
-
} catch {
|
|
92
|
-
/* body already consumed / redirected away / not available - best-effort only */
|
|
93
|
-
}
|
|
94
|
-
const [reqHeaders, resHeaders] = await Promise.all([
|
|
95
|
-
request.allHeaders().catch(() => undefined),
|
|
96
|
-
response.allHeaders().catch(() => undefined),
|
|
97
|
-
]);
|
|
98
|
-
await recordNetworkEntry(page, {
|
|
99
|
-
method: request.method(),
|
|
100
|
-
url: request.url(),
|
|
101
|
-
status: response.status(),
|
|
102
|
-
ok: response.ok(),
|
|
103
|
-
ms: start !== undefined ? Date.now() - start : undefined,
|
|
104
|
-
reqHeaders,
|
|
105
|
-
resHeaders,
|
|
106
|
-
reqBody: request.postData() || undefined,
|
|
107
|
-
resBody,
|
|
108
|
-
});
|
|
109
|
-
} catch {
|
|
110
|
-
/* a capture failure must never break the actual run it's observing */
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
page.on("requestfailed", (request) => {
|
|
115
|
-
startedAt.delete(request);
|
|
116
|
-
if (!RELEVANT_TYPES.has(request.resourceType())) return;
|
|
117
|
-
recordNetworkEntry(page, {
|
|
118
|
-
method: request.method(),
|
|
119
|
-
url: request.url(),
|
|
120
|
-
status: 0,
|
|
121
|
-
ok: false,
|
|
122
|
-
reqBody: request.postData() || undefined,
|
|
123
|
-
resBody: request.failure() ? request.failure().errorText : undefined,
|
|
124
|
-
});
|
|
125
|
-
});
|
|
126
|
-
}
|