waygraph 0.13.7 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +970 -232
- package/assets/stubs/stub.mp4 +0 -0
- package/assets/stubs/stub.pdf +32 -0
- package/assets/stubs/stub.png +0 -0
- package/dist/agent-dive.d.ts +9 -0
- package/dist/agent-dive.js +32 -0
- package/dist/auto-explore-run.d.ts +20 -2
- package/dist/auto-explore-run.js +9 -8
- package/dist/auto-explore.js +22 -2
- package/dist/auto-session-ipc.d.ts +123 -0
- package/dist/auto-session-ipc.js +381 -0
- package/dist/auto-session.d.ts +342 -0
- package/dist/auto-session.js +760 -0
- package/dist/cli.js +450 -51
- package/dist/engine.d.ts +201 -1
- package/dist/engine.js +312 -2
- package/dist/graph.d.ts +18 -0
- package/dist/graph.js +65 -2
- package/dist/highlights.d.ts +20 -1
- package/dist/highlights.js +60 -0
- package/dist/index.d.ts +8 -4
- package/dist/index.js +5 -3
- package/dist/map-check.d.ts +18 -0
- package/dist/map-check.js +140 -0
- package/dist/pilot-overlay.d.ts +88 -0
- package/dist/pilot-overlay.js +363 -0
- package/dist/pilot.d.ts +49 -0
- package/dist/pilot.js +53 -0
- package/dist/trait.d.ts +22 -0
- package/dist/trait.js +60 -3
- package/dist/types.d.ts +21 -1
- package/dist/types.js +17 -1
- package/examples/routed-demo/.waygraph-auto/4d4902b7.log +0 -0
- package/examples/routed-demo/.waygraph-auto/51ef462e.log +0 -0
- package/examples/routed-demo/.waygraph-auto/71527ad9.log +0 -0
- package/examples/routed-demo/.waygraph-auto/ca16778e.log +0 -0
- package/examples/routed-demo/package.json +26 -0
- package/examples/routed-demo/playwright.config.ts +20 -0
- package/examples/routed-demo/scripts/fixture-server.mjs +37 -0
- package/examples/routed-demo/scripts/with-fixture.mjs +70 -0
- package/examples/routed-demo/src/flows/routed-demo-map.flow.ts +39 -0
- package/examples/routed-demo/src/flows/routed-demo.flow.ts +12 -0
- package/examples/routed-demo/src/map/(app_base)/dashboard/_methods/click-widget.block.ts +23 -0
- package/examples/routed-demo/src/map/(app_base)/dashboard/_nav.block.ts +18 -0
- package/examples/routed-demo/src/map/(app_base)/dashboard/_page.block.ts +22 -0
- package/examples/routed-demo/src/map/(app_base)/dashboard/_sel.ts +10 -0
- package/examples/routed-demo/src/map/(external)/docs/_nav.block.ts +21 -0
- package/examples/routed-demo/src/map/(external)/docs/_page.block.ts +15 -0
- package/examples/routed-demo/src/map/(external)/docs/_sel.ts +7 -0
- package/examples/routed-demo/src/pages/dashboard.html +10 -0
- package/examples/routed-demo/src/pages/docs.html +8 -0
- package/examples/routed-demo/src/states/routed-demo.states.ts +10 -0
- package/examples/routed-demo/test-results/.last-run.json +4 -0
- package/examples/routed-demo/tests/routed-demo-map.spec.ts +17 -0
- package/examples/routed-demo/tests/routed-demo.spec.ts +75 -0
- package/examples/routed-demo/tsconfig.json +18 -0
- package/examples/routed-demo-consumer/package.json +18 -0
- package/examples/saucedemo/.waygraph-auto/00d5336e.log +0 -0
- package/examples/saucedemo/.waygraph-auto/010dd92b.log +0 -0
- package/examples/saucedemo/.waygraph-auto/011ad671.log +0 -0
- package/examples/saucedemo/.waygraph-auto/01b45645.log +0 -0
- package/examples/saucedemo/.waygraph-auto/03764153.log +0 -0
- package/examples/saucedemo/.waygraph-auto/0593587e.log +0 -0
- package/examples/saucedemo/.waygraph-auto/06d12823.log +0 -0
- package/examples/saucedemo/.waygraph-auto/083cc5b9.log +0 -0
- package/examples/saucedemo/.waygraph-auto/0b1f5b26.json +8 -0
- package/examples/saucedemo/.waygraph-auto/0c00f25f.log +0 -0
- package/examples/saucedemo/.waygraph-auto/0e480591.log +0 -0
- package/examples/saucedemo/.waygraph-auto/104751ef.log +0 -0
- package/examples/saucedemo/.waygraph-auto/110958b8.log +0 -0
- package/examples/saucedemo/.waygraph-auto/138107c1.log +0 -0
- package/examples/saucedemo/.waygraph-auto/159d541b.log +0 -0
- package/examples/saucedemo/.waygraph-auto/16aa2c01.log +0 -0
- package/examples/saucedemo/.waygraph-auto/16c35dd5.log +0 -0
- package/examples/saucedemo/.waygraph-auto/1706547d.log +0 -0
- package/examples/saucedemo/.waygraph-auto/17537e42.log +0 -0
- package/examples/saucedemo/.waygraph-auto/175655f7.log +0 -0
- package/examples/saucedemo/.waygraph-auto/17ede493.log +0 -0
- package/examples/saucedemo/.waygraph-auto/1fe2414f.log +0 -0
- package/examples/saucedemo/.waygraph-auto/1fe2e3b8.log +0 -0
- package/examples/saucedemo/.waygraph-auto/2219f00b.log +0 -0
- package/examples/saucedemo/.waygraph-auto/23e62571.log +0 -0
- package/examples/saucedemo/.waygraph-auto/25f68ada.log +0 -0
- package/examples/saucedemo/.waygraph-auto/26ca9cd8.log +0 -0
- package/examples/saucedemo/.waygraph-auto/2bb6c4e8.log +0 -0
- package/examples/saucedemo/.waygraph-auto/2d425004.log +0 -0
- package/examples/saucedemo/.waygraph-auto/2f5b3ea6.log +0 -0
- package/examples/saucedemo/.waygraph-auto/31bb303d.log +0 -0
- package/examples/saucedemo/.waygraph-auto/31f2042f.log +0 -0
- package/examples/saucedemo/.waygraph-auto/36551ec1.log +0 -0
- package/examples/saucedemo/.waygraph-auto/36a1c274.log +0 -0
- package/examples/saucedemo/.waygraph-auto/381aa338.log +0 -0
- package/examples/saucedemo/.waygraph-auto/3882bce1.log +0 -0
- package/examples/saucedemo/.waygraph-auto/38acd1dc.log +0 -0
- package/examples/saucedemo/.waygraph-auto/3b8b77b9.log +0 -0
- package/examples/saucedemo/.waygraph-auto/4028d2a2.log +0 -0
- package/examples/saucedemo/.waygraph-auto/4168b208.log +0 -0
- package/examples/saucedemo/.waygraph-auto/42cc9113.log +0 -0
- package/examples/saucedemo/.waygraph-auto/439d30aa.log +0 -0
- package/examples/saucedemo/.waygraph-auto/43ab66ce.log +0 -0
- package/examples/saucedemo/.waygraph-auto/43f66838.log +0 -0
- package/examples/saucedemo/.waygraph-auto/442171d4.log +0 -0
- package/examples/saucedemo/.waygraph-auto/453b1ce1.log +0 -0
- package/examples/saucedemo/.waygraph-auto/457322bd.log +0 -0
- package/examples/saucedemo/.waygraph-auto/46197027.log +0 -0
- package/examples/saucedemo/.waygraph-auto/46889468.log +0 -0
- package/examples/saucedemo/.waygraph-auto/4890da1c.log +0 -0
- package/examples/saucedemo/.waygraph-auto/4893a63b.log +0 -0
- package/examples/saucedemo/.waygraph-auto/4a85f496.log +0 -0
- package/examples/saucedemo/.waygraph-auto/4af71440.log +0 -0
- package/examples/saucedemo/.waygraph-auto/4f7496d1.log +0 -0
- package/examples/saucedemo/.waygraph-auto/50e8baaa.log +0 -0
- package/examples/saucedemo/.waygraph-auto/52b3a455.log +0 -0
- package/examples/saucedemo/.waygraph-auto/532dd9b8.log +0 -0
- package/examples/saucedemo/.waygraph-auto/5391ce40.log +0 -0
- package/examples/saucedemo/.waygraph-auto/57dbddb3.log +0 -0
- package/examples/saucedemo/.waygraph-auto/5897f501.log +0 -0
- package/examples/saucedemo/.waygraph-auto/59c0b57d.log +0 -0
- package/examples/saucedemo/.waygraph-auto/5b511794.log +0 -0
- package/examples/saucedemo/.waygraph-auto/5c0eef7f.log +0 -0
- package/examples/saucedemo/.waygraph-auto/5c47910f.log +0 -0
- package/examples/saucedemo/.waygraph-auto/5d60da77.log +0 -0
- package/examples/saucedemo/.waygraph-auto/5eda8273.log +0 -0
- package/examples/saucedemo/.waygraph-auto/5fc3a33b.log +0 -0
- package/examples/saucedemo/.waygraph-auto/61b6546d.log +0 -0
- package/examples/saucedemo/.waygraph-auto/621518ad.log +0 -0
- package/examples/saucedemo/.waygraph-auto/632b7118.log +0 -0
- package/examples/saucedemo/.waygraph-auto/64314c2b.log +0 -0
- package/examples/saucedemo/.waygraph-auto/650ed066.log +0 -0
- package/examples/saucedemo/.waygraph-auto/66516213.log +0 -0
- package/examples/saucedemo/.waygraph-auto/66c17079.log +0 -0
- package/examples/saucedemo/.waygraph-auto/69bf0b80.log +0 -0
- package/examples/saucedemo/.waygraph-auto/69c2347a.log +0 -0
- package/examples/saucedemo/.waygraph-auto/6d22bdb0.log +0 -0
- package/examples/saucedemo/.waygraph-auto/6d9aaad3.log +0 -0
- package/examples/saucedemo/.waygraph-auto/7103bebb.log +0 -0
- package/examples/saucedemo/.waygraph-auto/740c9faa.log +0 -0
- package/examples/saucedemo/.waygraph-auto/74872fc5.log +0 -0
- package/examples/saucedemo/.waygraph-auto/75846ca9.log +0 -0
- package/examples/saucedemo/.waygraph-auto/7626c85b.log +0 -0
- package/examples/saucedemo/.waygraph-auto/76308eec.log +0 -0
- package/examples/saucedemo/.waygraph-auto/76c1650e.log +0 -0
- package/examples/saucedemo/.waygraph-auto/7861f38f.log +0 -0
- package/examples/saucedemo/.waygraph-auto/78b21219.log +0 -0
- package/examples/saucedemo/.waygraph-auto/7af224ed.log +0 -0
- package/examples/saucedemo/.waygraph-auto/7c3be585.log +0 -0
- package/examples/saucedemo/.waygraph-auto/7ed55a2c.log +0 -0
- package/examples/saucedemo/.waygraph-auto/80086ba2.log +0 -0
- package/examples/saucedemo/.waygraph-auto/80206369.log +0 -0
- package/examples/saucedemo/.waygraph-auto/847f1092.log +0 -0
- package/examples/saucedemo/.waygraph-auto/84d6d293.log +0 -0
- package/examples/saucedemo/.waygraph-auto/8581abfa.log +0 -0
- package/examples/saucedemo/.waygraph-auto/87b7e0fd.log +0 -0
- package/examples/saucedemo/.waygraph-auto/87c79256.log +0 -0
- package/examples/saucedemo/.waygraph-auto/88af2495.log +0 -0
- package/examples/saucedemo/.waygraph-auto/8a3eb088.log +0 -0
- package/examples/saucedemo/.waygraph-auto/8c04a403.log +0 -0
- package/examples/saucedemo/.waygraph-auto/8c9ab09e.log +0 -0
- package/examples/saucedemo/.waygraph-auto/8cc5db51.log +0 -0
- package/examples/saucedemo/.waygraph-auto/8ea3a69c.log +0 -0
- package/examples/saucedemo/.waygraph-auto/9150f913.log +0 -0
- package/examples/saucedemo/.waygraph-auto/929a4313.log +0 -0
- package/examples/saucedemo/.waygraph-auto/95a599e4.log +0 -0
- package/examples/saucedemo/.waygraph-auto/96c45350.log +0 -0
- package/examples/saucedemo/.waygraph-auto/986030e6.log +0 -0
- package/examples/saucedemo/.waygraph-auto/99787abb.log +0 -0
- package/examples/saucedemo/.waygraph-auto/99ddb62c.log +0 -0
- package/examples/saucedemo/.waygraph-auto/a2dd30dd.log +0 -0
- package/examples/saucedemo/.waygraph-auto/a63a2d20.log +0 -0
- package/examples/saucedemo/.waygraph-auto/a78befb7.log +0 -0
- package/examples/saucedemo/.waygraph-auto/a84d9b79.log +0 -0
- package/examples/saucedemo/.waygraph-auto/a87bb3ee.log +0 -0
- package/examples/saucedemo/.waygraph-auto/a9270890.log +0 -0
- package/examples/saucedemo/.waygraph-auto/aa440153.log +0 -0
- package/examples/saucedemo/.waygraph-auto/ab7561e0.log +0 -0
- package/examples/saucedemo/.waygraph-auto/ac19ae60.log +0 -0
- package/examples/saucedemo/.waygraph-auto/ae21ad8e.log +0 -0
- package/examples/saucedemo/.waygraph-auto/af09042f.log +0 -0
- package/examples/saucedemo/.waygraph-auto/b1684126.log +0 -0
- package/examples/saucedemo/.waygraph-auto/b21e9d12.log +0 -0
- package/examples/saucedemo/.waygraph-auto/b5a838be.log +0 -0
- package/examples/saucedemo/.waygraph-auto/b603549d.log +0 -0
- package/examples/saucedemo/.waygraph-auto/b81e074f.log +0 -0
- package/examples/saucedemo/.waygraph-auto/b83e6259.log +0 -0
- package/examples/saucedemo/.waygraph-auto/b9cb2796.log +0 -0
- package/examples/saucedemo/.waygraph-auto/ba58abb7.log +0 -0
- package/examples/saucedemo/.waygraph-auto/bb0a0018.log +0 -0
- package/examples/saucedemo/.waygraph-auto/bb9fd384.log +0 -0
- package/examples/saucedemo/.waygraph-auto/bc0bdd0e.log +0 -0
- package/examples/saucedemo/.waygraph-auto/bc7d4a83.log +0 -0
- package/examples/saucedemo/.waygraph-auto/bd8e082a.log +0 -0
- package/examples/saucedemo/.waygraph-auto/bea0c93e.log +0 -0
- package/examples/saucedemo/.waygraph-auto/bf35201a.log +0 -0
- package/examples/saucedemo/.waygraph-auto/bffa3a7a.log +0 -0
- package/examples/saucedemo/.waygraph-auto/c02ea583.log +0 -0
- package/examples/saucedemo/.waygraph-auto/c2caf0a8.log +0 -0
- package/examples/saucedemo/.waygraph-auto/c3bdc714.log +0 -0
- package/examples/saucedemo/.waygraph-auto/c4afb8bc.log +0 -0
- package/examples/saucedemo/.waygraph-auto/c916a654.log +0 -0
- package/examples/saucedemo/.waygraph-auto/c9b8d69e.log +0 -0
- package/examples/saucedemo/.waygraph-auto/cd68bbc4.log +0 -0
- package/examples/saucedemo/.waygraph-auto/cdc6db50.log +0 -0
- package/examples/saucedemo/.waygraph-auto/d01906a7.log +0 -0
- package/examples/saucedemo/.waygraph-auto/d02e5e7e.log +0 -0
- package/examples/saucedemo/.waygraph-auto/d09aff71.log +0 -0
- package/examples/saucedemo/.waygraph-auto/d0e41396.log +0 -0
- package/examples/saucedemo/.waygraph-auto/d1370d76.log +0 -0
- package/examples/saucedemo/.waygraph-auto/d3714ae4.log +0 -0
- package/examples/saucedemo/.waygraph-auto/d9e5f8a4.log +0 -0
- package/examples/saucedemo/.waygraph-auto/da0685dc.log +0 -0
- package/examples/saucedemo/.waygraph-auto/da894ad8.log +0 -0
- package/examples/saucedemo/.waygraph-auto/daa2f922.log +0 -0
- package/examples/saucedemo/.waygraph-auto/daefb614.log +0 -0
- package/examples/saucedemo/.waygraph-auto/db97e833.log +0 -0
- package/examples/saucedemo/.waygraph-auto/dec3076e.log +0 -0
- package/examples/saucedemo/.waygraph-auto/e101d19a.log +0 -0
- package/examples/saucedemo/.waygraph-auto/e1973991.log +0 -0
- package/examples/saucedemo/.waygraph-auto/e207c989.log +0 -0
- package/examples/saucedemo/.waygraph-auto/e633e545.log +0 -0
- package/examples/saucedemo/.waygraph-auto/e69aec68.log +0 -0
- package/examples/saucedemo/.waygraph-auto/e70e2d06.log +0 -0
- package/examples/saucedemo/.waygraph-auto/e8306a4b.log +0 -0
- package/examples/saucedemo/.waygraph-auto/ebad3410.log +0 -0
- package/examples/saucedemo/.waygraph-auto/ec88b3ef.log +0 -0
- package/examples/saucedemo/.waygraph-auto/ecbb0966.log +0 -0
- package/examples/saucedemo/.waygraph-auto/ecdee753.log +0 -0
- package/examples/saucedemo/.waygraph-auto/ed888783.log +0 -0
- package/examples/saucedemo/.waygraph-auto/ed931dac.log +0 -0
- package/examples/saucedemo/.waygraph-auto/ef655a3f.log +0 -0
- package/examples/saucedemo/.waygraph-auto/f34c9a26.log +0 -0
- package/examples/saucedemo/.waygraph-auto/f3c29b21.log +0 -0
- package/examples/saucedemo/.waygraph-auto/f53f7cfc.log +0 -0
- package/examples/saucedemo/.waygraph-auto/f5525d53.log +0 -0
- package/examples/saucedemo/.waygraph-auto/f5ad5830.log +0 -0
- package/examples/saucedemo/.waygraph-auto/f90035b3.log +0 -0
- package/examples/saucedemo/.waygraph-auto/fa687bc2.log +0 -0
- package/examples/saucedemo/.waygraph-auto/faed36dd.log +0 -0
- package/examples/saucedemo/.waygraph-auto/fb66fba0.log +0 -0
- package/examples/saucedemo/.waygraph-auto/fc48fd76.log +0 -0
- package/examples/saucedemo/docs/CONVENTION.md +25 -5
- package/examples/saucedemo/docs/HELPERS.md +15 -4
- package/examples/saucedemo/scripts/capture-wrong-login.mjs +8 -2
- package/examples/saucedemo/scripts/prove-wrong-login-runtime.mjs +8 -2
- package/examples/saucedemo/src/blocks/SITE-MAP.md +14 -3
- package/examples/saucedemo/src/blocks/saucedemo-web/NAV.md +15 -1
- package/examples/saucedemo/src/blocks/saucedemo-web/cart/NAV.md +1 -0
- package/examples/saucedemo/src/blocks/saucedemo-web/cart/cart.sel.ts +9 -0
- package/examples/saucedemo/src/blocks/saucedemo-web/cart/nav-cart.block.ts +3 -2
- package/examples/saucedemo/src/blocks/saucedemo-web/cart/nav-checkout-info.block.ts +2 -1
- package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/NAV.md +6 -1
- package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/checkout-info.sel.ts +11 -0
- package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/fill-first-name.method.block.ts +22 -0
- package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/fill-last-name.method.block.ts +21 -0
- package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/fill-postal-code.method.block.ts +21 -0
- package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/submit-checkout-info.method.block.ts +6 -7
- package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-two/NAV.md +2 -0
- package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-two/methods/checkout-overview.sel.ts +9 -0
- package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.ts +7 -6
- package/examples/saucedemo/src/blocks/saucedemo-web/ff-owner-auth.block.ts +7 -2
- package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/NAV.md +1 -0
- package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/item-detail.sel.ts +9 -0
- package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/nav-back-to-inventory.block.ts +2 -1
- package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/nav-back-to-products.block.ts +2 -1
- package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/nav-continue-shopping.block.ts +2 -1
- package/examples/saucedemo/src/blocks/saucedemo-web/methods/fill-password.method.block.ts +51 -0
- package/examples/saucedemo/src/blocks/saucedemo-web/methods/fill-username.method.block.ts +69 -0
- package/examples/saucedemo/src/blocks/saucedemo-web/methods/login.sel.ts +13 -0
- package/examples/saucedemo/src/blocks/saucedemo-web/methods/submit-login-for-flow.ts +4 -4
- package/examples/saucedemo/src/blocks/saucedemo-web/methods/submit-login.method.block.ts +13 -51
- package/examples/saucedemo/src/blocks/saucedemo-web/methods/submit-logout.method.block.ts +4 -3
- package/examples/saucedemo/src/blocks/saucedemo-web/nav-login.block.ts +14 -6
- package/examples/saucedemo/src/flows/checkout-then-browse-again.flow.ts +15 -0
- package/examples/saucedemo/src/flows/checkout.flow.ts +20 -2
- package/examples/saucedemo/src/flows/device-showcase.flow.ts +4 -0
- package/examples/saucedemo/src/flows/login.flow.ts +3 -1
- package/examples/saucedemo/src/flows/shop.flow.ts +6 -0
- package/examples/saucedemo/src/flows/smoke.flow.ts +13 -7
- package/examples/saucedemo/src/flows/stub-on-error.flow.ts +4 -2
- package/examples/saucedemo/src/flows/viewer-blocked.flow.ts +6 -2
- package/examples/saucedemo/tests/flow-block-verify.spec.ts +3 -3
- package/examples/saucedemo/tests/submit-login-branch.spec.ts +5 -3
- package/package.json +2 -1
- package/templates/agents/waygraph-author.agent.md +43 -5
- package/templates/agents/waygraph-planner.agent.md +33 -2
- package/templates/quickstart/src/blocks/saucedemo-web/NAV.md +15 -1
- package/templates/quickstart/src/blocks/saucedemo-web/cart/NAV.md +1 -0
- package/templates/quickstart/src/blocks/saucedemo-web/cart/cart.sel.ts +9 -0
- package/templates/quickstart/src/blocks/saucedemo-web/cart/nav-cart.block.ts +19 -15
- package/templates/quickstart/src/blocks/saucedemo-web/cart/nav-checkout-info.block.ts +2 -1
- package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/NAV.md +6 -1
- package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/checkout-info.sel.ts +11 -0
- package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/fill-first-name.method.block.ts +22 -0
- package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/fill-last-name.method.block.ts +21 -0
- package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/fill-postal-code.method.block.ts +21 -0
- package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/submit-checkout-info.method.block.ts +6 -7
- package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-two/NAV.md +2 -0
- package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-two/methods/checkout-overview.sel.ts +9 -0
- package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.ts +7 -6
- package/templates/quickstart/src/blocks/saucedemo-web/ff-owner-auth.block.ts +7 -2
- package/templates/quickstart/src/blocks/saucedemo-web/inventory/methods/add-to-cart.effect.block.ts +24 -16
- package/templates/quickstart/src/blocks/saucedemo-web/inventory/nav-item-detail.block.ts +3 -3
- package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/NAV.md +1 -0
- package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/item-detail.sel.ts +9 -0
- package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/nav-back-to-inventory.block.ts +2 -1
- package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/nav-back-to-products.block.ts +2 -1
- package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/nav-continue-shopping.block.ts +2 -1
- package/templates/quickstart/src/blocks/saucedemo-web/methods/fill-password.method.block.ts +51 -0
- package/templates/quickstart/src/blocks/saucedemo-web/methods/fill-username.method.block.ts +69 -0
- package/templates/quickstart/src/blocks/saucedemo-web/methods/login.sel.ts +13 -0
- package/templates/quickstart/src/blocks/saucedemo-web/methods/submit-login-for-flow.ts +4 -4
- package/templates/quickstart/src/blocks/saucedemo-web/methods/submit-login.method.block.ts +35 -63
- package/templates/quickstart/src/blocks/saucedemo-web/methods/submit-logout.method.block.ts +4 -3
- package/templates/quickstart/src/blocks/saucedemo-web/nav-login.block.ts +14 -6
- package/templates/quickstart/src/flows/checkout-then-browse-again.flow.ts +15 -0
- package/templates/quickstart/src/flows/checkout.flow.ts +29 -2
- package/templates/quickstart/src/flows/device-showcase.flow.ts +4 -0
- package/templates/quickstart/src/flows/login.flow.ts +3 -1
- package/templates/quickstart/src/flows/shop.flow.ts +6 -0
- package/templates/quickstart/src/flows/smoke.flow.ts +13 -7
- package/templates/quickstart/src/flows/viewer-blocked.flow.ts +6 -2
- package/templates/quickstart/tests/chain-flow.spec.ts +8 -1
- package/templates/scaffold/STRUCTURE.md +23 -3
- package/templates/scaffold/scripts/fixture-server.mjs +11 -2
- package/templates/scaffold/src/flows/example.flow.ts +8 -6
- package/templates/scaffold/src/flows/mail-verify.flow.ts +85 -0
- package/templates/scaffold/src/flows/shop.flow.ts +23 -6
- package/templates/scaffold/src/map/(app_base)/docs/_nav.block.ts +20 -0
- package/templates/scaffold/src/map/(app_base)/docs/_page.block.ts +15 -0
- package/templates/scaffold/src/map/(app_base)/docs/_sel.ts +7 -0
- package/templates/scaffold/src/map/(app_base)/docs/docs.html +8 -0
- package/templates/scaffold/src/{blocks/demo-web/methods → map/(app_base)/home/_methods}/add-item.effect.block.ts +3 -3
- package/templates/scaffold/src/map/(app_base)/home/_methods/assert-hello.method.block.ts +46 -0
- package/templates/scaffold/src/map/(app_base)/home/_methods/assert-item-added.method.block.ts +38 -0
- package/templates/scaffold/src/{blocks/demo-web/methods → map/(app_base)/home/_methods}/clear-cart.method.block.ts +9 -3
- package/templates/scaffold/src/{blocks/demo-web/methods → map/(app_base)/home/_methods}/remove-item.effect.block.ts +3 -3
- package/templates/scaffold/src/{blocks/demo-web/nav-home.block.ts → map/(app_base)/home/_nav.block.ts} +2 -2
- package/templates/scaffold/src/{blocks/demo-web/home.page.block.ts → map/(app_base)/home/_page.block.ts} +7 -7
- package/templates/scaffold/src/{blocks/demo-web/demo-sel.ts → map/(app_base)/home/_sel.ts} +1 -0
- package/templates/scaffold/src/{blocks/demo-web → map/(app_base)/home}/home.html +4 -0
- package/templates/scaffold/src/map/(app_base)/home/nav-verification-link.block.ts +34 -0
- package/templates/scaffold/src/map/(external)/mailpit/_methods/assert-email-content.method.block.ts +48 -0
- package/templates/scaffold/src/map/(external)/mailpit/_methods/assert-email-received.method.block.ts +49 -0
- package/templates/scaffold/src/map/(external)/mailpit/_methods/extract-email-link.method.block.ts +41 -0
- package/templates/scaffold/src/map/(external)/mailpit/_methods/open-message.method.block.ts +39 -0
- package/templates/scaffold/src/map/(external)/mailpit/_nav.block.ts +20 -0
- package/templates/scaffold/src/map/(external)/mailpit/_page.block.ts +30 -0
- package/templates/scaffold/src/map/(external)/mailpit/_sel.ts +5 -0
- package/templates/scaffold/src/states/demo.mem-keys.ts +25 -1
- package/templates/scaffold/src/states/demo.states.ts +11 -0
- package/templates/scaffold/test-results/.last-run.json +4 -0
- package/templates/scaffold/tests/example.spec.ts +2 -2
- package/templates/scaffold/tests/mail-verify.spec.ts +191 -0
- package/templates/skills/waygraph-blind-pilot.skill.md +61 -0
- package/templates/skills/waygraph-pilot.skill.md +108 -0
- package/templates/quickstart/README-saucedemo-commands.md +0 -72
- package/templates/scaffold/src/blocks/SITE-MAP.md +0 -12
- package/templates/scaffold/src/blocks/demo-web/NAV.md +0 -29
- package/templates/scaffold/src/blocks/demo-web/methods/assert-hello.method.block.ts +0 -50
|
@@ -1,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
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { Engine, start, end, withTitle, withSessionReset, withExpectedFailure } from "waygraph";
|
|
2
2
|
import { NavLoginBlock } from "../blocks/saucedemo-web/nav-login.block.js";
|
|
3
|
-
import {
|
|
3
|
+
import { FillUsernameBlock } from "../blocks/saucedemo-web/methods/fill-username.method.block.js";
|
|
4
|
+
import { FillPasswordBlock } from "../blocks/saucedemo-web/methods/fill-password.method.block.js";
|
|
5
|
+
import { SubmitLoginBlock } from "../blocks/saucedemo-web/methods/submit-login.method.block.js";
|
|
4
6
|
|
|
5
7
|
const engine = new Engine();
|
|
6
8
|
|
|
@@ -22,7 +24,9 @@ const engine = new Engine();
|
|
|
22
24
|
// "expected outcome" panel (branching no longer throws).
|
|
23
25
|
export const viewerBlockedFlow = withExpectedFailure(
|
|
24
26
|
withTitle(
|
|
25
|
-
withSessionReset(
|
|
27
|
+
withSessionReset(
|
|
28
|
+
engine.defineFlow([start, NavLoginBlock, FillUsernameBlock, FillPasswordBlock, SubmitLoginBlock, end]),
|
|
29
|
+
),
|
|
26
30
|
"Viewer: Blocked Login Attempt",
|
|
27
31
|
),
|
|
28
32
|
"locked_out_user stays on LoginPage with the error banner - this is the product working as intended.",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { test, expect } from "@playwright/test";
|
|
2
2
|
import { MemPage, checkpoint, Trait } from "waygraph";
|
|
3
3
|
import { checkoutFlow } from "../src/flows/checkout.flow.js";
|
|
4
|
-
import {
|
|
4
|
+
import { SubmitLoginBlock } from "../src/blocks/saucedemo-web/methods/submit-login.method.block.js";
|
|
5
5
|
import { LoginCreds, SelectedItem } from "../src/states/checkout.mem-keys.js";
|
|
6
6
|
|
|
7
7
|
// checkoutFlow.withBlockVerify/modBlockVerify - a spec that only imports the
|
|
@@ -31,9 +31,9 @@ test("withBlockVerify: replacing login's verify with an extra real check still p
|
|
|
31
31
|
mem.set(LoginCreds({ username: "standard_user", password: "secret_sauce" }));
|
|
32
32
|
mem.set(SelectedItem({ id: "sauce-labs-backpack", name: "Sauce Labs Backpack" }));
|
|
33
33
|
|
|
34
|
-
// Addressed by the actual
|
|
34
|
+
// Addressed by the actual SubmitLoginBlock reference - the preferred
|
|
35
35
|
// form: no typo risk, refactor-safe, jump-to-definition works.
|
|
36
|
-
const patched = checkoutFlow.withBlockVerify(
|
|
36
|
+
const patched = checkoutFlow.withBlockVerify(SubmitLoginBlock, [
|
|
37
37
|
Trait.url({ pathname: "/inventory.html" }),
|
|
38
38
|
Trait.visible(".inventory_list"),
|
|
39
39
|
]);
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { test, expect } from "@playwright/test";
|
|
2
2
|
import { MemPage, Engine, start, end } from "waygraph";
|
|
3
3
|
import { NavLoginBlock } from "../src/blocks/saucedemo-web/nav-login.block.js";
|
|
4
|
-
import {
|
|
4
|
+
import { FillUsernameBlock } from "../src/blocks/saucedemo-web/methods/fill-username.method.block.js";
|
|
5
|
+
import { FillPasswordBlock } from "../src/blocks/saucedemo-web/methods/fill-password.method.block.js";
|
|
6
|
+
import { SubmitLoginBlock } from "../src/blocks/saucedemo-web/methods/submit-login.method.block.js";
|
|
5
7
|
import { LoginCreds } from "../src/states/checkout.mem-keys.js";
|
|
6
8
|
|
|
7
9
|
test("submit-login: wrong password branches to LoginPage with error banner", async () => {
|
|
@@ -9,7 +11,7 @@ test("submit-login: wrong password branches to LoginPage with error banner", asy
|
|
|
9
11
|
mem.set(LoginCreds({ username: "standard_user", password: "wrong-password" }));
|
|
10
12
|
|
|
11
13
|
const engine = new Engine();
|
|
12
|
-
const flow = engine.defineFlow([start, NavLoginBlock,
|
|
14
|
+
const flow = engine.defineFlow([start, NavLoginBlock, FillUsernameBlock, FillPasswordBlock, SubmitLoginBlock, end]);
|
|
13
15
|
const result = await flow.run(mem);
|
|
14
16
|
|
|
15
17
|
expect(result.__state).toBe("LoginPage");
|
|
@@ -20,7 +22,7 @@ test("submit-login: good password branches to LoggedIn", async () => {
|
|
|
20
22
|
mem.set(LoginCreds({ username: "standard_user", password: "secret_sauce" }));
|
|
21
23
|
|
|
22
24
|
const engine = new Engine();
|
|
23
|
-
const flow = engine.defineFlow([start, NavLoginBlock,
|
|
25
|
+
const flow = engine.defineFlow([start, NavLoginBlock, FillUsernameBlock, FillPasswordBlock, SubmitLoginBlock, end]);
|
|
24
26
|
const result = await flow.run(mem);
|
|
25
27
|
|
|
26
28
|
expect(result.__state).toBe("LoggedIn");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "waygraph",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A typed graph of reusable Blocks for driving a browser through E2E flows.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"bin",
|
|
21
21
|
"templates",
|
|
22
22
|
"examples",
|
|
23
|
+
"assets",
|
|
23
24
|
"!examples/**/.tmp",
|
|
24
25
|
"!examples/**/.tmp/**",
|
|
25
26
|
"!examples/**/.waygraph-traverse",
|
|
@@ -13,11 +13,43 @@ You are a waygraph block author. Implement Blocks and Flows that match the consu
|
|
|
13
13
|
## Rules
|
|
14
14
|
|
|
15
15
|
1. One concern per file: `nav-*.block.ts`, `*.page.block.ts`, `*.method.block.ts`, `*.effect.block.ts`, `*.flow.ts`.
|
|
16
|
-
2.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
2. **One distinct action per Block - hard rule, not a style preference.** A Method/Effect that
|
|
17
|
+
fills form fields *and* submits, or that drives a multi-step sequence inside one `act()`,
|
|
18
|
+
is wrong even if it "works" - split it into separate atomic Blocks. Concretely: a login
|
|
19
|
+
form is `fill-username` (self-loop) + `fill-password` (self-loop) + `submit-login` (the
|
|
20
|
+
real transition), never one Block doing all three. See `examples/saucedemo/src/blocks/saucedemo-web/methods/`
|
|
21
|
+
(`fill-username.method.block.ts`, `fill-password.method.block.ts`,
|
|
22
|
+
`submit-login.method.block.ts`) for the canonical before/after shape - `submit-login`
|
|
23
|
+
used to also fill both fields; now it only clicks. A Block that only asserts something on
|
|
24
|
+
the current page (no state change) is `defineAssertBlock({ name, checkpoint, verify,
|
|
25
|
+
requires? })` - self-loop and `resolve` are generated for you, so there is no hand-written
|
|
26
|
+
`act`/`resolve` to accidentally make do two things. Give it an explicit type argument
|
|
27
|
+
(`defineAssertBlock<LoggedIn>({...})`) whenever it is not the last Block before `end` -
|
|
28
|
+
without one it defaults to wildcard `Checkpoint<string>`, which breaks `defineFlow`'s
|
|
29
|
+
tuple typing once the assert sits between two specifically-typed Blocks.
|
|
30
|
+
3. Navigation only inside `defineNavBlock` / `defineNavClickBlock`. Regular Method/Effect `act` uses ActionPage (no goto).
|
|
31
|
+
4. Effects that appear in `waygraph auto` menus need `instanceOptions` that scan the live DOM (or mem) for labeled rows.
|
|
32
|
+
5. Stubs: `stubBefore` / `stubAfter` / `stubOnError` for demo narration; YAP slides on Methods when useful; flow fixtures via `withHighlightFixtures` when AC copy is flow-specific.
|
|
33
|
+
6. Mem: `requires` lists keys the block needs; seed via `--data` / `WAYGRAPH_DATA` / project defaults - never assume saucedemo creds for email keys. A key an *earlier Block in the same chain* produces (not the caller) is never declared under `requires` - `requires` means externally supplied, and preflight checks the whole chain up front, before any Block runs.
|
|
34
|
+
7. **External Mailpit/MailHog: nav to inbox URL from env; Methods open message / read or click
|
|
35
|
+
the link; never put mail UI under `*-web/`.** Read the message via `page.locator`/
|
|
36
|
+
`page.frameLocator` DOM calls, never the catcher's REST API - zero new engine surface, and
|
|
37
|
+
it's narratable in `waygraph demo`/`auto`. Live, proven reference:
|
|
38
|
+
`templates/scaffold/src/blocks/demo-external/mailpit/` + `mail-verify.flow.ts`. Match a
|
|
39
|
+
specific inbox row by a mem-supplied recipient, not inbox position (a shared inbox across
|
|
40
|
+
runs can hold mail for more than one recipient). **Build the mail-reading Blocks
|
|
41
|
+
scenario-agnostic from the start**, not one Block set per email type: put the
|
|
42
|
+
link-matching pattern and expected body copy in mem too (alongside the recipient), so the
|
|
43
|
+
same fixed Blocks serve signup confirmation, password reset, magic link, etc. - a Block
|
|
44
|
+
named for one scenario (`extract-verification-link`) is a sign it should instead be named
|
|
45
|
+
for its mechanism (`extract-email-link`) and driven by mem. For asserting the message
|
|
46
|
+
*body* content (not just that a link exists), the top-level page's own `Trait.text`/
|
|
47
|
+
`Trait.visible` cannot see inside the preview iframe at all - use `Trait.frameVisible`/
|
|
48
|
+
`Trait.frameText`/`Trait.frameContains` (or a bespoke mem-aware `{ name, check(page, mem) }`
|
|
49
|
+
Trait when the expected value itself must vary per run).
|
|
50
|
+
8. `verify`/`defineAssertBlock` selectors live in a `*Sel` object next to the route, never
|
|
51
|
+
inlined as a literal string in `Trait.visible(...)`/`Trait.text(...)` - `waygraph check`
|
|
52
|
+
warns on this (see below); fix by moving the string into that route's `*Sel`.
|
|
21
53
|
|
|
22
54
|
## Verify locally
|
|
23
55
|
|
|
@@ -31,6 +63,12 @@ npx playwright test
|
|
|
31
63
|
npm run auto # or: npx waygraph auto --cli
|
|
32
64
|
```
|
|
33
65
|
|
|
66
|
+
**Do not report this work done until `waygraph check .` shows zero orphan Blocks and zero
|
|
67
|
+
inline-selector warnings, and zero nav-escape warnings for anything you touched.** A nonzero
|
|
68
|
+
count in any of those three is not an informational note to mention and move past - it means
|
|
69
|
+
go fix it first (wire the orphan into a `.flow.ts`, move the inline selector into `*Sel`, or
|
|
70
|
+
move the escaping navigation into a `defineNavBlock`), then re-run `check`.
|
|
71
|
+
|
|
34
72
|
## Output
|
|
35
73
|
|
|
36
74
|
Ship compiling TypeScript under `src/blocks/` + `src/flows/` + `src/states/`. Update NAV.md when edges change. Keep STRUCTURE / SITE-MAP honest.
|
|
@@ -17,7 +17,12 @@ You are a waygraph planner. Your job is to dive an existing app and produce a SI
|
|
|
17
17
|
3. **Block kinds:**
|
|
18
18
|
- Nav — `defineNavBlock` / `defineNavClickBlock` — only place for `page.goto` / click-nav
|
|
19
19
|
- Page — `definePageBlock` hub + `methods` registry
|
|
20
|
-
- Method
|
|
20
|
+
- Method - one same-URL action (a single form field fill, a single submit/click) - never
|
|
21
|
+
"fill several fields and submit" in one Block; each of those is its own Method
|
|
22
|
+
- Assert - `defineAssertBlock` - a same-URL check with no state change (self-loop);
|
|
23
|
+
prefer this over a hand-written Method for pure assertions, since `resolve` is generated
|
|
24
|
+
for you. Accepts `requires` like every other helper, for a mem-aware Trait's externally
|
|
25
|
+
-supplied input.
|
|
21
26
|
- Effect — `defineEffectBlock` + `instanceOptions` for per-row auto menus (add/remove/toggle)
|
|
22
27
|
4. **Mem keys:** typed `key` / `keyGroup`. Never rely on substring `"login"` defaults — email keys like `login-email` stay strings; credential objects use exact names such as `saucedemo.credentials` / `login-credentials`.
|
|
23
28
|
5. Prefer `click` NavBlocks when the product has a real control; use `url` for deep links / email tokens.
|
|
@@ -27,9 +32,35 @@ You are a waygraph planner. Your job is to dive an existing app and produce a SI
|
|
|
27
32
|
1. Read the app router (Next.js `app/`, etc.) and list real page URLs.
|
|
28
33
|
2. Draft `src/blocks/SITE-MAP.md` with namespaces + route folders.
|
|
29
34
|
3. For each route: list nav-to edges, methods/effects, checkpoints, mem keys in `NAV.md` (plan only).
|
|
30
|
-
4. Call out external surfaces (Mailpit inbox, magic-link verify) under `*-external/`.
|
|
35
|
+
4. Call out external surfaces (Mailpit inbox, magic-link verify) under `*-external/`. Plan
|
|
36
|
+
these Blocks as reusable across every email-driven scenario the product has (signup
|
|
37
|
+
confirmation, password reset, magic link, ...) via mem (recipient, link pattern, expected
|
|
38
|
+
copy), not as a separate Block set per scenario - see
|
|
39
|
+
`templates/scaffold/src/blocks/demo-external/mailpit/` for the live, proven shape.
|
|
31
40
|
5. Propose 1-3 starter flows (happy path, login/verify, one feature) — do not implement unless asked.
|
|
32
41
|
|
|
42
|
+
## Blind mode (no frontend source)
|
|
43
|
+
|
|
44
|
+
When there is no app codebase to read - a production target, or a deliberately
|
|
45
|
+
codebase-blind engagement - discover the route/interaction structure live instead, using the
|
|
46
|
+
`waygraph auto` session tools rather than skipping planning:
|
|
47
|
+
|
|
48
|
+
1. `waygraph auto --cli --detach [--base-url <url>]` against a throwaway project dir (or the
|
|
49
|
+
target project once a `src/blocks/` tree exists) - starts a driveable session, prints
|
|
50
|
+
`{sessionId, socketPath}`.
|
|
51
|
+
2. `waygraph auto status <sessionId>` to read the current menu (what Blocks/edges are already
|
|
52
|
+
discoverable) and `waygraph auto dom <sessionId>` (default `aria` mode) to see the live
|
|
53
|
+
page's actual interactive elements by role/name - this is how you find real routes and
|
|
54
|
+
controls without reading a single line of frontend source.
|
|
55
|
+
3. `waygraph auto send <sessionId> "<pick>"` to move to the next screen once you know what is
|
|
56
|
+
there; repeat status/dom/send to walk the app and build the same SITE-MAP/NAV.md picture
|
|
57
|
+
step 1-4 above describe, just discovered live instead of read from source.
|
|
58
|
+
4. `waygraph auto trace <sessionId>` at the end to get the Checkpoint/Block sequence you just
|
|
59
|
+
walked as a JSON record - useful as a starting outline for the flows step 5 asks for.
|
|
60
|
+
5. `waygraph auto send <sessionId> q` to end the session when done exploring.
|
|
61
|
+
|
|
62
|
+
Same output contract as sighted planning: a SITE-MAP/NAV.md plan, not implemented Blocks.
|
|
63
|
+
|
|
33
64
|
## Output
|
|
34
65
|
|
|
35
66
|
Write/update markdown under `src/blocks/` (`SITE-MAP.md`, route `NAV.md` stubs). ASCII only. No localhost ports in shared docs.
|
|
@@ -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,29 +15,32 @@ 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");
|
|
21
|
-
// Device showcase: rotate tablet to landscape before the cart tap.
|
|
22
22
|
ctx.landscape();
|
|
23
|
-
ctx.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
23
|
+
ctx.todos(
|
|
24
|
+
"saucedemo",
|
|
25
|
+
[
|
|
26
|
+
{ id: "login-user", text: "Enter username", done: true },
|
|
27
|
+
{ id: "login-pass", text: "Enter password", done: true },
|
|
28
|
+
{ id: "login-submit", text: "Tap Login", done: true },
|
|
29
|
+
{ id: "cart-find", text: "Find the product", done: true },
|
|
30
|
+
{ id: "cart-add", text: "Add to cart", done: true },
|
|
31
|
+
{ id: "cart-open", text: "Open cart" },
|
|
32
|
+
],
|
|
33
|
+
{ title: "Device showcase", index: 5 },
|
|
34
|
+
);
|
|
30
35
|
ctx.zoom(1.4);
|
|
31
36
|
ctx.zoomOut(false);
|
|
32
37
|
ctx.highlights({
|
|
33
38
|
cart: {
|
|
34
|
-
selector:
|
|
39
|
+
selector: CartSel.cartLink,
|
|
35
40
|
label: "Cart",
|
|
36
|
-
detail: "
|
|
41
|
+
detail: "Open cart",
|
|
37
42
|
focus: true,
|
|
38
43
|
color: "#c9a6ff",
|
|
39
|
-
zoom: 1.55,
|
|
40
44
|
zoomOut: false,
|
|
41
45
|
followMouse: false,
|
|
42
46
|
weight: "bold",
|
|
@@ -46,16 +50,16 @@ export const NavCartBlock = defineNavClickBlock<CartPage>({
|
|
|
46
50
|
},
|
|
47
51
|
stubAfter: (ctx: StubCtx) => {
|
|
48
52
|
ctx.banner("Your cart · desktop");
|
|
49
|
-
// Showcase finale: back to desktop.
|
|
50
53
|
ctx.clearDevice();
|
|
51
|
-
ctx.
|
|
54
|
+
ctx.hideTodos();
|
|
55
|
+
ctx.zoomOut(true);
|
|
52
56
|
ctx.ring("items", {
|
|
53
57
|
selector: InventorySel.cartItem,
|
|
54
58
|
label: "Cart items",
|
|
55
59
|
detail: "Product landed in cart",
|
|
56
60
|
focus: true,
|
|
57
61
|
color: "#86efac",
|
|
58
|
-
|
|
62
|
+
zoomOut: true,
|
|
59
63
|
followMouse: false,
|
|
60
64
|
duration: true,
|
|
61
65
|
});
|
|
@@ -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/templates/quickstart/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
|
+
};
|