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
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -1,7 +1,21 @@
|
|
|
1
1
|
# saucedemo waygraph conventions
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
**How this maps to the app:** navigate to the site -> you land on a `Page` Block
|
|
4
|
+
(the screen hub) -> every Method/Effect/Nav that screen can do hangs off that
|
|
5
|
+
Page. Each Block does exactly **one** distinct action - never two or more
|
|
6
|
+
bundled together. Filling a form field and submitting it are two different
|
|
7
|
+
actions, so they are two different Blocks, even on the same screen:
|
|
8
|
+
`fill-username` / `fill-password` (self-loop Methods, no checkpoint change) and
|
|
9
|
+
`submit-login` (the real transition) are three real Blocks, not one Method
|
|
10
|
+
that "inputs username and password and logs in at the same time." The same
|
|
11
|
+
split applies to `fill-first-name` / `fill-last-name` / `fill-postal-code` /
|
|
12
|
+
`submit-checkout-info` on the shipping form.
|
|
13
|
+
|
|
14
|
+
This is what makes `waygraph auto`/`traverse` see a clean, honest graph of the
|
|
15
|
+
app: every real user-visible action is its own edge, and no Block silently
|
|
16
|
+
"teleports" the user past several actions at once. It is also why a
|
|
17
|
+
`page.goto()` (or NavBlock `click`) never appears anywhere except inside a
|
|
18
|
+
`defineNavBlock`/`defineNavClickBlock` - see `waygraph check` below.
|
|
5
19
|
|
|
6
20
|
**TypeScript salt only.** Helpers force a useful shape. At runtime everything is
|
|
7
21
|
still a `Block` - there is no separate Page / Effect / Nav engine.
|
|
@@ -33,9 +47,12 @@ src/blocks/
|
|
|
33
47
|
SITE-MAP.md
|
|
34
48
|
saucedemo-web/ # THIS FOLDER IS URL "/"
|
|
35
49
|
NAV.md
|
|
36
|
-
nav-login.block.ts
|
|
50
|
+
nav-login.block.ts # Page hub
|
|
51
|
+
ff-owner-auth.block.ts # FFCompose wrapping the 4 Blocks below
|
|
37
52
|
methods/
|
|
38
|
-
|
|
53
|
+
fill-username.method.block.ts # self-loop, fills only
|
|
54
|
+
fill-password.method.block.ts # self-loop, fills only
|
|
55
|
+
submit-login.method.block.ts # click only, branches
|
|
39
56
|
submit-login-for-flow.ts
|
|
40
57
|
submit-logout.method.block.ts
|
|
41
58
|
inventory/ # /inventory.html
|
|
@@ -58,7 +75,10 @@ src/blocks/
|
|
|
58
75
|
checkout-step-one/ # /checkout-step-one.html
|
|
59
76
|
NAV.md
|
|
60
77
|
methods/
|
|
61
|
-
|
|
78
|
+
fill-first-name.method.block.ts # self-loop, fills only
|
|
79
|
+
fill-last-name.method.block.ts # self-loop, fills only
|
|
80
|
+
fill-postal-code.method.block.ts # self-loop, fills only
|
|
81
|
+
submit-checkout-info.method.block.ts # click only
|
|
62
82
|
checkout-step-two/ # /checkout-step-two.html
|
|
63
83
|
NAV.md
|
|
64
84
|
methods/
|
|
@@ -8,13 +8,24 @@ Runtime is always a `Block`. Helpers are TypeScript salt + clear intent.
|
|
|
8
8
|
| `defineNavBlock` | URL / `goto` only | `nav-*.block.ts` |
|
|
9
9
|
| `defineNavClickBlock` | Click-to-navigate only | `nav-*.block.ts` |
|
|
10
10
|
| `defineMemNavBlock` | Nav + per-row `instanceOptions` | `nav-*.block.ts` |
|
|
11
|
-
| `defineMethodBlock` | One-shot non-nav app step | `*.method.block.ts` under `methods/` |
|
|
11
|
+
| `defineMethodBlock` | One-shot non-nav app step, exactly one action | `*.method.block.ts` under `methods/` |
|
|
12
|
+
| `defineAssertBlock` | Self-loop assertion, no state change - `verify` only | `*.method.block.ts` under `methods/` |
|
|
12
13
|
| `defineEffectBlock` | Instance mutate + auto menu rows | `*.effect.block.ts` under `methods/` |
|
|
13
14
|
| `defineBlock` | Escape hatch: tests, unsure, probes | any |
|
|
14
|
-
| `defineActionBlock` | **Deprecated** alias of `defineMethodBlock` |
|
|
15
|
+
| `defineActionBlock` | **Deprecated** alias of `defineMethodBlock` | - |
|
|
15
16
|
|
|
16
17
|
`defineNavBlock({ click })` still works (compat) - prefer `defineNavClickBlock` in app code.
|
|
17
18
|
|
|
19
|
+
**One distinct action per Block.** A Method that fills fields *and* submits is wrong even if
|
|
20
|
+
it "works" - split it (`fill-username` + `fill-password` + `submit-login`, not one Block).
|
|
21
|
+
`defineAssertBlock({ name, checkpoint, verify, waitForHeading?, requires? })` is the
|
|
22
|
+
self-loop-only shape for "assert something on the current page, no state change" - no
|
|
23
|
+
hand-written `act`/`resolve` to accidentally make do two things. `waygraph check` warns when
|
|
24
|
+
a `verify` array inlines a literal selector string instead of a `*Sel` reference. Give it an
|
|
25
|
+
explicit type argument (`defineAssertBlock<LoggedIn>({...})`) whenever it is not the last
|
|
26
|
+
Block before `end` - otherwise `Out` defaults to wildcard `Checkpoint<string>`, which breaks
|
|
27
|
+
`defineFlow`'s tuple typing mid-chain.
|
|
28
|
+
|
|
18
29
|
---
|
|
19
30
|
|
|
20
31
|
## Page hub + methods + Sel
|
|
@@ -76,7 +87,7 @@ Conditional Out (no `branch()` needed for auto/graph):
|
|
|
76
87
|
defineMethodBlock<LoginPage, LoggedIn | LoginPage>({
|
|
77
88
|
name: "submit-login",
|
|
78
89
|
instruction: {
|
|
79
|
-
async act(page
|
|
90
|
+
async act(page) { /* click only - fields were filled by earlier Blocks */ },
|
|
80
91
|
async observe(page) {
|
|
81
92
|
try {
|
|
82
93
|
await page.waitForURL(/\/inventory\.html/, { timeout: 8000 });
|
|
@@ -93,7 +104,7 @@ defineMethodBlock<LoginPage, LoggedIn | LoginPage>({
|
|
|
93
104
|
Optional routing for `runGraph`:
|
|
94
105
|
|
|
95
106
|
```ts
|
|
96
|
-
branch(
|
|
107
|
+
branch(SubmitLoginBlock, {
|
|
97
108
|
LoggedIn: AddToCartBlock,
|
|
98
109
|
LoginPage: null, // stop
|
|
99
110
|
});
|
|
@@ -87,7 +87,13 @@ const { graph, library } = await buildExploreContext(root);
|
|
|
87
87
|
const nodeNames = graph.nodes.map((n) => n.checkpoint);
|
|
88
88
|
|
|
89
89
|
const { NavLoginBlock } = await import(pathToFileURL(join(root, "src/blocks/saucedemo-web/nav-login.block.js")).href);
|
|
90
|
-
const {
|
|
90
|
+
const { FillUsernameBlock } = await import(
|
|
91
|
+
pathToFileURL(join(root, "src/blocks/saucedemo-web/methods/fill-username.method.block.js")).href
|
|
92
|
+
);
|
|
93
|
+
const { FillPasswordBlock } = await import(
|
|
94
|
+
pathToFileURL(join(root, "src/blocks/saucedemo-web/methods/fill-password.method.block.js")).href
|
|
95
|
+
);
|
|
96
|
+
const { SubmitLoginBlock } = await import(
|
|
91
97
|
pathToFileURL(join(root, "src/blocks/saucedemo-web/methods/submit-login.method.block.js")).href
|
|
92
98
|
);
|
|
93
99
|
const { LoginCreds } = await import(pathToFileURL(join(root, "src/states/checkout.mem-keys.js")).href);
|
|
@@ -111,7 +117,7 @@ await paintPanel(page, menuBefore, nodeNames, library.byName, "Mem: standard_use
|
|
|
111
117
|
await snap(page, "wrong-login-1-before.png");
|
|
112
118
|
|
|
113
119
|
mem.set(LoginCreds({ username: "standard_user", password: "wrong-password" }));
|
|
114
|
-
const flow = engine.defineFlow([start, NavLoginBlock,
|
|
120
|
+
const flow = engine.defineFlow([start, NavLoginBlock, FillUsernameBlock, FillPasswordBlock, SubmitLoginBlock, end]);
|
|
115
121
|
const runOut = await flow.run(context, mem, { page, closeOnFinish: false });
|
|
116
122
|
const result = runOut && typeof runOut === "object" && "result" in runOut ? runOut.result : runOut;
|
|
117
123
|
|
|
@@ -14,7 +14,13 @@ const root = join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
|
14
14
|
const waygraphDist = join(root, "../../dist");
|
|
15
15
|
const { Engine, start, end, MemPage } = await import(pathToFileURL(join(waygraphDist, "index.js")).href);
|
|
16
16
|
const { NavLoginBlock } = await import(pathToFileURL(join(root, "src/blocks/saucedemo-web/nav-login.block.js")).href);
|
|
17
|
-
const {
|
|
17
|
+
const { FillUsernameBlock } = await import(
|
|
18
|
+
pathToFileURL(join(root, "src/blocks/saucedemo-web/methods/fill-username.method.block.js")).href
|
|
19
|
+
);
|
|
20
|
+
const { FillPasswordBlock } = await import(
|
|
21
|
+
pathToFileURL(join(root, "src/blocks/saucedemo-web/methods/fill-password.method.block.js")).href
|
|
22
|
+
);
|
|
23
|
+
const { SubmitLoginBlock } = await import(
|
|
18
24
|
pathToFileURL(join(root, "src/blocks/saucedemo-web/methods/submit-login.method.block.js")).href
|
|
19
25
|
);
|
|
20
26
|
const { LoginCreds } = await import(pathToFileURL(join(root, "src/states/checkout.mem-keys.js")).href);
|
|
@@ -35,7 +41,7 @@ const engine = new Engine({ headless: true });
|
|
|
35
41
|
const mem = new MemPage();
|
|
36
42
|
mem.set(LoginCreds({ username: "standard_user", password: "wrong-password" }));
|
|
37
43
|
|
|
38
|
-
const flow = engine.defineFlow([start, NavLoginBlock,
|
|
44
|
+
const flow = engine.defineFlow([start, NavLoginBlock, FillUsernameBlock, FillPasswordBlock, SubmitLoginBlock, end]);
|
|
39
45
|
const runOut = await flow.run(context, mem, { page, closeOnFinish: false });
|
|
40
46
|
const result = runOut && typeof runOut === "object" && "result" in runOut ? runOut.result : runOut;
|
|
41
47
|
|
|
@@ -8,11 +8,15 @@ src/blocks/
|
|
|
8
8
|
SITE-MAP.md
|
|
9
9
|
saucedemo-web/ # URL /
|
|
10
10
|
NAV.md
|
|
11
|
-
nav-login.block.ts #
|
|
11
|
+
nav-login.block.ts # Page definePageBlock url:/
|
|
12
|
+
ff-owner-auth.block.ts # FFCompose (nav-login + fill-username + fill-password + submit-login)
|
|
12
13
|
methods/
|
|
13
|
-
|
|
14
|
+
fill-username.method.block.ts # Method defineMethodBlock (self-loop on LoginPage)
|
|
15
|
+
fill-password.method.block.ts # Method defineMethodBlock (self-loop on LoginPage)
|
|
16
|
+
submit-login.method.block.ts # Method defineMethodBlock (click only; branches)
|
|
14
17
|
submit-login-for-flow.ts # helper (not a discoverable *.block.ts alone)
|
|
15
18
|
submit-logout.method.block.ts # Method defineMethodBlock
|
|
19
|
+
login.sel.ts # LoginSel (not a Block)
|
|
16
20
|
inventory/ # URL /inventory.html
|
|
17
21
|
inventory.page.block.ts # Page definePageBlock
|
|
18
22
|
NAV.md
|
|
@@ -25,20 +29,27 @@ src/blocks/
|
|
|
25
29
|
remove-from-cart.effect.block.ts
|
|
26
30
|
inventory-item/ # URL /inventory-item.html
|
|
27
31
|
NAV.md
|
|
32
|
+
item-detail.sel.ts # ItemDetailSel (not a Block)
|
|
28
33
|
nav-continue-shopping.block.ts
|
|
29
34
|
nav-back-to-products.block.ts
|
|
30
35
|
nav-back-to-inventory.block.ts
|
|
31
36
|
cart/ # URL /cart.html
|
|
32
37
|
NAV.md
|
|
38
|
+
cart.sel.ts # CartSel (not a Block)
|
|
33
39
|
nav-cart.block.ts # Nav click header cart
|
|
34
40
|
nav-checkout-info.block.ts
|
|
35
41
|
checkout-step-one/ # URL /checkout-step-one.html
|
|
36
42
|
NAV.md
|
|
37
43
|
methods/
|
|
38
|
-
|
|
44
|
+
checkout-info.sel.ts # CheckoutInfoSel (not a Block)
|
|
45
|
+
fill-first-name.method.block.ts # Method defineMethodBlock (self-loop on CheckoutInfoPage)
|
|
46
|
+
fill-last-name.method.block.ts # Method defineMethodBlock (self-loop on CheckoutInfoPage)
|
|
47
|
+
fill-postal-code.method.block.ts # Method defineMethodBlock (self-loop on CheckoutInfoPage)
|
|
48
|
+
submit-checkout-info.method.block.ts # Method defineMethodBlock (click only)
|
|
39
49
|
checkout-step-two/ # URL /checkout-step-two.html
|
|
40
50
|
NAV.md
|
|
41
51
|
methods/
|
|
52
|
+
checkout-overview.sel.ts # CheckoutOverviewSel (not a Block)
|
|
42
53
|
finish-order.method.block.ts
|
|
43
54
|
```
|
|
44
55
|
|
|
@@ -16,11 +16,25 @@ Login page for Swag Labs. This folder is the namespace root (`/` in the browser)
|
|
|
16
16
|
|
|
17
17
|
| File | Kind | Notes |
|
|
18
18
|
|------|------|-------|
|
|
19
|
-
| `methods/
|
|
19
|
+
| `methods/fill-username.method.block.ts` | Method | Fills username only; self-loop on LoginPage |
|
|
20
|
+
| `methods/fill-password.method.block.ts` | Method | Fills password only; self-loop on LoginPage |
|
|
21
|
+
| `methods/submit-login.method.block.ts` | Method | Click Login only; branches LoggedIn vs LoginPage |
|
|
20
22
|
| `methods/submit-login-for-flow.ts` | helper | Typed alias for linear Flows |
|
|
21
23
|
| `methods/submit-logout.method.block.ts` | Method | Burger menu logout -> LoginPage |
|
|
24
|
+
| `methods/login.sel.ts` | helper | `LoginSel` (not a Block) |
|
|
25
|
+
|
|
26
|
+
Fill and submit are three separate Blocks (not one that fills both fields and
|
|
27
|
+
clicks Login) so the graph/demo show each as its own step - no Block does
|
|
28
|
+
more than one distinct action.
|
|
29
|
+
|
|
30
|
+
## Other
|
|
31
|
+
|
|
32
|
+
| File | Kind | Notes |
|
|
33
|
+
|------|------|-------|
|
|
34
|
+
| `ff-owner-auth.block.ts` | FFCompose | Collapses nav-login + fill-username + fill-password + submit-login into one opaque demo/run step (`--ff-expand` shows all 4 again) |
|
|
22
35
|
|
|
23
36
|
## Related mem keys / checkpoints
|
|
24
37
|
|
|
25
38
|
- Mem: `saucedemo.credentials` (`LoginCreds`)
|
|
26
39
|
- Checkpoints: `LoginPage`, `LoggedIn` (success path of submit-login)
|
|
40
|
+
- Sel: `LoginSel` (`methods/login.sel.ts`) - DOM only, not mem
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DOM selectors for the cart route (`/cart.html`) and its outbound nav
|
|
3
|
+
* controls. Convention: DOM strings live in `*Sel` next to the page, not
|
|
4
|
+
* inlined in each Block.
|
|
5
|
+
*/
|
|
6
|
+
export const CartSel = {
|
|
7
|
+
cartLink: ".shopping_cart_link",
|
|
8
|
+
checkoutBtn: "#checkout",
|
|
9
|
+
};
|
|
@@ -2,6 +2,7 @@ import { defineNavClickBlock, Trait } from "waygraph";
|
|
|
2
2
|
import type { StubCtx } from "waygraph";
|
|
3
3
|
import type { CartPage } from "../../../states/checkout.states.js";
|
|
4
4
|
import { InventorySel } from "../inventory/methods/inventory-items.js";
|
|
5
|
+
import { CartSel } from "./cart.sel.js";
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Kind: Nav
|
|
@@ -14,7 +15,7 @@ export const NavCartBlock = defineNavClickBlock<CartPage>({
|
|
|
14
15
|
name: "nav-cart",
|
|
15
16
|
description: "Clicks the cart link in the header.",
|
|
16
17
|
checkpoint: "CartPage",
|
|
17
|
-
click:
|
|
18
|
+
click: CartSel.cartLink,
|
|
18
19
|
verify: [Trait.url({ pathname: "/cart.html" })],
|
|
19
20
|
stubBefore: (ctx: StubCtx) => {
|
|
20
21
|
ctx.title("Open cart · landscape");
|
|
@@ -35,7 +36,7 @@ export const NavCartBlock = defineNavClickBlock<CartPage>({
|
|
|
35
36
|
ctx.zoomOut(false);
|
|
36
37
|
ctx.highlights({
|
|
37
38
|
cart: {
|
|
38
|
-
selector:
|
|
39
|
+
selector: CartSel.cartLink,
|
|
39
40
|
label: "Cart",
|
|
40
41
|
detail: "Open cart",
|
|
41
42
|
focus: true,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { defineNavClickBlock, Trait } from "waygraph";
|
|
2
2
|
import type { CheckoutInfoPage } from "../../../states/checkout.states.js";
|
|
3
|
+
import { CartSel } from "./cart.sel.js";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Kind: Nav
|
|
@@ -12,6 +13,6 @@ export const NavCheckoutInfoBlock = defineNavClickBlock<CheckoutInfoPage>({
|
|
|
12
13
|
name: "nav-checkout-info",
|
|
13
14
|
description: "Clicks 'Checkout' on the cart page.",
|
|
14
15
|
checkpoint: "CheckoutInfoPage",
|
|
15
|
-
click:
|
|
16
|
+
click: CartSel.checkoutBtn,
|
|
16
17
|
verify: [Trait.url({ pathname: "/checkout-step-one.html" })],
|
|
17
18
|
});
|
|
@@ -14,8 +14,13 @@ Shipping info form before order overview.
|
|
|
14
14
|
|
|
15
15
|
| File | Kind | Notes |
|
|
16
16
|
|------|------|-------|
|
|
17
|
-
| `methods/
|
|
17
|
+
| `methods/fill-first-name.method.block.ts` | Method | Fills first name only; self-loop on CheckoutInfoPage |
|
|
18
|
+
| `methods/fill-last-name.method.block.ts` | Method | Fills last name only; self-loop on CheckoutInfoPage |
|
|
19
|
+
| `methods/fill-postal-code.method.block.ts` | Method | Fills postal code only; self-loop on CheckoutInfoPage |
|
|
20
|
+
| `methods/submit-checkout-info.method.block.ts` | Method | Click Continue only -> overview |
|
|
21
|
+
| `methods/checkout-info.sel.ts` | helper | `CheckoutInfoSel` (not a Block) |
|
|
18
22
|
|
|
19
23
|
## Related mem keys / checkpoints
|
|
20
24
|
|
|
21
25
|
- Checkpoints: `CheckoutInfoPage`, `CheckoutOverviewPage`
|
|
26
|
+
- Sel: `CheckoutInfoSel` (`methods/checkout-info.sel.ts`) - DOM only, not mem
|
package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/checkout-info.sel.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DOM selectors for the shipping info form (`/checkout-step-one.html`).
|
|
3
|
+
* Convention: DOM strings live in `*Sel` next to the page, not inlined in
|
|
4
|
+
* each Block.
|
|
5
|
+
*/
|
|
6
|
+
export const CheckoutInfoSel = {
|
|
7
|
+
firstName: "#first-name",
|
|
8
|
+
lastName: "#last-name",
|
|
9
|
+
postalCode: "#postal-code",
|
|
10
|
+
continueBtn: "#continue",
|
|
11
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { defineMethodBlock, checkpoint } from "waygraph";
|
|
2
|
+
import type { CheckoutInfoPage } from "../../../../states/checkout.states.js";
|
|
3
|
+
import { CheckoutInfoSel } from "./checkout-info.sel.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Kind: Method
|
|
7
|
+
* Helper: defineMethodBlock
|
|
8
|
+
* Route: saucedemo-web/checkout-step-one/methods/ (= /checkout-step-one.html)
|
|
9
|
+
*
|
|
10
|
+
* Fills the first name field only - self-loop on CheckoutInfoPage. Continue
|
|
11
|
+
* is its own Block (submit-checkout-info.method.block.ts).
|
|
12
|
+
*/
|
|
13
|
+
export const FillFirstNameBlock = defineMethodBlock<CheckoutInfoPage, CheckoutInfoPage>({
|
|
14
|
+
name: "fill-first-name",
|
|
15
|
+
description: "Fills the first name field on the shipping info form.",
|
|
16
|
+
instruction: {
|
|
17
|
+
async act(page) {
|
|
18
|
+
await page.locator(CheckoutInfoSel.firstName).fill("Ada");
|
|
19
|
+
},
|
|
20
|
+
resolve: () => checkpoint("CheckoutInfoPage"),
|
|
21
|
+
},
|
|
22
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { defineMethodBlock, checkpoint } from "waygraph";
|
|
2
|
+
import type { CheckoutInfoPage } from "../../../../states/checkout.states.js";
|
|
3
|
+
import { CheckoutInfoSel } from "./checkout-info.sel.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Kind: Method
|
|
7
|
+
* Helper: defineMethodBlock
|
|
8
|
+
* Route: saucedemo-web/checkout-step-one/methods/ (= /checkout-step-one.html)
|
|
9
|
+
*
|
|
10
|
+
* Fills the last name field only - self-loop on CheckoutInfoPage.
|
|
11
|
+
*/
|
|
12
|
+
export const FillLastNameBlock = defineMethodBlock<CheckoutInfoPage, CheckoutInfoPage>({
|
|
13
|
+
name: "fill-last-name",
|
|
14
|
+
description: "Fills the last name field on the shipping info form.",
|
|
15
|
+
instruction: {
|
|
16
|
+
async act(page) {
|
|
17
|
+
await page.locator(CheckoutInfoSel.lastName).fill("Lovelace");
|
|
18
|
+
},
|
|
19
|
+
resolve: () => checkpoint("CheckoutInfoPage"),
|
|
20
|
+
},
|
|
21
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { defineMethodBlock, checkpoint } from "waygraph";
|
|
2
|
+
import type { CheckoutInfoPage } from "../../../../states/checkout.states.js";
|
|
3
|
+
import { CheckoutInfoSel } from "./checkout-info.sel.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Kind: Method
|
|
7
|
+
* Helper: defineMethodBlock
|
|
8
|
+
* Route: saucedemo-web/checkout-step-one/methods/ (= /checkout-step-one.html)
|
|
9
|
+
*
|
|
10
|
+
* Fills the postal code field only - self-loop on CheckoutInfoPage.
|
|
11
|
+
*/
|
|
12
|
+
export const FillPostalCodeBlock = defineMethodBlock<CheckoutInfoPage, CheckoutInfoPage>({
|
|
13
|
+
name: "fill-postal-code",
|
|
14
|
+
description: "Fills the postal code field on the shipping info form.",
|
|
15
|
+
instruction: {
|
|
16
|
+
async act(page) {
|
|
17
|
+
await page.locator(CheckoutInfoSel.postalCode).fill("1000");
|
|
18
|
+
},
|
|
19
|
+
resolve: () => checkpoint("CheckoutInfoPage"),
|
|
20
|
+
},
|
|
21
|
+
});
|
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
import { defineMethodBlock, checkpoint, Trait } from "waygraph";
|
|
2
2
|
import type { CheckoutInfoPage, CheckoutOverviewPage } from "../../../../states/checkout.states.js";
|
|
3
|
+
import { CheckoutInfoSel } from "./checkout-info.sel.js";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Kind: Method
|
|
6
7
|
* Helper: defineMethodBlock
|
|
7
8
|
* Route: saucedemo-web/checkout-step-one/methods/ (= /checkout-step-one.html)
|
|
8
9
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
10
|
+
* Clicks Continue only - fields are filled by fill-first-name /
|
|
11
|
+
* fill-last-name / fill-postal-code (each its own Block). One Block, one
|
|
12
|
+
* action: submit.
|
|
11
13
|
*/
|
|
12
14
|
export const SubmitCheckoutInfoBlock = defineMethodBlock<CheckoutInfoPage, CheckoutOverviewPage>({
|
|
13
15
|
name: "submit-checkout-info",
|
|
14
|
-
description: "
|
|
16
|
+
description: "Continues from the shipping info form to the order overview.",
|
|
15
17
|
instruction: {
|
|
16
18
|
async act(page) {
|
|
17
|
-
await page.locator(
|
|
18
|
-
await page.locator("#last-name").fill("Lovelace");
|
|
19
|
-
await page.locator("#postal-code").fill("1000");
|
|
20
|
-
await page.locator("#continue").click();
|
|
19
|
+
await page.locator(CheckoutInfoSel.continueBtn).click();
|
|
21
20
|
},
|
|
22
21
|
resolve: () => checkpoint("CheckoutOverviewPage"),
|
|
23
22
|
verify: [Trait.url({ pathname: "/checkout-step-two.html" })],
|
|
@@ -15,7 +15,9 @@ Order overview / finish page.
|
|
|
15
15
|
| File | Kind | Notes |
|
|
16
16
|
|------|------|-------|
|
|
17
17
|
| `methods/finish-order.method.block.ts` | Method | Finish -> thank-you / OrderComplete |
|
|
18
|
+
| `methods/checkout-overview.sel.ts` | helper | `CheckoutOverviewSel` (not a Block) |
|
|
18
19
|
|
|
19
20
|
## Related mem keys / checkpoints
|
|
20
21
|
|
|
21
22
|
- Checkpoints: `CheckoutOverviewPage`, `OrderComplete`
|
|
23
|
+
- Sel: `CheckoutOverviewSel` (`methods/checkout-overview.sel.ts`) - DOM only, not mem
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DOM selectors for the order overview / completion page
|
|
3
|
+
* (`/checkout-step-two.html`). Convention: DOM strings live in `*Sel` next
|
|
4
|
+
* to the page, not inlined in each Block.
|
|
5
|
+
*/
|
|
6
|
+
export const CheckoutOverviewSel = {
|
|
7
|
+
finishBtn: "#finish",
|
|
8
|
+
completeHeader: ".complete-header",
|
|
9
|
+
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { defineMethodBlock, checkpoint, Trait, narrate } from "waygraph";
|
|
2
2
|
import type { CheckoutOverviewPage, OrderComplete } from "../../../../states/checkout.states.js";
|
|
3
|
+
import { CheckoutOverviewSel } from "./checkout-overview.sel.js";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Kind: Method
|
|
@@ -13,17 +14,17 @@ export const FinishOrderBlock = defineMethodBlock<CheckoutOverviewPage, OrderCom
|
|
|
13
14
|
description: "Places the order and confirms the 'Thank you for your order!' completion page.",
|
|
14
15
|
instruction: {
|
|
15
16
|
async act(page) {
|
|
16
|
-
const finishButton = page.locator(
|
|
17
|
+
const finishButton = page.locator(CheckoutOverviewSel.finishBtn);
|
|
17
18
|
await narrate(finishButton, "Placing the order", () => finishButton.click());
|
|
18
19
|
},
|
|
19
20
|
resolve: () => checkpoint("OrderComplete"),
|
|
20
|
-
verify: [Trait.text(
|
|
21
|
+
verify: [Trait.text(CheckoutOverviewSel.completeHeader, "Thank you for your order!")],
|
|
21
22
|
stubBefore: {
|
|
22
|
-
finish: { selector:
|
|
23
|
+
finish: { selector: CheckoutOverviewSel.finishBtn, label: "Finish" },
|
|
23
24
|
},
|
|
24
25
|
stubAfter: {
|
|
25
26
|
thanks: {
|
|
26
|
-
selector:
|
|
27
|
+
selector: CheckoutOverviewSel.completeHeader,
|
|
27
28
|
label: "Order confirmed",
|
|
28
29
|
detail: "Thank you for your order!",
|
|
29
30
|
duration: true,
|
|
@@ -42,7 +43,7 @@ export const FinishOrderBlock = defineMethodBlock<CheckoutOverviewPage, OrderCom
|
|
|
42
43
|
caption: "Completion page is the durable proof",
|
|
43
44
|
detail: "The thank-you header is what verify asserts on.",
|
|
44
45
|
tag: "YAP",
|
|
45
|
-
selector:
|
|
46
|
+
selector: CheckoutOverviewSel.completeHeader,
|
|
46
47
|
duration: 2500,
|
|
47
48
|
fastMode: 700,
|
|
48
49
|
},
|
|
@@ -50,7 +51,7 @@ export const FinishOrderBlock = defineMethodBlock<CheckoutOverviewPage, OrderCom
|
|
|
50
51
|
caption: "Episode continues after this yap",
|
|
51
52
|
detail: "Next step rings the same banner, then you move on.",
|
|
52
53
|
tag: "YAP",
|
|
53
|
-
selector:
|
|
54
|
+
selector: CheckoutOverviewSel.completeHeader,
|
|
54
55
|
duration: true,
|
|
55
56
|
fastMode: 500,
|
|
56
57
|
},
|