waygraph 0.13.7 → 0.15.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 +970 -232
- package/assets/stubs/stub.mp4 +0 -0
- package/assets/stubs/stub.pdf +32 -0
- package/assets/stubs/stub.png +0 -0
- package/dist/agent-dive.d.ts +9 -0
- package/dist/agent-dive.js +32 -0
- package/dist/auto-explore-run.d.ts +20 -2
- package/dist/auto-explore-run.js +9 -8
- package/dist/auto-explore.js +22 -2
- package/dist/auto-session-ipc.d.ts +123 -0
- package/dist/auto-session-ipc.js +381 -0
- package/dist/auto-session.d.ts +342 -0
- package/dist/auto-session.js +760 -0
- package/dist/cli.js +450 -51
- package/dist/engine.d.ts +201 -1
- package/dist/engine.js +312 -2
- package/dist/graph.d.ts +18 -0
- package/dist/graph.js +65 -2
- package/dist/highlights.d.ts +20 -1
- package/dist/highlights.js +60 -0
- package/dist/index.d.ts +8 -4
- package/dist/index.js +5 -3
- package/dist/map-check.d.ts +18 -0
- package/dist/map-check.js +140 -0
- package/dist/pilot-overlay.d.ts +88 -0
- package/dist/pilot-overlay.js +363 -0
- package/dist/pilot.d.ts +49 -0
- package/dist/pilot.js +53 -0
- package/dist/trait.d.ts +22 -0
- package/dist/trait.js +60 -3
- package/dist/types.d.ts +21 -1
- package/dist/types.js +17 -1
- package/examples/routed-demo/.waygraph-auto/4d4902b7.log +0 -0
- package/examples/routed-demo/.waygraph-auto/51ef462e.log +0 -0
- package/examples/routed-demo/.waygraph-auto/71527ad9.log +0 -0
- package/examples/routed-demo/.waygraph-auto/ca16778e.log +0 -0
- package/examples/routed-demo/package.json +26 -0
- package/examples/routed-demo/playwright.config.ts +20 -0
- package/examples/routed-demo/scripts/fixture-server.mjs +37 -0
- package/examples/routed-demo/scripts/with-fixture.mjs +70 -0
- package/examples/routed-demo/src/flows/routed-demo-map.flow.ts +39 -0
- package/examples/routed-demo/src/flows/routed-demo.flow.ts +12 -0
- package/examples/routed-demo/src/map/(app_base)/dashboard/_methods/click-widget.block.ts +23 -0
- package/examples/routed-demo/src/map/(app_base)/dashboard/_nav.block.ts +18 -0
- package/examples/routed-demo/src/map/(app_base)/dashboard/_page.block.ts +22 -0
- package/examples/routed-demo/src/map/(app_base)/dashboard/_sel.ts +10 -0
- package/examples/routed-demo/src/map/(external)/docs/_nav.block.ts +21 -0
- package/examples/routed-demo/src/map/(external)/docs/_page.block.ts +15 -0
- package/examples/routed-demo/src/map/(external)/docs/_sel.ts +7 -0
- package/examples/routed-demo/src/pages/dashboard.html +10 -0
- package/examples/routed-demo/src/pages/docs.html +8 -0
- package/examples/routed-demo/src/states/routed-demo.states.ts +10 -0
- package/examples/routed-demo/test-results/.last-run.json +4 -0
- package/examples/routed-demo/tests/routed-demo-map.spec.ts +17 -0
- package/examples/routed-demo/tests/routed-demo.spec.ts +75 -0
- package/examples/routed-demo/tsconfig.json +18 -0
- package/examples/routed-demo-consumer/package.json +18 -0
- package/examples/saucedemo/.waygraph-auto/00d5336e.log +0 -0
- package/examples/saucedemo/.waygraph-auto/010dd92b.log +0 -0
- package/examples/saucedemo/.waygraph-auto/011ad671.log +0 -0
- package/examples/saucedemo/.waygraph-auto/01b45645.log +0 -0
- package/examples/saucedemo/.waygraph-auto/03764153.log +0 -0
- package/examples/saucedemo/.waygraph-auto/0593587e.log +0 -0
- package/examples/saucedemo/.waygraph-auto/06d12823.log +0 -0
- package/examples/saucedemo/.waygraph-auto/083cc5b9.log +0 -0
- package/examples/saucedemo/.waygraph-auto/0b1f5b26.json +8 -0
- package/examples/saucedemo/.waygraph-auto/0c00f25f.log +0 -0
- package/examples/saucedemo/.waygraph-auto/0e480591.log +0 -0
- package/examples/saucedemo/.waygraph-auto/104751ef.log +0 -0
- package/examples/saucedemo/.waygraph-auto/110958b8.log +0 -0
- package/examples/saucedemo/.waygraph-auto/138107c1.log +0 -0
- package/examples/saucedemo/.waygraph-auto/159d541b.log +0 -0
- package/examples/saucedemo/.waygraph-auto/16aa2c01.log +0 -0
- package/examples/saucedemo/.waygraph-auto/16c35dd5.log +0 -0
- package/examples/saucedemo/.waygraph-auto/1706547d.log +0 -0
- package/examples/saucedemo/.waygraph-auto/17537e42.log +0 -0
- package/examples/saucedemo/.waygraph-auto/175655f7.log +0 -0
- package/examples/saucedemo/.waygraph-auto/17ede493.log +0 -0
- package/examples/saucedemo/.waygraph-auto/1fe2414f.log +0 -0
- package/examples/saucedemo/.waygraph-auto/1fe2e3b8.log +0 -0
- package/examples/saucedemo/.waygraph-auto/2219f00b.log +0 -0
- package/examples/saucedemo/.waygraph-auto/23e62571.log +0 -0
- package/examples/saucedemo/.waygraph-auto/25f68ada.log +0 -0
- package/examples/saucedemo/.waygraph-auto/26ca9cd8.log +0 -0
- package/examples/saucedemo/.waygraph-auto/2bb6c4e8.log +0 -0
- package/examples/saucedemo/.waygraph-auto/2d425004.log +0 -0
- package/examples/saucedemo/.waygraph-auto/2f5b3ea6.log +0 -0
- package/examples/saucedemo/.waygraph-auto/31bb303d.log +0 -0
- package/examples/saucedemo/.waygraph-auto/31f2042f.log +0 -0
- package/examples/saucedemo/.waygraph-auto/36551ec1.log +0 -0
- package/examples/saucedemo/.waygraph-auto/36a1c274.log +0 -0
- package/examples/saucedemo/.waygraph-auto/381aa338.log +0 -0
- package/examples/saucedemo/.waygraph-auto/3882bce1.log +0 -0
- package/examples/saucedemo/.waygraph-auto/38acd1dc.log +0 -0
- package/examples/saucedemo/.waygraph-auto/3b8b77b9.log +0 -0
- package/examples/saucedemo/.waygraph-auto/4028d2a2.log +0 -0
- package/examples/saucedemo/.waygraph-auto/4168b208.log +0 -0
- package/examples/saucedemo/.waygraph-auto/42cc9113.log +0 -0
- package/examples/saucedemo/.waygraph-auto/439d30aa.log +0 -0
- package/examples/saucedemo/.waygraph-auto/43ab66ce.log +0 -0
- package/examples/saucedemo/.waygraph-auto/43f66838.log +0 -0
- package/examples/saucedemo/.waygraph-auto/442171d4.log +0 -0
- package/examples/saucedemo/.waygraph-auto/453b1ce1.log +0 -0
- package/examples/saucedemo/.waygraph-auto/457322bd.log +0 -0
- package/examples/saucedemo/.waygraph-auto/46197027.log +0 -0
- package/examples/saucedemo/.waygraph-auto/46889468.log +0 -0
- package/examples/saucedemo/.waygraph-auto/4890da1c.log +0 -0
- package/examples/saucedemo/.waygraph-auto/4893a63b.log +0 -0
- package/examples/saucedemo/.waygraph-auto/4a85f496.log +0 -0
- package/examples/saucedemo/.waygraph-auto/4af71440.log +0 -0
- package/examples/saucedemo/.waygraph-auto/4f7496d1.log +0 -0
- package/examples/saucedemo/.waygraph-auto/50e8baaa.log +0 -0
- package/examples/saucedemo/.waygraph-auto/52b3a455.log +0 -0
- package/examples/saucedemo/.waygraph-auto/532dd9b8.log +0 -0
- package/examples/saucedemo/.waygraph-auto/5391ce40.log +0 -0
- package/examples/saucedemo/.waygraph-auto/57dbddb3.log +0 -0
- package/examples/saucedemo/.waygraph-auto/5897f501.log +0 -0
- package/examples/saucedemo/.waygraph-auto/59c0b57d.log +0 -0
- package/examples/saucedemo/.waygraph-auto/5b511794.log +0 -0
- package/examples/saucedemo/.waygraph-auto/5c0eef7f.log +0 -0
- package/examples/saucedemo/.waygraph-auto/5c47910f.log +0 -0
- package/examples/saucedemo/.waygraph-auto/5d60da77.log +0 -0
- package/examples/saucedemo/.waygraph-auto/5eda8273.log +0 -0
- package/examples/saucedemo/.waygraph-auto/5fc3a33b.log +0 -0
- package/examples/saucedemo/.waygraph-auto/61b6546d.log +0 -0
- package/examples/saucedemo/.waygraph-auto/621518ad.log +0 -0
- package/examples/saucedemo/.waygraph-auto/632b7118.log +0 -0
- package/examples/saucedemo/.waygraph-auto/64314c2b.log +0 -0
- package/examples/saucedemo/.waygraph-auto/650ed066.log +0 -0
- package/examples/saucedemo/.waygraph-auto/66516213.log +0 -0
- package/examples/saucedemo/.waygraph-auto/66c17079.log +0 -0
- package/examples/saucedemo/.waygraph-auto/69bf0b80.log +0 -0
- package/examples/saucedemo/.waygraph-auto/69c2347a.log +0 -0
- package/examples/saucedemo/.waygraph-auto/6d22bdb0.log +0 -0
- package/examples/saucedemo/.waygraph-auto/6d9aaad3.log +0 -0
- package/examples/saucedemo/.waygraph-auto/7103bebb.log +0 -0
- package/examples/saucedemo/.waygraph-auto/740c9faa.log +0 -0
- package/examples/saucedemo/.waygraph-auto/74872fc5.log +0 -0
- package/examples/saucedemo/.waygraph-auto/75846ca9.log +0 -0
- package/examples/saucedemo/.waygraph-auto/7626c85b.log +0 -0
- package/examples/saucedemo/.waygraph-auto/76308eec.log +0 -0
- package/examples/saucedemo/.waygraph-auto/76c1650e.log +0 -0
- package/examples/saucedemo/.waygraph-auto/7861f38f.log +0 -0
- package/examples/saucedemo/.waygraph-auto/78b21219.log +0 -0
- package/examples/saucedemo/.waygraph-auto/7af224ed.log +0 -0
- package/examples/saucedemo/.waygraph-auto/7c3be585.log +0 -0
- package/examples/saucedemo/.waygraph-auto/7ed55a2c.log +0 -0
- package/examples/saucedemo/.waygraph-auto/80086ba2.log +0 -0
- package/examples/saucedemo/.waygraph-auto/80206369.log +0 -0
- package/examples/saucedemo/.waygraph-auto/847f1092.log +0 -0
- package/examples/saucedemo/.waygraph-auto/84d6d293.log +0 -0
- package/examples/saucedemo/.waygraph-auto/8581abfa.log +0 -0
- package/examples/saucedemo/.waygraph-auto/87b7e0fd.log +0 -0
- package/examples/saucedemo/.waygraph-auto/87c79256.log +0 -0
- package/examples/saucedemo/.waygraph-auto/88af2495.log +0 -0
- package/examples/saucedemo/.waygraph-auto/8a3eb088.log +0 -0
- package/examples/saucedemo/.waygraph-auto/8c04a403.log +0 -0
- package/examples/saucedemo/.waygraph-auto/8c9ab09e.log +0 -0
- package/examples/saucedemo/.waygraph-auto/8cc5db51.log +0 -0
- package/examples/saucedemo/.waygraph-auto/8ea3a69c.log +0 -0
- package/examples/saucedemo/.waygraph-auto/9150f913.log +0 -0
- package/examples/saucedemo/.waygraph-auto/929a4313.log +0 -0
- package/examples/saucedemo/.waygraph-auto/95a599e4.log +0 -0
- package/examples/saucedemo/.waygraph-auto/96c45350.log +0 -0
- package/examples/saucedemo/.waygraph-auto/986030e6.log +0 -0
- package/examples/saucedemo/.waygraph-auto/99787abb.log +0 -0
- package/examples/saucedemo/.waygraph-auto/99ddb62c.log +0 -0
- package/examples/saucedemo/.waygraph-auto/a2dd30dd.log +0 -0
- package/examples/saucedemo/.waygraph-auto/a63a2d20.log +0 -0
- package/examples/saucedemo/.waygraph-auto/a78befb7.log +0 -0
- package/examples/saucedemo/.waygraph-auto/a84d9b79.log +0 -0
- package/examples/saucedemo/.waygraph-auto/a87bb3ee.log +0 -0
- package/examples/saucedemo/.waygraph-auto/a9270890.log +0 -0
- package/examples/saucedemo/.waygraph-auto/aa440153.log +0 -0
- package/examples/saucedemo/.waygraph-auto/ab7561e0.log +0 -0
- package/examples/saucedemo/.waygraph-auto/ac19ae60.log +0 -0
- package/examples/saucedemo/.waygraph-auto/ae21ad8e.log +0 -0
- package/examples/saucedemo/.waygraph-auto/af09042f.log +0 -0
- package/examples/saucedemo/.waygraph-auto/b1684126.log +0 -0
- package/examples/saucedemo/.waygraph-auto/b21e9d12.log +0 -0
- package/examples/saucedemo/.waygraph-auto/b5a838be.log +0 -0
- package/examples/saucedemo/.waygraph-auto/b603549d.log +0 -0
- package/examples/saucedemo/.waygraph-auto/b81e074f.log +0 -0
- package/examples/saucedemo/.waygraph-auto/b83e6259.log +0 -0
- package/examples/saucedemo/.waygraph-auto/b9cb2796.log +0 -0
- package/examples/saucedemo/.waygraph-auto/ba58abb7.log +0 -0
- package/examples/saucedemo/.waygraph-auto/bb0a0018.log +0 -0
- package/examples/saucedemo/.waygraph-auto/bb9fd384.log +0 -0
- package/examples/saucedemo/.waygraph-auto/bc0bdd0e.log +0 -0
- package/examples/saucedemo/.waygraph-auto/bc7d4a83.log +0 -0
- package/examples/saucedemo/.waygraph-auto/bd8e082a.log +0 -0
- package/examples/saucedemo/.waygraph-auto/bea0c93e.log +0 -0
- package/examples/saucedemo/.waygraph-auto/bf35201a.log +0 -0
- package/examples/saucedemo/.waygraph-auto/bffa3a7a.log +0 -0
- package/examples/saucedemo/.waygraph-auto/c02ea583.log +0 -0
- package/examples/saucedemo/.waygraph-auto/c2caf0a8.log +0 -0
- package/examples/saucedemo/.waygraph-auto/c3bdc714.log +0 -0
- package/examples/saucedemo/.waygraph-auto/c4afb8bc.log +0 -0
- package/examples/saucedemo/.waygraph-auto/c916a654.log +0 -0
- package/examples/saucedemo/.waygraph-auto/c9b8d69e.log +0 -0
- package/examples/saucedemo/.waygraph-auto/cd68bbc4.log +0 -0
- package/examples/saucedemo/.waygraph-auto/cdc6db50.log +0 -0
- package/examples/saucedemo/.waygraph-auto/d01906a7.log +0 -0
- package/examples/saucedemo/.waygraph-auto/d02e5e7e.log +0 -0
- package/examples/saucedemo/.waygraph-auto/d09aff71.log +0 -0
- package/examples/saucedemo/.waygraph-auto/d0e41396.log +0 -0
- package/examples/saucedemo/.waygraph-auto/d1370d76.log +0 -0
- package/examples/saucedemo/.waygraph-auto/d3714ae4.log +0 -0
- package/examples/saucedemo/.waygraph-auto/d9e5f8a4.log +0 -0
- package/examples/saucedemo/.waygraph-auto/da0685dc.log +0 -0
- package/examples/saucedemo/.waygraph-auto/da894ad8.log +0 -0
- package/examples/saucedemo/.waygraph-auto/daa2f922.log +0 -0
- package/examples/saucedemo/.waygraph-auto/daefb614.log +0 -0
- package/examples/saucedemo/.waygraph-auto/db97e833.log +0 -0
- package/examples/saucedemo/.waygraph-auto/dec3076e.log +0 -0
- package/examples/saucedemo/.waygraph-auto/e101d19a.log +0 -0
- package/examples/saucedemo/.waygraph-auto/e1973991.log +0 -0
- package/examples/saucedemo/.waygraph-auto/e207c989.log +0 -0
- package/examples/saucedemo/.waygraph-auto/e633e545.log +0 -0
- package/examples/saucedemo/.waygraph-auto/e69aec68.log +0 -0
- package/examples/saucedemo/.waygraph-auto/e70e2d06.log +0 -0
- package/examples/saucedemo/.waygraph-auto/e8306a4b.log +0 -0
- package/examples/saucedemo/.waygraph-auto/ebad3410.log +0 -0
- package/examples/saucedemo/.waygraph-auto/ec88b3ef.log +0 -0
- package/examples/saucedemo/.waygraph-auto/ecbb0966.log +0 -0
- package/examples/saucedemo/.waygraph-auto/ecdee753.log +0 -0
- package/examples/saucedemo/.waygraph-auto/ed888783.log +0 -0
- package/examples/saucedemo/.waygraph-auto/ed931dac.log +0 -0
- package/examples/saucedemo/.waygraph-auto/ef655a3f.log +0 -0
- package/examples/saucedemo/.waygraph-auto/f34c9a26.log +0 -0
- package/examples/saucedemo/.waygraph-auto/f3c29b21.log +0 -0
- package/examples/saucedemo/.waygraph-auto/f53f7cfc.log +0 -0
- package/examples/saucedemo/.waygraph-auto/f5525d53.log +0 -0
- package/examples/saucedemo/.waygraph-auto/f5ad5830.log +0 -0
- package/examples/saucedemo/.waygraph-auto/f90035b3.log +0 -0
- package/examples/saucedemo/.waygraph-auto/fa687bc2.log +0 -0
- package/examples/saucedemo/.waygraph-auto/faed36dd.log +0 -0
- package/examples/saucedemo/.waygraph-auto/fb66fba0.log +0 -0
- package/examples/saucedemo/.waygraph-auto/fc48fd76.log +0 -0
- package/examples/saucedemo/docs/CONVENTION.md +25 -5
- package/examples/saucedemo/docs/HELPERS.md +15 -4
- package/examples/saucedemo/scripts/capture-wrong-login.mjs +8 -2
- package/examples/saucedemo/scripts/prove-wrong-login-runtime.mjs +8 -2
- package/examples/saucedemo/src/blocks/SITE-MAP.md +14 -3
- package/examples/saucedemo/src/blocks/saucedemo-web/NAV.md +15 -1
- package/examples/saucedemo/src/blocks/saucedemo-web/cart/NAV.md +1 -0
- package/examples/saucedemo/src/blocks/saucedemo-web/cart/cart.sel.ts +9 -0
- package/examples/saucedemo/src/blocks/saucedemo-web/cart/nav-cart.block.ts +3 -2
- package/examples/saucedemo/src/blocks/saucedemo-web/cart/nav-checkout-info.block.ts +2 -1
- package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/NAV.md +6 -1
- package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/checkout-info.sel.ts +11 -0
- package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/fill-first-name.method.block.ts +22 -0
- package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/fill-last-name.method.block.ts +21 -0
- package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/fill-postal-code.method.block.ts +21 -0
- package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/submit-checkout-info.method.block.ts +6 -7
- package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-two/NAV.md +2 -0
- package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-two/methods/checkout-overview.sel.ts +9 -0
- package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.ts +7 -6
- package/examples/saucedemo/src/blocks/saucedemo-web/ff-owner-auth.block.ts +7 -2
- package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/NAV.md +1 -0
- package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/item-detail.sel.ts +9 -0
- package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/nav-back-to-inventory.block.ts +2 -1
- package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/nav-back-to-products.block.ts +2 -1
- package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/nav-continue-shopping.block.ts +2 -1
- package/examples/saucedemo/src/blocks/saucedemo-web/methods/fill-password.method.block.ts +51 -0
- package/examples/saucedemo/src/blocks/saucedemo-web/methods/fill-username.method.block.ts +69 -0
- package/examples/saucedemo/src/blocks/saucedemo-web/methods/login.sel.ts +13 -0
- package/examples/saucedemo/src/blocks/saucedemo-web/methods/submit-login-for-flow.ts +4 -4
- package/examples/saucedemo/src/blocks/saucedemo-web/methods/submit-login.method.block.ts +13 -51
- package/examples/saucedemo/src/blocks/saucedemo-web/methods/submit-logout.method.block.ts +4 -3
- package/examples/saucedemo/src/blocks/saucedemo-web/nav-login.block.ts +14 -6
- package/examples/saucedemo/src/flows/checkout-then-browse-again.flow.ts +15 -0
- package/examples/saucedemo/src/flows/checkout.flow.ts +20 -2
- package/examples/saucedemo/src/flows/device-showcase.flow.ts +4 -0
- package/examples/saucedemo/src/flows/login.flow.ts +3 -1
- package/examples/saucedemo/src/flows/shop.flow.ts +6 -0
- package/examples/saucedemo/src/flows/smoke.flow.ts +13 -7
- package/examples/saucedemo/src/flows/stub-on-error.flow.ts +4 -2
- package/examples/saucedemo/src/flows/viewer-blocked.flow.ts +6 -2
- package/examples/saucedemo/tests/flow-block-verify.spec.ts +3 -3
- package/examples/saucedemo/tests/submit-login-branch.spec.ts +5 -3
- package/package.json +2 -1
- package/templates/agents/waygraph-author.agent.md +43 -5
- package/templates/agents/waygraph-planner.agent.md +33 -2
- package/templates/quickstart/src/blocks/saucedemo-web/NAV.md +15 -1
- package/templates/quickstart/src/blocks/saucedemo-web/cart/NAV.md +1 -0
- package/templates/quickstart/src/blocks/saucedemo-web/cart/cart.sel.ts +9 -0
- package/templates/quickstart/src/blocks/saucedemo-web/cart/nav-cart.block.ts +19 -15
- package/templates/quickstart/src/blocks/saucedemo-web/cart/nav-checkout-info.block.ts +2 -1
- package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/NAV.md +6 -1
- package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/checkout-info.sel.ts +11 -0
- package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/fill-first-name.method.block.ts +22 -0
- package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/fill-last-name.method.block.ts +21 -0
- package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/fill-postal-code.method.block.ts +21 -0
- package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/submit-checkout-info.method.block.ts +6 -7
- package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-two/NAV.md +2 -0
- package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-two/methods/checkout-overview.sel.ts +9 -0
- package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.ts +7 -6
- package/templates/quickstart/src/blocks/saucedemo-web/ff-owner-auth.block.ts +7 -2
- package/templates/quickstart/src/blocks/saucedemo-web/inventory/methods/add-to-cart.effect.block.ts +24 -16
- 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.md +1 -0
- package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/item-detail.sel.ts +9 -0
- package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/nav-back-to-inventory.block.ts +2 -1
- package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/nav-back-to-products.block.ts +2 -1
- package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/nav-continue-shopping.block.ts +2 -1
- package/templates/quickstart/src/blocks/saucedemo-web/methods/fill-password.method.block.ts +51 -0
- package/templates/quickstart/src/blocks/saucedemo-web/methods/fill-username.method.block.ts +69 -0
- package/templates/quickstart/src/blocks/saucedemo-web/methods/login.sel.ts +13 -0
- package/templates/quickstart/src/blocks/saucedemo-web/methods/submit-login-for-flow.ts +4 -4
- package/templates/quickstart/src/blocks/saucedemo-web/methods/submit-login.method.block.ts +35 -63
- package/templates/quickstart/src/blocks/saucedemo-web/methods/submit-logout.method.block.ts +4 -3
- package/templates/quickstart/src/blocks/saucedemo-web/nav-login.block.ts +14 -6
- package/templates/quickstart/src/flows/checkout-then-browse-again.flow.ts +15 -0
- package/templates/quickstart/src/flows/checkout.flow.ts +29 -2
- package/templates/quickstart/src/flows/device-showcase.flow.ts +4 -0
- package/templates/quickstart/src/flows/login.flow.ts +3 -1
- package/templates/quickstart/src/flows/shop.flow.ts +6 -0
- package/templates/quickstart/src/flows/smoke.flow.ts +13 -7
- package/templates/quickstart/src/flows/viewer-blocked.flow.ts +6 -2
- package/templates/quickstart/tests/chain-flow.spec.ts +8 -1
- package/templates/scaffold/STRUCTURE.md +23 -3
- package/templates/scaffold/scripts/fixture-server.mjs +11 -2
- package/templates/scaffold/src/flows/example.flow.ts +8 -6
- package/templates/scaffold/src/flows/mail-verify.flow.ts +85 -0
- package/templates/scaffold/src/flows/shop.flow.ts +23 -6
- package/templates/scaffold/src/map/(app_base)/docs/_nav.block.ts +20 -0
- package/templates/scaffold/src/map/(app_base)/docs/_page.block.ts +15 -0
- package/templates/scaffold/src/map/(app_base)/docs/_sel.ts +7 -0
- package/templates/scaffold/src/map/(app_base)/docs/docs.html +8 -0
- package/templates/scaffold/src/{blocks/demo-web/methods → map/(app_base)/home/_methods}/add-item.effect.block.ts +3 -3
- package/templates/scaffold/src/map/(app_base)/home/_methods/assert-hello.method.block.ts +46 -0
- package/templates/scaffold/src/map/(app_base)/home/_methods/assert-item-added.method.block.ts +38 -0
- package/templates/scaffold/src/{blocks/demo-web/methods → map/(app_base)/home/_methods}/clear-cart.method.block.ts +9 -3
- package/templates/scaffold/src/{blocks/demo-web/methods → map/(app_base)/home/_methods}/remove-item.effect.block.ts +3 -3
- package/templates/scaffold/src/{blocks/demo-web/nav-home.block.ts → map/(app_base)/home/_nav.block.ts} +2 -2
- package/templates/scaffold/src/{blocks/demo-web/home.page.block.ts → map/(app_base)/home/_page.block.ts} +7 -7
- package/templates/scaffold/src/{blocks/demo-web/demo-sel.ts → map/(app_base)/home/_sel.ts} +1 -0
- package/templates/scaffold/src/{blocks/demo-web → map/(app_base)/home}/home.html +4 -0
- package/templates/scaffold/src/map/(app_base)/home/nav-verification-link.block.ts +34 -0
- package/templates/scaffold/src/map/(external)/mailpit/_methods/assert-email-content.method.block.ts +48 -0
- package/templates/scaffold/src/map/(external)/mailpit/_methods/assert-email-received.method.block.ts +49 -0
- package/templates/scaffold/src/map/(external)/mailpit/_methods/extract-email-link.method.block.ts +41 -0
- package/templates/scaffold/src/map/(external)/mailpit/_methods/open-message.method.block.ts +39 -0
- package/templates/scaffold/src/map/(external)/mailpit/_nav.block.ts +20 -0
- package/templates/scaffold/src/map/(external)/mailpit/_page.block.ts +30 -0
- package/templates/scaffold/src/map/(external)/mailpit/_sel.ts +5 -0
- package/templates/scaffold/src/states/demo.mem-keys.ts +25 -1
- package/templates/scaffold/src/states/demo.states.ts +11 -0
- package/templates/scaffold/test-results/.last-run.json +4 -0
- package/templates/scaffold/tests/example.spec.ts +2 -2
- package/templates/scaffold/tests/mail-verify.spec.ts +191 -0
- package/templates/skills/waygraph-blind-pilot.skill.md +61 -0
- package/templates/skills/waygraph-pilot.skill.md +108 -0
- package/templates/quickstart/README-saucedemo-commands.md +0 -72
- package/templates/scaffold/src/blocks/SITE-MAP.md +0 -12
- package/templates/scaffold/src/blocks/demo-web/NAV.md +0 -29
- package/templates/scaffold/src/blocks/demo-web/methods/assert-hello.method.block.ts +0 -50
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineMethodBlock, checkpoint, Trait, type StubCtx } from "waygraph";
|
|
2
2
|
import type { LoginPage, LoginSubmitOutcome } from "../../../states/checkout.states.js";
|
|
3
|
-
import {
|
|
3
|
+
import { LoginSel } from "./login.sel.js";
|
|
4
4
|
|
|
5
5
|
type LoginObserve = "success" | "failure";
|
|
6
6
|
|
|
@@ -9,30 +9,26 @@ type LoginObserve = "success" | "failure";
|
|
|
9
9
|
* Helper: defineMethodBlock
|
|
10
10
|
* Route: saucedemo-web/methods/ (page URL /)
|
|
11
11
|
*
|
|
12
|
-
*
|
|
12
|
+
* Clicks Login only - never page.goto (nav-login Page hub owns that), never
|
|
13
|
+
* fills fields (fill-username.method.block.ts / fill-password.method.block.ts
|
|
14
|
+
* already did that). One Block, one action: submit.
|
|
13
15
|
* Branches: good creds -> LoggedIn; bad/locked -> LoginPage with error banner.
|
|
14
|
-
* stubBefore/stubAfter drive the floating todo dock (Method fill/click advances
|
|
15
|
-
* todoIndex mid-act; stubAfter marks complete / fail).
|
|
16
16
|
*/
|
|
17
|
-
export const
|
|
17
|
+
export const SubmitLoginBlock = defineMethodBlock<LoginPage, LoginSubmitOutcome>({
|
|
18
18
|
name: "submit-login",
|
|
19
|
-
description: "
|
|
20
|
-
requires: [LoginCreds.key],
|
|
19
|
+
description: "Submits the login form; stays on LoginPage when auth fails.",
|
|
21
20
|
instruction: {
|
|
22
|
-
async act(page
|
|
23
|
-
const { username, password } = mem.get(LoginCreds.key);
|
|
24
|
-
await page.locator("#user-name").fill(username);
|
|
25
|
-
await page.locator("#password").fill(password);
|
|
21
|
+
async act(page) {
|
|
26
22
|
// noWaitAfter: observe owns the inventory URL wait. Default click
|
|
27
23
|
// navigation-wait can hang under waygraph auto's demo cursor patch.
|
|
28
|
-
await page.locator(
|
|
24
|
+
await page.locator(LoginSel.loginButton).click({ noWaitAfter: true });
|
|
29
25
|
},
|
|
30
26
|
async observe(page): Promise<LoginObserve> {
|
|
31
27
|
// Race inventory nav vs error banner - locked_out / wrong password show
|
|
32
28
|
// Epic sadface immediately; do not burn the full inventory timeout.
|
|
33
29
|
const inventory = page.waitForURL(/\/inventory\.html/, { timeout: 8_000 }).then(() => "success" as const);
|
|
34
30
|
const errorBanner = page
|
|
35
|
-
.locator(
|
|
31
|
+
.locator(LoginSel.errorBanner)
|
|
36
32
|
.first()
|
|
37
33
|
.waitFor({ state: "visible", timeout: 8_000 })
|
|
38
34
|
.then(() => "failure" as const);
|
|
@@ -46,40 +42,13 @@ export const SubmitLoginActionBlock = defineMethodBlock<LoginPage, LoginSubmitOu
|
|
|
46
42
|
verify: (out) =>
|
|
47
43
|
out.__state === "LoggedIn"
|
|
48
44
|
? [Trait.url({ pathname: "/inventory.html" })]
|
|
49
|
-
: [Trait.visible(
|
|
50
|
-
// Open lifecycle: banner title, todos, Screen Studio camera zoom,
|
|
51
|
-
// sequential highlight queue (appear / dwell / fade), focus + color.
|
|
45
|
+
: [Trait.visible(LoginSel.errorBanner)],
|
|
52
46
|
stubBefore: (ctx: StubCtx) => {
|
|
53
|
-
ctx.title("Signing in · mobile");
|
|
54
|
-
// 0.13.3: mobile portrait + touch; tap Login.
|
|
55
|
-
ctx.device("mobile");
|
|
56
|
-
ctx.portrait();
|
|
57
|
-
ctx.todoId("saucedemo-login");
|
|
58
|
-
ctx.todos([
|
|
59
|
-
{ id: "login-user", text: "Enter username" },
|
|
60
|
-
{ id: "login-pass", text: "Enter password" },
|
|
61
|
-
{ id: "login-submit", text: "Tap Login" },
|
|
62
|
-
]);
|
|
63
|
-
ctx.todoIndex(0);
|
|
64
|
-
ctx.zoom(1.35);
|
|
65
47
|
ctx.highlights({
|
|
66
|
-
username: {
|
|
67
|
-
selector: "#user-name",
|
|
68
|
-
label: "Username",
|
|
69
|
-
focus: true,
|
|
70
|
-
color: "#c9a6ff",
|
|
71
|
-
zoom: 1.4,
|
|
72
|
-
},
|
|
73
|
-
password: {
|
|
74
|
-
selector: "#password",
|
|
75
|
-
label: "Password",
|
|
76
|
-
focus: true,
|
|
77
|
-
color: "#c9a6ff",
|
|
78
|
-
zoom: 1.4,
|
|
79
|
-
},
|
|
80
48
|
submit: {
|
|
81
|
-
selector:
|
|
49
|
+
selector: LoginSel.loginButton,
|
|
82
50
|
label: "Login",
|
|
51
|
+
todo: "login-submit",
|
|
83
52
|
focus: true,
|
|
84
53
|
color: "#86efac",
|
|
85
54
|
zoom: 1.55,
|
|
@@ -89,19 +58,19 @@ export const SubmitLoginActionBlock = defineMethodBlock<LoginPage, LoginSubmitOu
|
|
|
89
58
|
});
|
|
90
59
|
},
|
|
91
60
|
stubAfter: (ctx: StubCtx) => {
|
|
92
|
-
// Fail branch lands on LoginPage with Epic sadface - do not ring the
|
|
93
|
-
// inventory shelf. Success (LoggedIn) hands off to shopFlow.
|
|
94
61
|
if (ctx.out && ctx.out.__state === "LoginPage") {
|
|
95
62
|
ctx.title("Login blocked");
|
|
96
|
-
ctx.
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
63
|
+
ctx.todos(
|
|
64
|
+
"saucedemo",
|
|
65
|
+
[
|
|
66
|
+
{ id: "login-user", text: "Enter username", done: true },
|
|
67
|
+
{ id: "login-pass", text: "Enter password", done: true },
|
|
68
|
+
{ id: "login-submit", text: "Click Login", done: true },
|
|
69
|
+
],
|
|
70
|
+
{ title: "Sign in", style: "checklist" },
|
|
71
|
+
);
|
|
103
72
|
ctx.ring("error", {
|
|
104
|
-
selector:
|
|
73
|
+
selector: LoginSel.errorBanner,
|
|
105
74
|
label: "Login error banner",
|
|
106
75
|
tone: "danger",
|
|
107
76
|
focus: true,
|
|
@@ -111,16 +80,19 @@ export const SubmitLoginActionBlock = defineMethodBlock<LoginPage, LoginSubmitOu
|
|
|
111
80
|
return;
|
|
112
81
|
}
|
|
113
82
|
ctx.banner("Inventory · landscape");
|
|
114
|
-
// Rotate mobile to landscape on the product shelf (toast + lerp).
|
|
115
83
|
ctx.landscape();
|
|
116
|
-
ctx.
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
84
|
+
ctx.todos(
|
|
85
|
+
"saucedemo",
|
|
86
|
+
[
|
|
87
|
+
{ id: "login-user", text: "Enter username", done: true },
|
|
88
|
+
{ id: "login-pass", text: "Enter password", done: true },
|
|
89
|
+
{ id: "login-submit", text: "Tap Login", done: true },
|
|
90
|
+
{ id: "cart-find", text: "Find the product" },
|
|
91
|
+
{ id: "cart-add", text: "Add to cart" },
|
|
92
|
+
{ id: "cart-open", text: "Open cart" },
|
|
93
|
+
],
|
|
94
|
+
{ title: "Device showcase", index: 3 },
|
|
95
|
+
);
|
|
124
96
|
ctx.ring("shelf", {
|
|
125
97
|
selector: ".inventory_list",
|
|
126
98
|
label: "Product shelf",
|
|
@@ -134,7 +106,7 @@ export const SubmitLoginActionBlock = defineMethodBlock<LoginPage, LoginSubmitOu
|
|
|
134
106
|
stubOnError: (ctx: StubCtx) => {
|
|
135
107
|
ctx.title("Login failed");
|
|
136
108
|
ctx.ring("error", {
|
|
137
|
-
selector:
|
|
109
|
+
selector: LoginSel.errorBanner,
|
|
138
110
|
label: "Login error banner",
|
|
139
111
|
tone: "danger",
|
|
140
112
|
focus: true,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { defineMethodBlock, checkpoint, Trait } from "waygraph";
|
|
2
2
|
import type { LoggedIn, LoginPage } from "../../../states/checkout.states.js";
|
|
3
|
+
import { LoginSel } from "./login.sel.js";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Kind: Method
|
|
@@ -13,10 +14,10 @@ export const SubmitLogoutBlock = defineMethodBlock<LoggedIn, LoginPage>({
|
|
|
13
14
|
description: "Opens the burger menu and logs out.",
|
|
14
15
|
instruction: {
|
|
15
16
|
async act(page) {
|
|
16
|
-
await page.locator(
|
|
17
|
-
await page.locator(
|
|
17
|
+
await page.locator(LoginSel.burgerMenuButton).click();
|
|
18
|
+
await page.locator(LoginSel.logoutLink).click();
|
|
18
19
|
},
|
|
19
20
|
resolve: () => checkpoint("LoginPage"),
|
|
20
|
-
verify: [Trait.visible(
|
|
21
|
+
verify: [Trait.visible(LoginSel.loginButton)],
|
|
21
22
|
},
|
|
22
23
|
});
|
|
@@ -1,23 +1,31 @@
|
|
|
1
1
|
import { definePageBlock, Trait } from "waygraph";
|
|
2
2
|
import type { LoginPage } from "../../states/checkout.states.js";
|
|
3
|
-
import {
|
|
3
|
+
import { FillUsernameBlock } from "./methods/fill-username.method.block.js";
|
|
4
|
+
import { FillPasswordBlock } from "./methods/fill-password.method.block.js";
|
|
5
|
+
import { SubmitLoginBlock } from "./methods/submit-login.method.block.js";
|
|
6
|
+
import { LoginSel } from "./methods/login.sel.js";
|
|
4
7
|
|
|
5
8
|
/**
|
|
6
9
|
* Kind: Page
|
|
7
10
|
* Helper: definePageBlock
|
|
8
11
|
* Route: saucedemo-web/ (= /)
|
|
9
12
|
*
|
|
10
|
-
* Login screen hub. Deep-link via url;
|
|
11
|
-
* page
|
|
12
|
-
*
|
|
13
|
+
* Login screen hub. Deep-link via url; fill-username / fill-password /
|
|
14
|
+
* submit-login hang off this page as three atomic Methods - fill-* are
|
|
15
|
+
* self-loops (LoginPage -> LoginPage), submit-login owns the one real
|
|
16
|
+
* transition (LoginPage -> LoggedIn|LoginPage). No single Block both fills
|
|
17
|
+
* and submits. Name stays `nav-login` so existing flows / chain specs keep
|
|
18
|
+
* working.
|
|
13
19
|
*/
|
|
14
20
|
export const NavLoginBlock = definePageBlock<LoginPage>({
|
|
15
21
|
name: "nav-login",
|
|
16
22
|
description: "Goes to the Swag Labs login page.",
|
|
17
23
|
checkpoint: "LoginPage",
|
|
18
24
|
url: "/",
|
|
19
|
-
verify: [Trait.visible(
|
|
25
|
+
verify: [Trait.visible(LoginSel.loginButton)],
|
|
20
26
|
methods: {
|
|
21
|
-
|
|
27
|
+
fillUsername: () => FillUsernameBlock,
|
|
28
|
+
fillPassword: () => FillPasswordBlock,
|
|
29
|
+
submitLogin: () => SubmitLoginBlock,
|
|
22
30
|
},
|
|
23
31
|
});
|
|
@@ -9,10 +9,15 @@ import type {
|
|
|
9
9
|
OrderComplete,
|
|
10
10
|
} from "../states/checkout.states.js";
|
|
11
11
|
import { NavLoginBlock } from "../blocks/saucedemo-web/nav-login.block.js";
|
|
12
|
+
import { FillUsernameBlock } from "../blocks/saucedemo-web/methods/fill-username.method.block.js";
|
|
13
|
+
import { FillPasswordBlock } from "../blocks/saucedemo-web/methods/fill-password.method.block.js";
|
|
12
14
|
import { SubmitLoginForFlow } from "../blocks/saucedemo-web/methods/submit-login-for-flow.js";
|
|
13
15
|
import { AddToCartBlock } from "../blocks/saucedemo-web/inventory/methods/add-to-cart.effect.block.js";
|
|
14
16
|
import { NavCartBlock } from "../blocks/saucedemo-web/cart/nav-cart.block.js";
|
|
15
17
|
import { NavCheckoutInfoBlock } from "../blocks/saucedemo-web/cart/nav-checkout-info.block.js";
|
|
18
|
+
import { FillFirstNameBlock } from "../blocks/saucedemo-web/checkout-step-one/methods/fill-first-name.method.block.js";
|
|
19
|
+
import { FillLastNameBlock } from "../blocks/saucedemo-web/checkout-step-one/methods/fill-last-name.method.block.js";
|
|
20
|
+
import { FillPostalCodeBlock } from "../blocks/saucedemo-web/checkout-step-one/methods/fill-postal-code.method.block.js";
|
|
16
21
|
import { SubmitCheckoutInfoBlock } from "../blocks/saucedemo-web/checkout-step-one/methods/submit-checkout-info.method.block.js";
|
|
17
22
|
import { FinishOrderBlock } from "../blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.js";
|
|
18
23
|
import { NavBackToProductsBlock } from "../blocks/saucedemo-web/inventory-item/nav-back-to-products.block.js";
|
|
@@ -23,21 +28,31 @@ const engine = new Engine({ headless: false, slowMo: 250 });
|
|
|
23
28
|
// (proves OrderComplete -> LoggedIn without a goto teleport).
|
|
24
29
|
export const checkoutThenBrowseAgainFlow = withTitle(
|
|
25
30
|
engine.defineFlow<
|
|
31
|
+
LoginPage,
|
|
32
|
+
LoginPage,
|
|
26
33
|
LoginPage,
|
|
27
34
|
LoggedIn,
|
|
28
35
|
ItemInCart,
|
|
29
36
|
CartPage,
|
|
30
37
|
CheckoutInfoPage,
|
|
38
|
+
CheckoutInfoPage,
|
|
39
|
+
CheckoutInfoPage,
|
|
40
|
+
CheckoutInfoPage,
|
|
31
41
|
CheckoutOverviewPage,
|
|
32
42
|
OrderComplete,
|
|
33
43
|
LoggedIn
|
|
34
44
|
>([
|
|
35
45
|
start,
|
|
36
46
|
NavLoginBlock,
|
|
47
|
+
FillUsernameBlock,
|
|
48
|
+
FillPasswordBlock,
|
|
37
49
|
SubmitLoginForFlow,
|
|
38
50
|
AddToCartBlock,
|
|
39
51
|
NavCartBlock,
|
|
40
52
|
NavCheckoutInfoBlock,
|
|
53
|
+
FillFirstNameBlock,
|
|
54
|
+
FillLastNameBlock,
|
|
55
|
+
FillPostalCodeBlock,
|
|
41
56
|
SubmitCheckoutInfoBlock,
|
|
42
57
|
FinishOrderBlock,
|
|
43
58
|
NavBackToProductsBlock,
|
|
@@ -11,12 +11,23 @@ import { FfOwnerAuthBlock } from "../blocks/saucedemo-web/ff-owner-auth.block.js
|
|
|
11
11
|
import { AddToCartBlock } from "../blocks/saucedemo-web/inventory/methods/add-to-cart.effect.block.js";
|
|
12
12
|
import { NavCartBlock } from "../blocks/saucedemo-web/cart/nav-cart.block.js";
|
|
13
13
|
import { NavCheckoutInfoBlock } from "../blocks/saucedemo-web/cart/nav-checkout-info.block.js";
|
|
14
|
+
import { FillFirstNameBlock } from "../blocks/saucedemo-web/checkout-step-one/methods/fill-first-name.method.block.js";
|
|
15
|
+
import { FillLastNameBlock } from "../blocks/saucedemo-web/checkout-step-one/methods/fill-last-name.method.block.js";
|
|
16
|
+
import { FillPostalCodeBlock } from "../blocks/saucedemo-web/checkout-step-one/methods/fill-postal-code.method.block.js";
|
|
14
17
|
import { SubmitCheckoutInfoBlock } from "../blocks/saucedemo-web/checkout-step-one/methods/submit-checkout-info.method.block.js";
|
|
15
18
|
import { FinishOrderBlock } from "../blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.js";
|
|
16
19
|
|
|
17
20
|
const engine = new Engine({ headless: false, slowMo: 250 });
|
|
18
21
|
|
|
19
|
-
//
|
|
22
|
+
// Atomic nav/action per real URL after auth - the shape `waygraph auto` discovers.
|
|
23
|
+
// Auth is one FFCompose step (ff-owner-auth) so demo pacing skips login yap;
|
|
24
|
+
// use --ff-expand (or loginFlow) when you need per-step auth narration.
|
|
25
|
+
//
|
|
26
|
+
// Demo narration showcase (waygraph 0.11+ / FFCompose 0.12):
|
|
27
|
+
// - FF opaque: one gate for auth; stubs on interesting post-login blocks
|
|
28
|
+
// - Block stubs: add-to-cart / finish-order stubAfter
|
|
29
|
+
// - Flow fixtures: ticket-style captions
|
|
30
|
+
// - Slides on finish-order: multi-step yap with Next between slides
|
|
20
31
|
export const checkoutFlow = withHighlightFixtures(
|
|
21
32
|
withTitle(
|
|
22
33
|
engine.defineFlow<
|
|
@@ -24,6 +35,9 @@ export const checkoutFlow = withHighlightFixtures(
|
|
|
24
35
|
ItemInCart,
|
|
25
36
|
CartPage,
|
|
26
37
|
CheckoutInfoPage,
|
|
38
|
+
CheckoutInfoPage,
|
|
39
|
+
CheckoutInfoPage,
|
|
40
|
+
CheckoutInfoPage,
|
|
27
41
|
CheckoutOverviewPage,
|
|
28
42
|
OrderComplete
|
|
29
43
|
>([
|
|
@@ -32,6 +46,9 @@ export const checkoutFlow = withHighlightFixtures(
|
|
|
32
46
|
AddToCartBlock,
|
|
33
47
|
NavCartBlock,
|
|
34
48
|
NavCheckoutInfoBlock,
|
|
49
|
+
FillFirstNameBlock,
|
|
50
|
+
FillLastNameBlock,
|
|
51
|
+
FillPostalCodeBlock,
|
|
35
52
|
SubmitCheckoutInfoBlock,
|
|
36
53
|
FinishOrderBlock,
|
|
37
54
|
end,
|
|
@@ -49,7 +66,9 @@ export const checkoutFlow = withHighlightFixtures(
|
|
|
49
66
|
},
|
|
50
67
|
},
|
|
51
68
|
},
|
|
52
|
-
|
|
69
|
+
// Kept for --ff-expand (inners become separate steps again: nav-login,
|
|
70
|
+
// fill-username, fill-password, submit-login).
|
|
71
|
+
"fill-username": {
|
|
53
72
|
stubBefore: {
|
|
54
73
|
username: {
|
|
55
74
|
label: "Demo user",
|
|
@@ -57,7 +76,15 @@ export const checkoutFlow = withHighlightFixtures(
|
|
|
57
76
|
tag: "AC",
|
|
58
77
|
duration: true,
|
|
59
78
|
},
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
"fill-password": {
|
|
82
|
+
stubBefore: {
|
|
60
83
|
password: { label: "Password", detail: "Filled from Mem credentials.", duration: 1500 },
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
"submit-login": {
|
|
87
|
+
stubBefore: {
|
|
61
88
|
submit: { label: "Sign in", tag: "GATE", duration: true, fastMode: 500 },
|
|
62
89
|
},
|
|
63
90
|
},
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Engine, start, end, withTitle } from "waygraph";
|
|
2
2
|
import { NavLoginBlock } from "../blocks/saucedemo-web/nav-login.block.js";
|
|
3
|
+
import { FillUsernameBlock } from "../blocks/saucedemo-web/methods/fill-username.method.block.js";
|
|
4
|
+
import { FillPasswordBlock } from "../blocks/saucedemo-web/methods/fill-password.method.block.js";
|
|
3
5
|
import { SubmitLoginForFlow } from "../blocks/saucedemo-web/methods/submit-login-for-flow.js";
|
|
4
6
|
import { AddToCartBlock } from "../blocks/saucedemo-web/inventory/methods/add-to-cart.effect.block.js";
|
|
5
7
|
import { NavCartBlock } from "../blocks/saucedemo-web/cart/nav-cart.block.js";
|
|
@@ -19,6 +21,8 @@ export const deviceShowcaseFlow = withTitle(
|
|
|
19
21
|
engine.defineFlow([
|
|
20
22
|
start,
|
|
21
23
|
NavLoginBlock,
|
|
24
|
+
FillUsernameBlock,
|
|
25
|
+
FillPasswordBlock,
|
|
22
26
|
SubmitLoginForFlow,
|
|
23
27
|
AddToCartBlock,
|
|
24
28
|
NavCartBlock,
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Engine, start, end, withTitle } from "waygraph";
|
|
2
2
|
import { NavLoginBlock } from "../blocks/saucedemo-web/nav-login.block.js";
|
|
3
|
+
import { FillUsernameBlock } from "../blocks/saucedemo-web/methods/fill-username.method.block.js";
|
|
4
|
+
import { FillPasswordBlock } from "../blocks/saucedemo-web/methods/fill-password.method.block.js";
|
|
3
5
|
import { SubmitLoginForFlow } from "../blocks/saucedemo-web/methods/submit-login-for-flow.js";
|
|
4
6
|
|
|
5
7
|
const engine = new Engine();
|
|
@@ -7,6 +9,6 @@ const engine = new Engine();
|
|
|
7
9
|
// The step-mode overlay prepends "Episode N: " itself - the title here is
|
|
8
10
|
// just the label, not the full heading.
|
|
9
11
|
export const loginFlow = withTitle(
|
|
10
|
-
engine.defineFlow([start, NavLoginBlock, SubmitLoginForFlow, end]),
|
|
12
|
+
engine.defineFlow([start, NavLoginBlock, FillUsernameBlock, FillPasswordBlock, SubmitLoginForFlow, end]),
|
|
11
13
|
"Sign In",
|
|
12
14
|
);
|
|
@@ -2,6 +2,9 @@ import { Engine, start, end, withTitle } from "waygraph";
|
|
|
2
2
|
import { AddToCartBlock } from "../blocks/saucedemo-web/inventory/methods/add-to-cart.effect.block.js";
|
|
3
3
|
import { NavCartBlock } from "../blocks/saucedemo-web/cart/nav-cart.block.js";
|
|
4
4
|
import { NavCheckoutInfoBlock } from "../blocks/saucedemo-web/cart/nav-checkout-info.block.js";
|
|
5
|
+
import { FillFirstNameBlock } from "../blocks/saucedemo-web/checkout-step-one/methods/fill-first-name.method.block.js";
|
|
6
|
+
import { FillLastNameBlock } from "../blocks/saucedemo-web/checkout-step-one/methods/fill-last-name.method.block.js";
|
|
7
|
+
import { FillPostalCodeBlock } from "../blocks/saucedemo-web/checkout-step-one/methods/fill-postal-code.method.block.js";
|
|
5
8
|
import { SubmitCheckoutInfoBlock } from "../blocks/saucedemo-web/checkout-step-one/methods/submit-checkout-info.method.block.js";
|
|
6
9
|
import { FinishOrderBlock } from "../blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.js";
|
|
7
10
|
|
|
@@ -15,6 +18,9 @@ export const shopFlow = withTitle(
|
|
|
15
18
|
AddToCartBlock,
|
|
16
19
|
NavCartBlock,
|
|
17
20
|
NavCheckoutInfoBlock,
|
|
21
|
+
FillFirstNameBlock,
|
|
22
|
+
FillLastNameBlock,
|
|
23
|
+
FillPostalCodeBlock,
|
|
18
24
|
SubmitCheckoutInfoBlock,
|
|
19
25
|
FinishOrderBlock,
|
|
20
26
|
end,
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { Engine, start, end } from "waygraph";
|
|
2
2
|
import type { LoginPage, LoggedIn, ItemInCart } from "../states/checkout.states.js";
|
|
3
3
|
import { NavLoginBlock } from "../blocks/saucedemo-web/nav-login.block.js";
|
|
4
|
+
import { FillUsernameBlock } from "../blocks/saucedemo-web/methods/fill-username.method.block.js";
|
|
5
|
+
import { FillPasswordBlock } from "../blocks/saucedemo-web/methods/fill-password.method.block.js";
|
|
4
6
|
import { SubmitLoginForFlow } from "../blocks/saucedemo-web/methods/submit-login-for-flow.js";
|
|
5
7
|
import { AddToCartBlock } from "../blocks/saucedemo-web/inventory/methods/add-to-cart.effect.block.js";
|
|
6
8
|
|
|
@@ -10,17 +12,21 @@ const engine = new Engine();
|
|
|
10
12
|
// it doesn't need the same DOM confirmation the real checkout.flow.ts wants.
|
|
11
13
|
// Same Blocks, same act/resolve, zero duplication - only verify differs.
|
|
12
14
|
// .withVerify([]) reads from the Block itself, discoverable by typing
|
|
13
|
-
// "NavLoginBlock."/"
|
|
15
|
+
// "NavLoginBlock."/"SubmitLoginForFlow." in an editor - not a free function
|
|
14
16
|
// you have to already know exists.
|
|
15
17
|
//
|
|
16
|
-
// Explicit <LoginPage, LoggedIn, ItemInCart> here -
|
|
17
|
-
// the wildcard Checkpoint<string> (it's reused as
|
|
18
|
-
// too), and inferring
|
|
19
|
-
// one array trips TS's overload
|
|
20
|
-
//
|
|
21
|
-
|
|
18
|
+
// Explicit <LoginPage, LoginPage, LoginPage, LoggedIn, ItemInCart> here -
|
|
19
|
+
// AddToCartBlock's In is now the wildcard Checkpoint<string> (it's reused as
|
|
20
|
+
// shopFlow's own entry block too), and inferring the chain purely from
|
|
21
|
+
// several chained .withVerify([]) calls in one array trips TS's overload
|
|
22
|
+
// resolution into unifying the wrong Out type partway through; pinning the
|
|
23
|
+
// type args sidesteps it rather than fighting it. The two middle `LoginPage`
|
|
24
|
+
// entries are fill-username / fill-password (self-loop Methods).
|
|
25
|
+
export const smokeFlow = engine.defineFlow<LoginPage, LoginPage, LoginPage, LoggedIn, ItemInCart>([
|
|
22
26
|
start,
|
|
23
27
|
NavLoginBlock.withVerify([]),
|
|
28
|
+
FillUsernameBlock,
|
|
29
|
+
FillPasswordBlock,
|
|
24
30
|
SubmitLoginForFlow.withVerify([]),
|
|
25
31
|
AddToCartBlock.withVerify([]),
|
|
26
32
|
end,
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { Engine, start, end, withTitle, withSessionReset, withExpectedFailure } from "waygraph";
|
|
2
2
|
import { NavLoginBlock } from "../blocks/saucedemo-web/nav-login.block.js";
|
|
3
|
-
import {
|
|
3
|
+
import { FillUsernameBlock } from "../blocks/saucedemo-web/methods/fill-username.method.block.js";
|
|
4
|
+
import { FillPasswordBlock } from "../blocks/saucedemo-web/methods/fill-password.method.block.js";
|
|
5
|
+
import { SubmitLoginBlock } from "../blocks/saucedemo-web/methods/submit-login.method.block.js";
|
|
4
6
|
|
|
5
7
|
const engine = new Engine();
|
|
6
8
|
|
|
@@ -22,7 +24,9 @@ const engine = new Engine();
|
|
|
22
24
|
// "expected outcome" panel (branching no longer throws).
|
|
23
25
|
export const viewerBlockedFlow = withExpectedFailure(
|
|
24
26
|
withTitle(
|
|
25
|
-
withSessionReset(
|
|
27
|
+
withSessionReset(
|
|
28
|
+
engine.defineFlow([start, NavLoginBlock, FillUsernameBlock, FillPasswordBlock, SubmitLoginBlock, end]),
|
|
29
|
+
),
|
|
26
30
|
"Viewer: Blocked Login Attempt",
|
|
27
31
|
),
|
|
28
32
|
"locked_out_user stays on LoginPage with the error banner - this is the product working as intended.",
|
|
@@ -38,16 +38,23 @@ test("chainFlow blocks() lists the flattened episode chain in order", () => {
|
|
|
38
38
|
const blocks = chainFlow(loginFlow, shopFlow, viewerBlockedFlow).blocks();
|
|
39
39
|
expect(blocks.map((b) => b.name)).toEqual([
|
|
40
40
|
"nav-login",
|
|
41
|
+
"fill-username",
|
|
42
|
+
"fill-password",
|
|
41
43
|
"submit-login",
|
|
42
44
|
"add-to-cart",
|
|
43
45
|
"nav-cart",
|
|
44
46
|
"nav-checkout-info",
|
|
47
|
+
"fill-first-name",
|
|
48
|
+
"fill-last-name",
|
|
49
|
+
"fill-postal-code",
|
|
45
50
|
"submit-checkout-info",
|
|
46
51
|
"finish-order",
|
|
47
52
|
"nav-login",
|
|
53
|
+
"fill-username",
|
|
54
|
+
"fill-password",
|
|
48
55
|
"submit-login",
|
|
49
56
|
]);
|
|
50
|
-
expect(blocks.every((b, i) => (i ===
|
|
57
|
+
expect(blocks.every((b, i) => (i === 12 ? b.resetSessionBefore === true : !b.resetSessionBefore))).toBe(
|
|
51
58
|
true,
|
|
52
59
|
);
|
|
53
60
|
});
|
|
@@ -25,9 +25,16 @@ Docs: [docs/scaffold.html](../../docs/scaffold.html)
|
|
|
25
25
|
│ ├── states/
|
|
26
26
|
│ │ ├── demo.states.ts
|
|
27
27
|
│ │ └── demo.mem-keys.ts # SelectedItem for Effect / auto
|
|
28
|
-
│
|
|
29
|
-
│
|
|
30
|
-
│
|
|
28
|
+
│ ├── flows/
|
|
29
|
+
│ │ ├── example.flow.ts # nav + assert (smoke)
|
|
30
|
+
│ │ ├── shop.flow.ts # nav + add-item + clear (Effect path)
|
|
31
|
+
│ │ └── routes-demo.flow.ts # Home (manual mode) -> Docs (Map convention)
|
|
32
|
+
│ └── routes/ # Waygraph Map convention - see README.md
|
|
33
|
+
│ └── (external)/
|
|
34
|
+
│ └── docs/
|
|
35
|
+
│ ├── docs.sel.ts
|
|
36
|
+
│ ├── nav.block.ts # fixed name - every page-slug folder's Nav
|
|
37
|
+
│ └── page.block.ts # fixed name - every page-slug folder's arrival hub
|
|
31
38
|
├── scripts/
|
|
32
39
|
│ ├── fixture-server.mjs # serves home.html on :4177
|
|
33
40
|
│ └── with-fixture.mjs # start server + run waygraph auto/demo/run
|
|
@@ -59,3 +66,16 @@ npm run auto:cli # same menus in the terminal
|
|
|
59
66
|
```
|
|
60
67
|
|
|
61
68
|
After `nav-home`, Effect blocks expose one menu row per visible Add/Remove button.
|
|
69
|
+
|
|
70
|
+
## Two authoring modes
|
|
71
|
+
|
|
72
|
+
`src/blocks/` (`demo-web/`, `demo-external/`) is **manual mode** - freeform, developer-chosen
|
|
73
|
+
file layout, the default this whole scaffold otherwise uses.
|
|
74
|
+
|
|
75
|
+
`src/routes/` is the **Waygraph Map** convention - `(group)/<page-slug>/page.block.ts` +
|
|
76
|
+
`nav.block.ts` + `methods/*.block.ts`, one Checkpoint per folder, `(group)` purely
|
|
77
|
+
organizational (parens, Next.js route-group style - never part of the Checkpoint tag). Same
|
|
78
|
+
Block helpers, same execution - only where files live and what they're named changes. A
|
|
79
|
+
project can adopt it folder by folder; `routes-demo.flow.ts` proves both modes compose in one
|
|
80
|
+
flow (`nav-home` from `blocks/`, `nav-docs` from `routes/`). See the main package's own
|
|
81
|
+
`README.md` "Waygraph Map" section and `openspec/changes/waygraph-map/`.
|
|
@@ -8,7 +8,15 @@ import { readFileSync, existsSync } from "node:fs";
|
|
|
8
8
|
import { join, dirname, extname, normalize } from "node:path";
|
|
9
9
|
import { fileURLToPath } from "node:url";
|
|
10
10
|
|
|
11
|
-
const ROOT = join(dirname(fileURLToPath(import.meta.url)), "../src/
|
|
11
|
+
const ROOT = join(dirname(fileURLToPath(import.meta.url)), "../src/map/(app_base)");
|
|
12
|
+
// Each fixture HTML file lives beside its own _page.block.ts under the
|
|
13
|
+
// Waygraph Map convention now (home/home.html, docs/docs.html) - no longer
|
|
14
|
+
// a single flat directory, so this maps the request filename to its own
|
|
15
|
+
// page's subfolder instead of assuming one shared ROOT holds every file.
|
|
16
|
+
const FILE_DIRS = {
|
|
17
|
+
"home.html": "home",
|
|
18
|
+
"docs.html": "docs",
|
|
19
|
+
};
|
|
12
20
|
const PORT = Number(process.env.WAYGRAPH_FIXTURE_PORT || 4177);
|
|
13
21
|
const HOST = process.env.WAYGRAPH_FIXTURE_HOST || "127.0.0.1";
|
|
14
22
|
|
|
@@ -23,7 +31,8 @@ const TYPES = {
|
|
|
23
31
|
const server = createServer((req, res) => {
|
|
24
32
|
const raw = (req.url || "/").split("?")[0] || "/";
|
|
25
33
|
const rel = raw === "/" ? "home.html" : raw.replace(/^\//, "");
|
|
26
|
-
const
|
|
34
|
+
const subdir = FILE_DIRS[rel];
|
|
35
|
+
const full = subdir ? normalize(join(ROOT, subdir, rel)) : normalize(join(ROOT, rel));
|
|
27
36
|
if (!full.startsWith(ROOT) || !existsSync(full)) {
|
|
28
37
|
res.writeHead(404, { "content-type": "text/plain" });
|
|
29
38
|
res.end("not found");
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { Engine, start, end, withTitle, withHighlightFixtures } from "waygraph";
|
|
2
|
-
import { NavHomeBlock } from "../
|
|
3
|
-
import { AssertHelloBlock } from "../
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
import { NavHomeBlock } from "../map/(app_base)/home/_nav.block.js";
|
|
3
|
+
import { AssertHelloBlock } from "../map/(app_base)/home/_methods/assert-hello.method.block.js";
|
|
4
|
+
import { NavDocsBlock } from "../map/(app_base)/docs/_nav.block.js";
|
|
5
|
+
// Page hubs registered for auto/docs grouping (arrival-only after nav).
|
|
6
|
+
import "../map/(app_base)/home/_page.block.js";
|
|
7
|
+
import "../map/(app_base)/docs/_page.block.js";
|
|
6
8
|
|
|
7
9
|
const engine = new Engine();
|
|
8
10
|
|
|
9
|
-
/** Smoke: nav + assert (no mem). Green offline. */
|
|
11
|
+
/** Smoke: nav + assert (no mem), then nav to the sibling docs/ page. Green offline. */
|
|
10
12
|
export const exampleFlow = withHighlightFixtures(
|
|
11
13
|
withTitle(
|
|
12
|
-
engine.defineFlow([start, NavHomeBlock, AssertHelloBlock, end]),
|
|
14
|
+
engine.defineFlow([start, NavHomeBlock, AssertHelloBlock, NavDocsBlock, end]),
|
|
13
15
|
"Scaffold: Hello Waygraph",
|
|
14
16
|
),
|
|
15
17
|
{
|