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.
Files changed (297) hide show
  1. package/README.md +820 -232
  2. package/assets/stubs/stub.mp4 +0 -0
  3. package/assets/stubs/stub.pdf +32 -0
  4. package/assets/stubs/stub.png +0 -0
  5. package/dist/agent-dive.d.ts +9 -0
  6. package/dist/agent-dive.js +32 -0
  7. package/dist/auto-explore-run.d.ts +20 -2
  8. package/dist/auto-explore-run.js +9 -8
  9. package/dist/auto-explore.js +22 -2
  10. package/dist/auto-session-ipc.d.ts +123 -0
  11. package/dist/auto-session-ipc.js +381 -0
  12. package/dist/auto-session.d.ts +342 -0
  13. package/dist/auto-session.js +760 -0
  14. package/dist/cli.js +417 -51
  15. package/dist/engine.d.ts +40 -1
  16. package/dist/engine.js +82 -0
  17. package/dist/graph.d.ts +18 -0
  18. package/dist/graph.js +65 -2
  19. package/dist/highlights.d.ts +20 -1
  20. package/dist/highlights.js +60 -0
  21. package/dist/index.d.ts +8 -4
  22. package/dist/index.js +5 -3
  23. package/dist/pilot-overlay.d.ts +88 -0
  24. package/dist/pilot-overlay.js +363 -0
  25. package/dist/pilot.d.ts +49 -0
  26. package/dist/pilot.js +53 -0
  27. package/dist/trait.d.ts +22 -0
  28. package/dist/trait.js +60 -3
  29. package/examples/routed-demo/package.json +26 -0
  30. package/examples/routed-demo/playwright.config.ts +20 -0
  31. package/examples/routed-demo/scripts/fixture-server.mjs +37 -0
  32. package/examples/routed-demo/scripts/with-fixture.mjs +70 -0
  33. package/examples/routed-demo/src/flows/routed-demo.flow.ts +12 -0
  34. package/examples/routed-demo/src/pages/dashboard.html +10 -0
  35. package/examples/routed-demo/src/pages/docs.html +8 -0
  36. package/examples/routed-demo/src/routes/(base_app)/dashboard/dashboard.sel.ts +10 -0
  37. package/examples/routed-demo/src/routes/(base_app)/dashboard/methods/click-widget.block.ts +23 -0
  38. package/examples/routed-demo/src/routes/(base_app)/dashboard/nav.block.ts +18 -0
  39. package/examples/routed-demo/src/routes/(base_app)/dashboard/page.block.ts +22 -0
  40. package/examples/routed-demo/src/routes/(external)/docs/docs.sel.ts +7 -0
  41. package/examples/routed-demo/src/routes/(external)/docs/nav.block.ts +21 -0
  42. package/examples/routed-demo/src/routes/(external)/docs/page.block.ts +15 -0
  43. package/examples/routed-demo/src/states/routed-demo.states.ts +10 -0
  44. package/examples/routed-demo/tests/routed-demo.spec.ts +75 -0
  45. package/examples/routed-demo/tsconfig.json +18 -0
  46. package/examples/routed-demo-consumer/package.json +18 -0
  47. package/examples/saucedemo/.waygraph-auto/010dd92b.log +0 -0
  48. package/examples/saucedemo/.waygraph-auto/011ad671.log +0 -0
  49. package/examples/saucedemo/.waygraph-auto/01b45645.log +0 -0
  50. package/examples/saucedemo/.waygraph-auto/03764153.log +0 -0
  51. package/examples/saucedemo/.waygraph-auto/0593587e.log +0 -0
  52. package/examples/saucedemo/.waygraph-auto/06d12823.log +0 -0
  53. package/examples/saucedemo/.waygraph-auto/0b1f5b26.json +8 -0
  54. package/examples/saucedemo/.waygraph-auto/0c00f25f.log +0 -0
  55. package/examples/saucedemo/.waygraph-auto/0e480591.log +0 -0
  56. package/examples/saucedemo/.waygraph-auto/110958b8.log +0 -0
  57. package/examples/saucedemo/.waygraph-auto/138107c1.log +0 -0
  58. package/examples/saucedemo/.waygraph-auto/159d541b.log +0 -0
  59. package/examples/saucedemo/.waygraph-auto/16aa2c01.log +0 -0
  60. package/examples/saucedemo/.waygraph-auto/16c35dd5.log +0 -0
  61. package/examples/saucedemo/.waygraph-auto/1706547d.log +0 -0
  62. package/examples/saucedemo/.waygraph-auto/17537e42.log +0 -0
  63. package/examples/saucedemo/.waygraph-auto/17ede493.log +0 -0
  64. package/examples/saucedemo/.waygraph-auto/1fe2414f.log +0 -0
  65. package/examples/saucedemo/.waygraph-auto/1fe2e3b8.log +0 -0
  66. package/examples/saucedemo/.waygraph-auto/25f68ada.log +0 -0
  67. package/examples/saucedemo/.waygraph-auto/26ca9cd8.log +0 -0
  68. package/examples/saucedemo/.waygraph-auto/2bb6c4e8.log +0 -0
  69. package/examples/saucedemo/.waygraph-auto/2d425004.log +0 -0
  70. package/examples/saucedemo/.waygraph-auto/2f5b3ea6.log +0 -0
  71. package/examples/saucedemo/.waygraph-auto/31bb303d.log +0 -0
  72. package/examples/saucedemo/.waygraph-auto/31f2042f.log +0 -0
  73. package/examples/saucedemo/.waygraph-auto/36551ec1.log +0 -0
  74. package/examples/saucedemo/.waygraph-auto/36a1c274.log +0 -0
  75. package/examples/saucedemo/.waygraph-auto/381aa338.log +0 -0
  76. package/examples/saucedemo/.waygraph-auto/3882bce1.log +0 -0
  77. package/examples/saucedemo/.waygraph-auto/38acd1dc.log +0 -0
  78. package/examples/saucedemo/.waygraph-auto/3b8b77b9.log +0 -0
  79. package/examples/saucedemo/.waygraph-auto/4028d2a2.log +0 -0
  80. package/examples/saucedemo/.waygraph-auto/4168b208.log +0 -0
  81. package/examples/saucedemo/.waygraph-auto/43ab66ce.log +0 -0
  82. package/examples/saucedemo/.waygraph-auto/43f66838.log +0 -0
  83. package/examples/saucedemo/.waygraph-auto/442171d4.log +0 -0
  84. package/examples/saucedemo/.waygraph-auto/453b1ce1.log +0 -0
  85. package/examples/saucedemo/.waygraph-auto/457322bd.log +0 -0
  86. package/examples/saucedemo/.waygraph-auto/46197027.log +0 -0
  87. package/examples/saucedemo/.waygraph-auto/46889468.log +0 -0
  88. package/examples/saucedemo/.waygraph-auto/4890da1c.log +0 -0
  89. package/examples/saucedemo/.waygraph-auto/4893a63b.log +0 -0
  90. package/examples/saucedemo/.waygraph-auto/4af71440.log +0 -0
  91. package/examples/saucedemo/.waygraph-auto/4f7496d1.log +0 -0
  92. package/examples/saucedemo/.waygraph-auto/50e8baaa.log +0 -0
  93. package/examples/saucedemo/.waygraph-auto/52b3a455.log +0 -0
  94. package/examples/saucedemo/.waygraph-auto/532dd9b8.log +0 -0
  95. package/examples/saucedemo/.waygraph-auto/5391ce40.log +0 -0
  96. package/examples/saucedemo/.waygraph-auto/57dbddb3.log +0 -0
  97. package/examples/saucedemo/.waygraph-auto/5897f501.log +0 -0
  98. package/examples/saucedemo/.waygraph-auto/59c0b57d.log +0 -0
  99. package/examples/saucedemo/.waygraph-auto/5b511794.log +0 -0
  100. package/examples/saucedemo/.waygraph-auto/5c47910f.log +0 -0
  101. package/examples/saucedemo/.waygraph-auto/5eda8273.log +0 -0
  102. package/examples/saucedemo/.waygraph-auto/621518ad.log +0 -0
  103. package/examples/saucedemo/.waygraph-auto/632b7118.log +0 -0
  104. package/examples/saucedemo/.waygraph-auto/64314c2b.log +0 -0
  105. package/examples/saucedemo/.waygraph-auto/66516213.log +0 -0
  106. package/examples/saucedemo/.waygraph-auto/66c17079.log +0 -0
  107. package/examples/saucedemo/.waygraph-auto/69bf0b80.log +0 -0
  108. package/examples/saucedemo/.waygraph-auto/69c2347a.log +0 -0
  109. package/examples/saucedemo/.waygraph-auto/6d22bdb0.log +0 -0
  110. package/examples/saucedemo/.waygraph-auto/7103bebb.log +0 -0
  111. package/examples/saucedemo/.waygraph-auto/740c9faa.log +0 -0
  112. package/examples/saucedemo/.waygraph-auto/74872fc5.log +0 -0
  113. package/examples/saucedemo/.waygraph-auto/75846ca9.log +0 -0
  114. package/examples/saucedemo/.waygraph-auto/7626c85b.log +0 -0
  115. package/examples/saucedemo/.waygraph-auto/76308eec.log +0 -0
  116. package/examples/saucedemo/.waygraph-auto/76c1650e.log +0 -0
  117. package/examples/saucedemo/.waygraph-auto/7861f38f.log +0 -0
  118. package/examples/saucedemo/.waygraph-auto/7af224ed.log +0 -0
  119. package/examples/saucedemo/.waygraph-auto/7c3be585.log +0 -0
  120. package/examples/saucedemo/.waygraph-auto/7ed55a2c.log +0 -0
  121. package/examples/saucedemo/.waygraph-auto/80086ba2.log +0 -0
  122. package/examples/saucedemo/.waygraph-auto/80206369.log +0 -0
  123. package/examples/saucedemo/.waygraph-auto/847f1092.log +0 -0
  124. package/examples/saucedemo/.waygraph-auto/8581abfa.log +0 -0
  125. package/examples/saucedemo/.waygraph-auto/87b7e0fd.log +0 -0
  126. package/examples/saucedemo/.waygraph-auto/87c79256.log +0 -0
  127. package/examples/saucedemo/.waygraph-auto/88af2495.log +0 -0
  128. package/examples/saucedemo/.waygraph-auto/8c04a403.log +0 -0
  129. package/examples/saucedemo/.waygraph-auto/8c9ab09e.log +0 -0
  130. package/examples/saucedemo/.waygraph-auto/8cc5db51.log +0 -0
  131. package/examples/saucedemo/.waygraph-auto/8ea3a69c.log +0 -0
  132. package/examples/saucedemo/.waygraph-auto/9150f913.log +0 -0
  133. package/examples/saucedemo/.waygraph-auto/929a4313.log +0 -0
  134. package/examples/saucedemo/.waygraph-auto/95a599e4.log +0 -0
  135. package/examples/saucedemo/.waygraph-auto/96c45350.log +0 -0
  136. package/examples/saucedemo/.waygraph-auto/986030e6.log +0 -0
  137. package/examples/saucedemo/.waygraph-auto/99787abb.log +0 -0
  138. package/examples/saucedemo/.waygraph-auto/99ddb62c.log +0 -0
  139. package/examples/saucedemo/.waygraph-auto/a63a2d20.log +0 -0
  140. package/examples/saucedemo/.waygraph-auto/a78befb7.log +0 -0
  141. package/examples/saucedemo/.waygraph-auto/a84d9b79.log +0 -0
  142. package/examples/saucedemo/.waygraph-auto/a9270890.log +0 -0
  143. package/examples/saucedemo/.waygraph-auto/aa440153.log +0 -0
  144. package/examples/saucedemo/.waygraph-auto/ab7561e0.log +0 -0
  145. package/examples/saucedemo/.waygraph-auto/ac19ae60.log +0 -0
  146. package/examples/saucedemo/.waygraph-auto/ae21ad8e.log +0 -0
  147. package/examples/saucedemo/.waygraph-auto/af09042f.log +0 -0
  148. package/examples/saucedemo/.waygraph-auto/b1684126.log +0 -0
  149. package/examples/saucedemo/.waygraph-auto/b21e9d12.log +0 -0
  150. package/examples/saucedemo/.waygraph-auto/b5a838be.log +0 -0
  151. package/examples/saucedemo/.waygraph-auto/b603549d.log +0 -0
  152. package/examples/saucedemo/.waygraph-auto/b83e6259.log +0 -0
  153. package/examples/saucedemo/.waygraph-auto/b9cb2796.log +0 -0
  154. package/examples/saucedemo/.waygraph-auto/bb0a0018.log +0 -0
  155. package/examples/saucedemo/.waygraph-auto/bc0bdd0e.log +0 -0
  156. package/examples/saucedemo/.waygraph-auto/bc7d4a83.log +0 -0
  157. package/examples/saucedemo/.waygraph-auto/bd8e082a.log +0 -0
  158. package/examples/saucedemo/.waygraph-auto/bea0c93e.log +0 -0
  159. package/examples/saucedemo/.waygraph-auto/bf35201a.log +0 -0
  160. package/examples/saucedemo/.waygraph-auto/bffa3a7a.log +0 -0
  161. package/examples/saucedemo/.waygraph-auto/c4afb8bc.log +0 -0
  162. package/examples/saucedemo/.waygraph-auto/c916a654.log +0 -0
  163. package/examples/saucedemo/.waygraph-auto/c9b8d69e.log +0 -0
  164. package/examples/saucedemo/.waygraph-auto/d02e5e7e.log +0 -0
  165. package/examples/saucedemo/.waygraph-auto/d09aff71.log +0 -0
  166. package/examples/saucedemo/.waygraph-auto/d0e41396.log +0 -0
  167. package/examples/saucedemo/.waygraph-auto/d1370d76.log +0 -0
  168. package/examples/saucedemo/.waygraph-auto/d3714ae4.log +0 -0
  169. package/examples/saucedemo/.waygraph-auto/da0685dc.log +0 -0
  170. package/examples/saucedemo/.waygraph-auto/da894ad8.log +0 -0
  171. package/examples/saucedemo/.waygraph-auto/daa2f922.log +0 -0
  172. package/examples/saucedemo/.waygraph-auto/daefb614.log +0 -0
  173. package/examples/saucedemo/.waygraph-auto/db97e833.log +0 -0
  174. package/examples/saucedemo/.waygraph-auto/e101d19a.log +0 -0
  175. package/examples/saucedemo/.waygraph-auto/e207c989.log +0 -0
  176. package/examples/saucedemo/.waygraph-auto/e633e545.log +0 -0
  177. package/examples/saucedemo/.waygraph-auto/e69aec68.log +0 -0
  178. package/examples/saucedemo/.waygraph-auto/e70e2d06.log +0 -0
  179. package/examples/saucedemo/.waygraph-auto/ebad3410.log +0 -0
  180. package/examples/saucedemo/.waygraph-auto/ecbb0966.log +0 -0
  181. package/examples/saucedemo/.waygraph-auto/ecdee753.log +0 -0
  182. package/examples/saucedemo/.waygraph-auto/ed888783.log +0 -0
  183. package/examples/saucedemo/.waygraph-auto/ed931dac.log +0 -0
  184. package/examples/saucedemo/.waygraph-auto/ef655a3f.log +0 -0
  185. package/examples/saucedemo/.waygraph-auto/f3c29b21.log +0 -0
  186. package/examples/saucedemo/.waygraph-auto/f53f7cfc.log +0 -0
  187. package/examples/saucedemo/.waygraph-auto/f5ad5830.log +0 -0
  188. package/examples/saucedemo/.waygraph-auto/faed36dd.log +0 -0
  189. package/examples/saucedemo/docs/CONVENTION.md +25 -5
  190. package/examples/saucedemo/docs/HELPERS.md +15 -4
  191. package/examples/saucedemo/scripts/capture-wrong-login.mjs +8 -2
  192. package/examples/saucedemo/scripts/prove-wrong-login-runtime.mjs +8 -2
  193. package/examples/saucedemo/src/blocks/SITE-MAP.md +14 -3
  194. package/examples/saucedemo/src/blocks/saucedemo-web/NAV.md +15 -1
  195. package/examples/saucedemo/src/blocks/saucedemo-web/cart/NAV.md +1 -0
  196. package/examples/saucedemo/src/blocks/saucedemo-web/cart/cart.sel.ts +9 -0
  197. package/examples/saucedemo/src/blocks/saucedemo-web/cart/nav-cart.block.ts +3 -2
  198. package/examples/saucedemo/src/blocks/saucedemo-web/cart/nav-checkout-info.block.ts +2 -1
  199. package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/NAV.md +6 -1
  200. package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/checkout-info.sel.ts +11 -0
  201. package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/fill-first-name.method.block.ts +22 -0
  202. package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/fill-last-name.method.block.ts +21 -0
  203. package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/fill-postal-code.method.block.ts +21 -0
  204. package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/methods/submit-checkout-info.method.block.ts +6 -7
  205. package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-two/NAV.md +2 -0
  206. package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-two/methods/checkout-overview.sel.ts +9 -0
  207. package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.ts +7 -6
  208. package/examples/saucedemo/src/blocks/saucedemo-web/ff-owner-auth.block.ts +7 -2
  209. package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/NAV.md +1 -0
  210. package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/item-detail.sel.ts +9 -0
  211. package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/nav-back-to-inventory.block.ts +2 -1
  212. package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/nav-back-to-products.block.ts +2 -1
  213. package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/nav-continue-shopping.block.ts +2 -1
  214. package/examples/saucedemo/src/blocks/saucedemo-web/methods/fill-password.method.block.ts +51 -0
  215. package/examples/saucedemo/src/blocks/saucedemo-web/methods/fill-username.method.block.ts +69 -0
  216. package/examples/saucedemo/src/blocks/saucedemo-web/methods/login.sel.ts +13 -0
  217. package/examples/saucedemo/src/blocks/saucedemo-web/methods/submit-login-for-flow.ts +4 -4
  218. package/examples/saucedemo/src/blocks/saucedemo-web/methods/submit-login.method.block.ts +13 -51
  219. package/examples/saucedemo/src/blocks/saucedemo-web/methods/submit-logout.method.block.ts +4 -3
  220. package/examples/saucedemo/src/blocks/saucedemo-web/nav-login.block.ts +14 -6
  221. package/examples/saucedemo/src/flows/checkout-then-browse-again.flow.ts +15 -0
  222. package/examples/saucedemo/src/flows/checkout.flow.ts +20 -2
  223. package/examples/saucedemo/src/flows/device-showcase.flow.ts +4 -0
  224. package/examples/saucedemo/src/flows/login.flow.ts +3 -1
  225. package/examples/saucedemo/src/flows/shop.flow.ts +6 -0
  226. package/examples/saucedemo/src/flows/smoke.flow.ts +13 -7
  227. package/examples/saucedemo/src/flows/stub-on-error.flow.ts +4 -2
  228. package/examples/saucedemo/src/flows/viewer-blocked.flow.ts +6 -2
  229. package/examples/saucedemo/tests/flow-block-verify.spec.ts +3 -3
  230. package/examples/saucedemo/tests/submit-login-branch.spec.ts +5 -3
  231. package/package.json +2 -1
  232. package/templates/agents/waygraph-author.agent.md +43 -5
  233. package/templates/agents/waygraph-planner.agent.md +33 -2
  234. package/templates/quickstart/src/blocks/saucedemo-web/NAV.md +15 -1
  235. package/templates/quickstart/src/blocks/saucedemo-web/cart/NAV.md +1 -0
  236. package/templates/quickstart/src/blocks/saucedemo-web/cart/cart.sel.ts +9 -0
  237. package/templates/quickstart/src/blocks/saucedemo-web/cart/nav-cart.block.ts +19 -15
  238. package/templates/quickstart/src/blocks/saucedemo-web/cart/nav-checkout-info.block.ts +2 -1
  239. package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/NAV.md +6 -1
  240. package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/checkout-info.sel.ts +11 -0
  241. package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/fill-first-name.method.block.ts +22 -0
  242. package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/fill-last-name.method.block.ts +21 -0
  243. package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/fill-postal-code.method.block.ts +21 -0
  244. package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/methods/submit-checkout-info.method.block.ts +6 -7
  245. package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-two/NAV.md +2 -0
  246. package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-two/methods/checkout-overview.sel.ts +9 -0
  247. package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.ts +7 -6
  248. package/templates/quickstart/src/blocks/saucedemo-web/ff-owner-auth.block.ts +7 -2
  249. package/templates/quickstart/src/blocks/saucedemo-web/inventory/methods/add-to-cart.effect.block.ts +24 -16
  250. package/templates/quickstart/src/blocks/saucedemo-web/inventory/nav-item-detail.block.ts +3 -3
  251. package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/NAV.md +1 -0
  252. package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/item-detail.sel.ts +9 -0
  253. package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/nav-back-to-inventory.block.ts +2 -1
  254. package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/nav-back-to-products.block.ts +2 -1
  255. package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/nav-continue-shopping.block.ts +2 -1
  256. package/templates/quickstart/src/blocks/saucedemo-web/methods/fill-password.method.block.ts +51 -0
  257. package/templates/quickstart/src/blocks/saucedemo-web/methods/fill-username.method.block.ts +69 -0
  258. package/templates/quickstart/src/blocks/saucedemo-web/methods/login.sel.ts +13 -0
  259. package/templates/quickstart/src/blocks/saucedemo-web/methods/submit-login-for-flow.ts +4 -4
  260. package/templates/quickstart/src/blocks/saucedemo-web/methods/submit-login.method.block.ts +35 -63
  261. package/templates/quickstart/src/blocks/saucedemo-web/methods/submit-logout.method.block.ts +4 -3
  262. package/templates/quickstart/src/blocks/saucedemo-web/nav-login.block.ts +14 -6
  263. package/templates/quickstart/src/flows/checkout-then-browse-again.flow.ts +15 -0
  264. package/templates/quickstart/src/flows/checkout.flow.ts +29 -2
  265. package/templates/quickstart/src/flows/device-showcase.flow.ts +4 -0
  266. package/templates/quickstart/src/flows/login.flow.ts +3 -1
  267. package/templates/quickstart/src/flows/shop.flow.ts +6 -0
  268. package/templates/quickstart/src/flows/smoke.flow.ts +13 -7
  269. package/templates/quickstart/src/flows/viewer-blocked.flow.ts +6 -2
  270. package/templates/quickstart/tests/chain-flow.spec.ts +8 -1
  271. package/templates/scaffold/STRUCTURE.md +23 -3
  272. package/templates/scaffold/src/blocks/demo-external/mailpit/mailpit-inbox.page.block.ts +30 -0
  273. package/templates/scaffold/src/blocks/demo-external/mailpit/mailpit-sel.ts +5 -0
  274. package/templates/scaffold/src/blocks/demo-external/mailpit/methods/assert-email-content.method.block.ts +48 -0
  275. package/templates/scaffold/src/blocks/demo-external/mailpit/methods/assert-email-received.method.block.ts +49 -0
  276. package/templates/scaffold/src/blocks/demo-external/mailpit/methods/extract-email-link.method.block.ts +41 -0
  277. package/templates/scaffold/src/blocks/demo-external/mailpit/methods/open-message.method.block.ts +39 -0
  278. package/templates/scaffold/src/blocks/demo-external/mailpit/nav-mailpit-inbox.block.ts +20 -0
  279. package/templates/scaffold/src/blocks/demo-web/demo-sel.ts +1 -0
  280. package/templates/scaffold/src/blocks/demo-web/docs.html +8 -0
  281. package/templates/scaffold/src/blocks/demo-web/home.html +4 -0
  282. package/templates/scaffold/src/blocks/demo-web/methods/assert-hello.method.block.ts +34 -38
  283. package/templates/scaffold/src/blocks/demo-web/methods/assert-item-added.method.block.ts +38 -0
  284. package/templates/scaffold/src/blocks/demo-web/nav-verification-link.block.ts +34 -0
  285. package/templates/scaffold/src/flows/mail-verify.flow.ts +85 -0
  286. package/templates/scaffold/src/flows/routes-demo.flow.ts +14 -0
  287. package/templates/scaffold/src/flows/shop.flow.ts +19 -2
  288. package/templates/scaffold/src/routes/(external)/docs/docs.sel.ts +7 -0
  289. package/templates/scaffold/src/routes/(external)/docs/nav.block.ts +21 -0
  290. package/templates/scaffold/src/routes/(external)/docs/page.block.ts +15 -0
  291. package/templates/scaffold/src/states/demo.mem-keys.ts +25 -1
  292. package/templates/scaffold/src/states/demo.states.ts +13 -0
  293. package/templates/scaffold/test-results/.last-run.json +4 -0
  294. package/templates/scaffold/tests/mail-verify.spec.ts +191 -0
  295. package/templates/skills/waygraph-blind-pilot.skill.md +61 -0
  296. package/templates/skills/waygraph-pilot.skill.md +108 -0
  297. 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
