waygraph 0.13.7 → 0.14.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 +820 -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 +417 -51
- package/dist/engine.d.ts +40 -1
- package/dist/engine.js +82 -0
- 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/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/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.flow.ts +12 -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/routes/(base_app)/dashboard/dashboard.sel.ts +10 -0
- package/examples/routed-demo/src/routes/(base_app)/dashboard/methods/click-widget.block.ts +23 -0
- package/examples/routed-demo/src/routes/(base_app)/dashboard/nav.block.ts +18 -0
- package/examples/routed-demo/src/routes/(base_app)/dashboard/page.block.ts +22 -0
- package/examples/routed-demo/src/routes/(external)/docs/docs.sel.ts +7 -0
- package/examples/routed-demo/src/routes/(external)/docs/nav.block.ts +21 -0
- package/examples/routed-demo/src/routes/(external)/docs/page.block.ts +15 -0
- package/examples/routed-demo/src/states/routed-demo.states.ts +10 -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/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/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/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/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/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/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/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/5c47910f.log +0 -0
- package/examples/saucedemo/.waygraph-auto/5eda8273.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/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/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/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/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/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/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/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/b83e6259.log +0 -0
- package/examples/saucedemo/.waygraph-auto/b9cb2796.log +0 -0
- package/examples/saucedemo/.waygraph-auto/bb0a0018.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/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/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/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/e101d19a.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/ebad3410.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/f3c29b21.log +0 -0
- package/examples/saucedemo/.waygraph-auto/f53f7cfc.log +0 -0
- package/examples/saucedemo/.waygraph-auto/f5ad5830.log +0 -0
- package/examples/saucedemo/.waygraph-auto/faed36dd.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/src/blocks/demo-external/mailpit/mailpit-inbox.page.block.ts +30 -0
- package/templates/scaffold/src/blocks/demo-external/mailpit/mailpit-sel.ts +5 -0
- package/templates/scaffold/src/blocks/demo-external/mailpit/methods/assert-email-content.method.block.ts +48 -0
- package/templates/scaffold/src/blocks/demo-external/mailpit/methods/assert-email-received.method.block.ts +49 -0
- package/templates/scaffold/src/blocks/demo-external/mailpit/methods/extract-email-link.method.block.ts +41 -0
- package/templates/scaffold/src/blocks/demo-external/mailpit/methods/open-message.method.block.ts +39 -0
- package/templates/scaffold/src/blocks/demo-external/mailpit/nav-mailpit-inbox.block.ts +20 -0
- package/templates/scaffold/src/blocks/demo-web/demo-sel.ts +1 -0
- package/templates/scaffold/src/blocks/demo-web/docs.html +8 -0
- package/templates/scaffold/src/blocks/demo-web/home.html +4 -0
- package/templates/scaffold/src/blocks/demo-web/methods/assert-hello.method.block.ts +34 -38
- package/templates/scaffold/src/blocks/demo-web/methods/assert-item-added.method.block.ts +38 -0
- package/templates/scaffold/src/blocks/demo-web/nav-verification-link.block.ts +34 -0
- package/templates/scaffold/src/flows/mail-verify.flow.ts +85 -0
- package/templates/scaffold/src/flows/routes-demo.flow.ts +14 -0
- package/templates/scaffold/src/flows/shop.flow.ts +19 -2
- package/templates/scaffold/src/routes/(external)/docs/docs.sel.ts +7 -0
- package/templates/scaffold/src/routes/(external)/docs/nav.block.ts +21 -0
- package/templates/scaffold/src/routes/(external)/docs/page.block.ts +15 -0
- package/templates/scaffold/src/states/demo.mem-keys.ts +25 -1
- package/templates/scaffold/src/states/demo.states.ts +13 -0
- package/templates/scaffold/test-results/.last-run.json +4 -0
- 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
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { fastForwardComposeBlock } from "waygraph";
|
|
2
2
|
import { NavLoginBlock } from "./nav-login.block.js";
|
|
3
|
+
import { FillUsernameBlock } from "./methods/fill-username.method.block.js";
|
|
4
|
+
import { FillPasswordBlock } from "./methods/fill-password.method.block.js";
|
|
3
5
|
import { SubmitLoginForFlow } from "./methods/submit-login-for-flow.js";
|
|
4
6
|
|
|
5
7
|
/**
|
|
@@ -7,11 +9,14 @@ import { SubmitLoginForFlow } from "./methods/submit-login-for-flow.js";
|
|
|
7
9
|
* Helper: fastForwardComposeBlock
|
|
8
10
|
* Route: saucedemo-web/ (auth prefix)
|
|
9
11
|
*
|
|
10
|
-
* Collapses nav-login +
|
|
11
|
-
* checkout demos skip watching auth. Use
|
|
12
|
+
* Collapses nav-login + fill-username + fill-password + submit-login into
|
|
13
|
+
* one opaque demo/run step so checkout demos skip watching auth. Use
|
|
14
|
+
* --ff-expand to gate inners again (they show as 4 separate steps).
|
|
12
15
|
* loginFlow stays expanded for Sign In episode narration.
|
|
13
16
|
*/
|
|
14
17
|
export const FfOwnerAuthBlock = fastForwardComposeBlock("ff-owner-auth", [
|
|
15
18
|
NavLoginBlock,
|
|
19
|
+
FillUsernameBlock,
|
|
20
|
+
FillPasswordBlock,
|
|
16
21
|
SubmitLoginForFlow,
|
|
17
22
|
]);
|
|
@@ -23,3 +23,4 @@ Single product detail page, plus nav edges that return to catalog
|
|
|
23
23
|
## Related mem keys / checkpoints
|
|
24
24
|
|
|
25
25
|
- Checkpoints: `ItemDetailPage`, `LoggedIn` (after back / continue), `OrderComplete` (from for back-to-products)
|
|
26
|
+
- Sel: `ItemDetailSel` (`item-detail.sel.ts`) - DOM only, not mem
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DOM selectors for the item detail page (`/inventory-item.html`) and the
|
|
3
|
+
* order-complete page's equivalent nav control. Convention: DOM strings
|
|
4
|
+
* live in `*Sel` next to the page, not inlined in each Block.
|
|
5
|
+
*/
|
|
6
|
+
export const ItemDetailSel = {
|
|
7
|
+
continueShoppingBtn: "#continue-shopping",
|
|
8
|
+
backToProductsBtn: "#back-to-products",
|
|
9
|
+
};
|
package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/nav-back-to-inventory.block.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { defineNavClickBlock, Trait } from "waygraph";
|
|
2
2
|
import type { LoggedIn } from "../../../states/checkout.states.js";
|
|
3
|
+
import { ItemDetailSel } from "./item-detail.sel.js";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Kind: Nav
|
|
@@ -13,6 +14,6 @@ export const NavBackToInventoryBlock = defineNavClickBlock<LoggedIn>({
|
|
|
13
14
|
name: "nav-back-to-inventory",
|
|
14
15
|
description: "Clicks 'Back to products' on the item detail page.",
|
|
15
16
|
checkpoint: "LoggedIn",
|
|
16
|
-
click:
|
|
17
|
+
click: ItemDetailSel.backToProductsBtn,
|
|
17
18
|
verify: [Trait.url({ pathname: "/inventory.html" })],
|
|
18
19
|
});
|
package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/nav-back-to-products.block.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { defineNavClickBlock, Trait } from "waygraph";
|
|
2
2
|
import type { LoggedIn } from "../../../states/checkout.states.js";
|
|
3
|
+
import { ItemDetailSel } from "./item-detail.sel.js";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Kind: Nav
|
|
@@ -13,6 +14,6 @@ export const NavBackToProductsBlock = defineNavClickBlock<LoggedIn>({
|
|
|
13
14
|
name: "nav-back-to-products",
|
|
14
15
|
description: "Clicks 'Back Home' on the order confirmation page.",
|
|
15
16
|
checkpoint: "LoggedIn",
|
|
16
|
-
click:
|
|
17
|
+
click: ItemDetailSel.backToProductsBtn,
|
|
17
18
|
verify: [Trait.url({ pathname: "/inventory.html" })],
|
|
18
19
|
});
|
package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/nav-continue-shopping.block.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { defineNavClickBlock, Trait } from "waygraph";
|
|
2
2
|
import type { LoggedIn } from "../../../states/checkout.states.js";
|
|
3
|
+
import { ItemDetailSel } from "./item-detail.sel.js";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Kind: Nav
|
|
@@ -12,6 +13,6 @@ export const NavContinueShoppingBlock = defineNavClickBlock<LoggedIn>({
|
|
|
12
13
|
name: "nav-continue-shopping",
|
|
13
14
|
description: "Clicks 'Continue Shopping' on the cart page.",
|
|
14
15
|
checkpoint: "LoggedIn",
|
|
15
|
-
click:
|
|
16
|
+
click: ItemDetailSel.continueShoppingBtn,
|
|
16
17
|
verify: [Trait.url({ pathname: "/inventory.html" })],
|
|
17
18
|
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { defineMethodBlock, checkpoint, type StubCtx } from "waygraph";
|
|
2
|
+
import type { LoginPage } from "../../../states/checkout.states.js";
|
|
3
|
+
import { LoginCreds } from "../../../states/checkout.mem-keys.js";
|
|
4
|
+
import { LoginSel } from "./login.sel.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Kind: Method
|
|
8
|
+
* Helper: defineMethodBlock
|
|
9
|
+
* Route: saucedemo-web/methods/ (page URL /)
|
|
10
|
+
*
|
|
11
|
+
* Fills the password field only - self-loop on LoginPage. See
|
|
12
|
+
* fill-username.method.block.ts for why this is split from submit.
|
|
13
|
+
*/
|
|
14
|
+
export const FillPasswordBlock = defineMethodBlock<LoginPage, LoginPage>({
|
|
15
|
+
name: "fill-password",
|
|
16
|
+
description: "Fills the password field on the login form.",
|
|
17
|
+
requires: [LoginCreds.key],
|
|
18
|
+
instruction: {
|
|
19
|
+
async act(page, _input, mem) {
|
|
20
|
+
const { password } = mem.get(LoginCreds.key);
|
|
21
|
+
await page.locator(LoginSel.password).fill(password);
|
|
22
|
+
},
|
|
23
|
+
resolve: () => checkpoint("LoginPage"),
|
|
24
|
+
stubBefore: (ctx: StubCtx) => {
|
|
25
|
+
ctx.highlights({
|
|
26
|
+
password: {
|
|
27
|
+
selector: LoginSel.password,
|
|
28
|
+
label: "Password",
|
|
29
|
+
todo: "login-pass",
|
|
30
|
+
focus: true,
|
|
31
|
+
color: "#c9a6ff",
|
|
32
|
+
zoom: 1.4,
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
},
|
|
36
|
+
stubAfter: (ctx: StubCtx) => {
|
|
37
|
+
ctx.todos(
|
|
38
|
+
"saucedemo",
|
|
39
|
+
[
|
|
40
|
+
{ id: "login-user", text: "Enter username", done: true },
|
|
41
|
+
{ id: "login-pass", text: "Enter password", done: true },
|
|
42
|
+
{ id: "login-submit", text: "Tap Login" },
|
|
43
|
+
{ id: "cart-find", text: "Find the product" },
|
|
44
|
+
{ id: "cart-add", text: "Add to cart" },
|
|
45
|
+
{ id: "cart-open", text: "Open cart" },
|
|
46
|
+
],
|
|
47
|
+
{ title: "Device showcase", index: 2 },
|
|
48
|
+
);
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
});
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { defineMethodBlock, checkpoint, type StubCtx } from "waygraph";
|
|
2
|
+
import type { LoginPage } from "../../../states/checkout.states.js";
|
|
3
|
+
import { LoginCreds } from "../../../states/checkout.mem-keys.js";
|
|
4
|
+
import { LoginSel } from "./login.sel.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Kind: Method
|
|
8
|
+
* Helper: defineMethodBlock
|
|
9
|
+
* Route: saucedemo-web/methods/ (page URL /)
|
|
10
|
+
*
|
|
11
|
+
* Fills the username field only - self-loop on LoginPage, no submit, no
|
|
12
|
+
* page.goto. Submit is its own Block (submit-login.method.block.ts) so the
|
|
13
|
+
* graph/demo show fill vs submit as real, distinct steps instead of one
|
|
14
|
+
* Block doing "input username and password and login at the same time".
|
|
15
|
+
*/
|
|
16
|
+
export const FillUsernameBlock = defineMethodBlock<LoginPage, LoginPage>({
|
|
17
|
+
name: "fill-username",
|
|
18
|
+
description: "Fills the username field on the login form.",
|
|
19
|
+
requires: [LoginCreds.key],
|
|
20
|
+
instruction: {
|
|
21
|
+
async act(page, _input, mem) {
|
|
22
|
+
const { username } = mem.get(LoginCreds.key);
|
|
23
|
+
await page.locator(LoginSel.username).fill(username);
|
|
24
|
+
},
|
|
25
|
+
resolve: () => checkpoint("LoginPage"),
|
|
26
|
+
stubBefore: (ctx: StubCtx) => {
|
|
27
|
+
ctx.title("Signing in · mobile");
|
|
28
|
+
ctx.device("mobile");
|
|
29
|
+
ctx.portrait();
|
|
30
|
+
ctx.todos(
|
|
31
|
+
"saucedemo",
|
|
32
|
+
[
|
|
33
|
+
{ id: "login-user", text: "Enter username" },
|
|
34
|
+
{ id: "login-pass", text: "Enter password" },
|
|
35
|
+
{ id: "login-submit", text: "Tap Login" },
|
|
36
|
+
{ id: "cart-find", text: "Find the product" },
|
|
37
|
+
{ id: "cart-add", text: "Add to cart" },
|
|
38
|
+
{ id: "cart-open", text: "Open cart" },
|
|
39
|
+
],
|
|
40
|
+
{ title: "Device showcase", index: 0 },
|
|
41
|
+
);
|
|
42
|
+
ctx.zoom(1.35);
|
|
43
|
+
ctx.highlights({
|
|
44
|
+
username: {
|
|
45
|
+
selector: LoginSel.username,
|
|
46
|
+
label: "Username",
|
|
47
|
+
todo: "login-user",
|
|
48
|
+
focus: true,
|
|
49
|
+
color: "#c9a6ff",
|
|
50
|
+
zoom: 1.4,
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
},
|
|
54
|
+
stubAfter: (ctx: StubCtx) => {
|
|
55
|
+
ctx.todos(
|
|
56
|
+
"saucedemo",
|
|
57
|
+
[
|
|
58
|
+
{ id: "login-user", text: "Enter username", done: true },
|
|
59
|
+
{ id: "login-pass", text: "Enter password" },
|
|
60
|
+
{ id: "login-submit", text: "Tap Login" },
|
|
61
|
+
{ id: "cart-find", text: "Find the product" },
|
|
62
|
+
{ id: "cart-add", text: "Add to cart" },
|
|
63
|
+
{ id: "cart-open", text: "Open cart" },
|
|
64
|
+
],
|
|
65
|
+
{ title: "Device showcase", index: 1 },
|
|
66
|
+
);
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DOM selectors for the login route (`/`) and its logout burger menu.
|
|
3
|
+
* Convention: DOM strings live in `*Sel` next to the page, not inlined in
|
|
4
|
+
* each Block.
|
|
5
|
+
*/
|
|
6
|
+
export const LoginSel = {
|
|
7
|
+
username: "#user-name",
|
|
8
|
+
password: "#password",
|
|
9
|
+
loginButton: "#login-button",
|
|
10
|
+
errorBanner: '[data-test="error"]',
|
|
11
|
+
burgerMenuButton: "#react-burger-menu-btn",
|
|
12
|
+
logoutLink: "#logout_sidebar_link",
|
|
13
|
+
};
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import type { DefinedBlock } from "waygraph";
|
|
2
2
|
import type { LoginPage, LoggedIn } from "../../../states/checkout.states.js";
|
|
3
|
-
import {
|
|
3
|
+
import { SubmitLoginBlock } from "./submit-login.method.block.js";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Kind: helper (not a discoverable Block file)
|
|
7
|
-
* Helper: typed alias over
|
|
7
|
+
* Helper: typed alias over SubmitLoginBlock
|
|
8
8
|
* Route: saucedemo-web/methods/ (page URL /)
|
|
9
9
|
*
|
|
10
10
|
* DefinedBlock cast so linear Flows can chain .withVerify on Out=LoggedIn;
|
|
11
|
-
* runtime still branches on bad credentials via
|
|
11
|
+
* runtime still branches on bad credentials via SubmitLoginBlock.
|
|
12
12
|
*/
|
|
13
|
-
export const SubmitLoginForFlow =
|
|
13
|
+
export const SubmitLoginForFlow = SubmitLoginBlock as unknown as DefinedBlock<LoginPage, LoggedIn>;
|
|
@@ -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,45 +42,11 @@ 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
|
-
ctx.device("mobile");
|
|
55
|
-
ctx.portrait();
|
|
56
|
-
ctx.todos(
|
|
57
|
-
"saucedemo",
|
|
58
|
-
[
|
|
59
|
-
{ id: "login-user", text: "Enter username" },
|
|
60
|
-
{ id: "login-pass", text: "Enter password" },
|
|
61
|
-
{ id: "login-submit", text: "Tap Login" },
|
|
62
|
-
{ id: "cart-find", text: "Find the product" },
|
|
63
|
-
{ id: "cart-add", text: "Add to cart" },
|
|
64
|
-
{ id: "cart-open", text: "Open cart" },
|
|
65
|
-
],
|
|
66
|
-
{ title: "Device showcase", index: 0 },
|
|
67
|
-
);
|
|
68
|
-
ctx.zoom(1.35);
|
|
69
47
|
ctx.highlights({
|
|
70
|
-
username: {
|
|
71
|
-
selector: "#user-name",
|
|
72
|
-
label: "Username",
|
|
73
|
-
todo: "login-user",
|
|
74
|
-
focus: true,
|
|
75
|
-
color: "#c9a6ff",
|
|
76
|
-
zoom: 1.4,
|
|
77
|
-
},
|
|
78
|
-
password: {
|
|
79
|
-
selector: "#password",
|
|
80
|
-
label: "Password",
|
|
81
|
-
todo: "login-pass",
|
|
82
|
-
focus: true,
|
|
83
|
-
color: "#c9a6ff",
|
|
84
|
-
zoom: 1.4,
|
|
85
|
-
},
|
|
86
48
|
submit: {
|
|
87
|
-
selector:
|
|
49
|
+
selector: LoginSel.loginButton,
|
|
88
50
|
label: "Login",
|
|
89
51
|
todo: "login-submit",
|
|
90
52
|
focus: true,
|
|
@@ -108,7 +70,7 @@ export const SubmitLoginActionBlock = defineMethodBlock<LoginPage, LoginSubmitOu
|
|
|
108
70
|
{ title: "Sign in", style: "checklist" },
|
|
109
71
|
);
|
|
110
72
|
ctx.ring("error", {
|
|
111
|
-
selector:
|
|
73
|
+
selector: LoginSel.errorBanner,
|
|
112
74
|
label: "Login error banner",
|
|
113
75
|
tone: "danger",
|
|
114
76
|
focus: true,
|
|
@@ -144,7 +106,7 @@ export const SubmitLoginActionBlock = defineMethodBlock<LoginPage, LoginSubmitOu
|
|
|
144
106
|
stubOnError: (ctx: StubCtx) => {
|
|
145
107
|
ctx.title("Login failed");
|
|
146
108
|
ctx.ring("error", {
|
|
147
|
-
selector:
|
|
109
|
+
selector: LoginSel.errorBanner,
|
|
148
110
|
label: "Login error banner",
|
|
149
111
|
tone: "danger",
|
|
150
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,6 +11,9 @@ 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
|
|
|
@@ -32,6 +35,9 @@ export const checkoutFlow = withHighlightFixtures(
|
|
|
32
35
|
ItemInCart,
|
|
33
36
|
CartPage,
|
|
34
37
|
CheckoutInfoPage,
|
|
38
|
+
CheckoutInfoPage,
|
|
39
|
+
CheckoutInfoPage,
|
|
40
|
+
CheckoutInfoPage,
|
|
35
41
|
CheckoutOverviewPage,
|
|
36
42
|
OrderComplete
|
|
37
43
|
>([
|
|
@@ -40,6 +46,9 @@ export const checkoutFlow = withHighlightFixtures(
|
|
|
40
46
|
AddToCartBlock,
|
|
41
47
|
NavCartBlock,
|
|
42
48
|
NavCheckoutInfoBlock,
|
|
49
|
+
FillFirstNameBlock,
|
|
50
|
+
FillLastNameBlock,
|
|
51
|
+
FillPostalCodeBlock,
|
|
43
52
|
SubmitCheckoutInfoBlock,
|
|
44
53
|
FinishOrderBlock,
|
|
45
54
|
end,
|
|
@@ -57,8 +66,9 @@ export const checkoutFlow = withHighlightFixtures(
|
|
|
57
66
|
},
|
|
58
67
|
},
|
|
59
68
|
},
|
|
60
|
-
// Kept for --ff-expand (inners become separate steps again
|
|
61
|
-
|
|
69
|
+
// Kept for --ff-expand (inners become separate steps again: nav-login,
|
|
70
|
+
// fill-username, fill-password, submit-login).
|
|
71
|
+
"fill-username": {
|
|
62
72
|
stubBefore: {
|
|
63
73
|
username: {
|
|
64
74
|
label: "Demo user",
|
|
@@ -66,7 +76,15 @@ export const checkoutFlow = withHighlightFixtures(
|
|
|
66
76
|
tag: "AC",
|
|
67
77
|
duration: true,
|
|
68
78
|
},
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
"fill-password": {
|
|
82
|
+
stubBefore: {
|
|
69
83
|
password: { label: "Password", detail: "Filled from Mem credentials.", duration: 1500 },
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
"submit-login": {
|
|
87
|
+
stubBefore: {
|
|
70
88
|
submit: { label: "Sign in", tag: "GATE", duration: true, fastMode: 500 },
|
|
71
89
|
},
|
|
72
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,
|
|
@@ -9,7 +9,9 @@ import {
|
|
|
9
9
|
Trait,
|
|
10
10
|
} from "waygraph";
|
|
11
11
|
import { NavLoginBlock } from "../blocks/saucedemo-web/nav-login.block.js";
|
|
12
|
-
import {
|
|
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";
|
|
14
|
+
import { SubmitLoginBlock } from "../blocks/saucedemo-web/methods/submit-login.method.block.js";
|
|
13
15
|
|
|
14
16
|
const engine = new Engine();
|
|
15
17
|
|
|
@@ -23,7 +25,7 @@ const engine = new Engine();
|
|
|
23
25
|
*/
|
|
24
26
|
const forcedInventoryVerify = withSessionReset(
|
|
25
27
|
engine
|
|
26
|
-
.defineFlow([start, NavLoginBlock,
|
|
28
|
+
.defineFlow([start, NavLoginBlock, FillUsernameBlock, FillPasswordBlock, SubmitLoginBlock, end])
|
|
27
29
|
.withBlockVerify("submit-login", [Trait.url({ pathname: "/inventory.html" })]),
|
|
28
30
|
);
|
|
29
31
|
|