- Atomic Blocks - one nav / effect / method per real URL or on-page mutation so
4
- `waygraph auto` can discover a real state graph (not a fat multi-page Block).
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
- submit-login.method.block.ts
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
- submit-checkout-info.method.block.ts
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, _in, mem) { /* fill + click */ },
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(SubmitLoginActionBlock, {
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 { SubmitLoginActionBlock } = await import(
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, SubmitLoginActionBlock, end]);
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 { SubmitLoginActionBlock } = await import(
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, SubmitLoginActionBlock, end]);
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 # Nav defineNavBlock url:/
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
- submit-login.method.block.ts # Method defineMethodBlock
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
- submit-checkout-info.method.block.ts
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/submit-login.method.block.ts` | Method | Form submit; branches LoggedIn vs LoginPage |
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
@@ -20,3 +20,4 @@ Shopping cart page and checkout entry.
20
20
  ## Related mem keys / checkpoints
21
21
 
22
22
  - Checkpoints: `CartPage`, `CheckoutInfoPage`, `ItemInCart` / `LoggedIn` (cart contents)
23
+ - Sel: `CartSel` (`cart.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: ".shopping_cart_link",
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: ".shopping_cart_link",
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: "#checkout",
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/submit-checkout-info.method.block.ts` | Method | Fill form + Continue -> overview |
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
@@ -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
- * Fills shipping form and continues - never navigates itself
10
- * (nav-checkout-info already got here).
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: "Fills in the shipping info form and continues to the order overview.",
16
+ description: "Continues from the shipping info form to the order overview.",
15
17
  instruction: {
16
18
  async act(page) {
17
- await page.locator("#first-name").fill("Ada");
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("#finish");
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(".complete-header", "Thank you for your order!")],
21
+ verify: [Trait.text(CheckoutOverviewSel.completeHeader, "Thank you for your order!")],
21
22
  stubBefore: {
22
- finish: { selector: "#finish", label: "Finish" },
23
+ finish: { selector: CheckoutOverviewSel.finishBtn, label: "Finish" },
23
24
  },
24
25
  stubAfter: {
25
26
  thanks: {
26
- selector: ".complete-header",
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: ".complete-header",
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: ".complete-header",
54
+ selector: CheckoutOverviewSel.completeHeader,
54
55
  duration: true,
55
56
  fastMode: 500,
56
57
  },