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
@@ -3,7 +3,7 @@ import type { ItemDetailPage } from "../../../states/checkout.states.js";
3
3
  import { SelectedItem } from "../../../states/checkout.mem-keys.js";
4
4
  import {
5
5
  collectInventoryItems,
6
- inventoryItemTitleSelector,
6
+ InventorySel,
7
7
  } from "./methods/inventory-items.js";
8
8
 
9
9
  /**
@@ -19,7 +19,7 @@ export const NavItemDetailBlock = defineMemNavBlock<ItemDetailPage>({
19
19
  description: "Opens the product named by mem (saucedemo.selectedItem) on its detail page.",
20
20
  checkpoint: "ItemDetailPage",
21
21
  requires: [SelectedItem.key],
22
- click: (mem) => inventoryItemTitleSelector(mem.get(SelectedItem.key).id),
22
+ click: (mem) => InventorySel.title(mem.get(SelectedItem.key).id),
23
23
  verify: [Trait.url({ pathname: "/inventory-item.html" })],
24
24
  async instanceOptions(page): Promise<readonly WaygraphInstanceOption[]> {
25
25
  const items = await collectInventoryItems(page);
@@ -28,7 +28,7 @@ export const NavItemDetailBlock = defineMemNavBlock<ItemDetailPage>({
28
28
  label: `Open "${item.name}" details`,
29
29
  key: SelectedItem.key,
30
30
  value: item,
31
- highlight: inventoryItemTitleSelector(item.id),
31
+ highlight: InventorySel.title(item.id),
32
32
  }));
33
33
  },
34
34
  });
@@ -23,3 +23,4 @@ Single product detail page, plus nav edges that return to catalog
23
23
  ## Related mem keys / checkpoints
24
24
 
25
25
  - Checkpoints: `ItemDetailPage`, `LoggedIn` (after back / continue), `OrderComplete` (from for back-to-products)
26
+ - Sel: `ItemDetailSel` (`item-detail.sel.ts`) - DOM only, not mem
@@ -0,0 +1,9 @@
1
+ /**
2
+ * DOM selectors for the item detail page (`/inventory-item.html`) and the
3
+ * order-complete page's equivalent nav control. Convention: DOM strings
4
+ * live in `*Sel` next to the page, not inlined in each Block.
5
+ */
6
+ export const ItemDetailSel = {
7
+ continueShoppingBtn: "#continue-shopping",
8
+ backToProductsBtn: "#back-to-products",
9
+ };
@@ -1,5 +1,6 @@
1
1
  import { defineNavClickBlock, Trait } from "waygraph";
2
2
  import type { LoggedIn } from "../../../states/checkout.states.js";
3
+ import { ItemDetailSel } from "./item-detail.sel.js";
3
4
 
4
5
  /**
5
6
  * Kind: Nav
@@ -13,6 +14,6 @@ export const NavBackToInventoryBlock = defineNavClickBlock<LoggedIn>({
13
14
  name: "nav-back-to-inventory",
14
15
  description: "Clicks 'Back to products' on the item detail page.",
15
16
  checkpoint: "LoggedIn",
16
- click: "#back-to-products",
17
+ click: ItemDetailSel.backToProductsBtn,
17
18
  verify: [Trait.url({ pathname: "/inventory.html" })],
18
19
  });
@@ -1,5 +1,6 @@
1
1
  import { defineNavClickBlock, Trait } from "waygraph";
2
2
  import type { LoggedIn } from "../../../states/checkout.states.js";
3
+ import { ItemDetailSel } from "./item-detail.sel.js";
3
4
 
4
5
  /**
5
6
  * Kind: Nav
@@ -13,6 +14,6 @@ export const NavBackToProductsBlock = defineNavClickBlock<LoggedIn>({
13
14
  name: "nav-back-to-products",
14
15
  description: "Clicks 'Back Home' on the order confirmation page.",
15
16
  checkpoint: "LoggedIn",
16
- click: "#back-to-products",
17
+ click: ItemDetailSel.backToProductsBtn,
17
18
  verify: [Trait.url({ pathname: "/inventory.html" })],
18
19
  });
@@ -1,5 +1,6 @@
1
1
  import { defineNavClickBlock, Trait } from "waygraph";
2
2
  import type { LoggedIn } from "../../../states/checkout.states.js";
3
+ import { ItemDetailSel } from "./item-detail.sel.js";
3
4
 
4
5
  /**
5
6
  * Kind: Nav
@@ -12,6 +13,6 @@ export const NavContinueShoppingBlock = defineNavClickBlock<LoggedIn>({
12
13
  name: "nav-continue-shopping",
13
14
  description: "Clicks 'Continue Shopping' on the cart page.",
14
15
  checkpoint: "LoggedIn",
15
- click: "#continue-shopping",
16
+ click: ItemDetailSel.continueShoppingBtn,
16
17
  verify: [Trait.url({ pathname: "/inventory.html" })],
17
18
  });
@@ -0,0 +1,51 @@
1
+ import { defineMethodBlock, checkpoint, type StubCtx } from "waygraph";
2
+ import type { LoginPage } from "../../../states/checkout.states.js";
3
+ import { LoginCreds } from "../../../states/checkout.mem-keys.js";
4
+ import { LoginSel } from "./login.sel.js";
5
+
6
+ /**
7
+ * Kind: Method
8
+ * Helper: defineMethodBlock
9
+ * Route: saucedemo-web/methods/ (page URL /)
10
+ *
11
+ * Fills the password field only - self-loop on LoginPage. See
12
+ * fill-username.method.block.ts for why this is split from submit.
13
+ */
14
+ export const FillPasswordBlock = defineMethodBlock<LoginPage, LoginPage>({
15
+ name: "fill-password",
16
+ description: "Fills the password field on the login form.",
17
+ requires: [LoginCreds.key],
18
+ instruction: {
19
+ async act(page, _input, mem) {
20
+ const { password } = mem.get(LoginCreds.key);
21
+ await page.locator(LoginSel.password).fill(password);
22
+ },
23
+ resolve: () => checkpoint("LoginPage"),
24
+ stubBefore: (ctx: StubCtx) => {
25
+ ctx.highlights({
26
+ password: {
27
+ selector: LoginSel.password,
28
+ label: "Password",
29
+ todo: "login-pass",
30
+ focus: true,
31
+ color: "#c9a6ff",
32
+ zoom: 1.4,
33
+ },
34
+ });
35
+ },
36
+ stubAfter: (ctx: StubCtx) => {
37
+ ctx.todos(
38
+ "saucedemo",
39
+ [
40
+ { id: "login-user", text: "Enter username", done: true },
41
+ { id: "login-pass", text: "Enter password", done: true },
42
+ { id: "login-submit", text: "Tap Login" },
43
+ { id: "cart-find", text: "Find the product" },
44
+ { id: "cart-add", text: "Add to cart" },
45
+ { id: "cart-open", text: "Open cart" },
46
+ ],
47
+ { title: "Device showcase", index: 2 },
48
+ );
49
+ },
50
+ },
51
+ });
@@ -0,0 +1,69 @@
1
+ import { defineMethodBlock, checkpoint, type StubCtx } from "waygraph";
2
+ import type { LoginPage } from "../../../states/checkout.states.js";
3
+ import { LoginCreds } from "../../../states/checkout.mem-keys.js";
4
+ import { LoginSel } from "./login.sel.js";
5
+
6
+ /**
7
+ * Kind: Method
8
+ * Helper: defineMethodBlock
9
+ * Route: saucedemo-web/methods/ (page URL /)
10
+ *
11
+ * Fills the username field only - self-loop on LoginPage, no submit, no
12
+ * page.goto. Submit is its own Block (submit-login.method.block.ts) so the
13
+ * graph/demo show fill vs submit as real, distinct steps instead of one
14
+ * Block doing "input username and password and login at the same time".
15
+ */
16
+ export const FillUsernameBlock = defineMethodBlock<LoginPage, LoginPage>({
17
+ name: "fill-username",
18
+ description: "Fills the username field on the login form.",
19
+ requires: [LoginCreds.key],
20
+ instruction: {
21
+ async act(page, _input, mem) {
22
+ const { username } = mem.get(LoginCreds.key);
23
+ await page.locator(LoginSel.username).fill(username);
24
+ },
25
+ resolve: () => checkpoint("LoginPage"),
26
+ stubBefore: (ctx: StubCtx) => {
27
+ ctx.title("Signing in · mobile");
28
+ ctx.device("mobile");
29
+ ctx.portrait();
30
+ ctx.todos(
31
+ "saucedemo",
32
+ [
33
+ { id: "login-user", text: "Enter username" },
34
+ { id: "login-pass", text: "Enter password" },
35
+ { id: "login-submit", text: "Tap Login" },
36
+ { id: "cart-find", text: "Find the product" },
37
+ { id: "cart-add", text: "Add to cart" },
38
+ { id: "cart-open", text: "Open cart" },
39
+ ],
40
+ { title: "Device showcase", index: 0 },
41
+ );
42
+ ctx.zoom(1.35);
43
+ ctx.highlights({
44
+ username: {
45
+ selector: LoginSel.username,
46
+ label: "Username",
47
+ todo: "login-user",
48
+ focus: true,
49
+ color: "#c9a6ff",
50
+ zoom: 1.4,
51
+ },
52
+ });
53
+ },
54
+ stubAfter: (ctx: StubCtx) => {
55
+ ctx.todos(
56
+ "saucedemo",
57
+ [
58
+ { id: "login-user", text: "Enter username", done: true },
59
+ { id: "login-pass", text: "Enter password" },
60
+ { id: "login-submit", text: "Tap Login" },
61
+ { id: "cart-find", text: "Find the product" },
62
+ { id: "cart-add", text: "Add to cart" },
63
+ { id: "cart-open", text: "Open cart" },
64
+ ],
65
+ { title: "Device showcase", index: 1 },
66
+ );
67
+ },
68
+ },
69
+ });
@@ -0,0 +1,13 @@
1
+ /**
2
+ * DOM selectors for the login route (`/`) and its logout burger menu.
3
+ * Convention: DOM strings live in `*Sel` next to the page, not inlined in
4
+ * each Block.
5
+ */
6
+ export const LoginSel = {
7
+ username: "#user-name",
8
+ password: "#password",
9
+ loginButton: "#login-button",
10
+ errorBanner: '[data-test="error"]',
11
+ burgerMenuButton: "#react-burger-menu-btn",
12
+ logoutLink: "#logout_sidebar_link",
13
+ };
@@ -1,13 +1,13 @@
1
1
  import type { DefinedBlock } from "waygraph";
2
2
  import type { LoginPage, LoggedIn } from "../../../states/checkout.states.js";
3
- import { SubmitLoginActionBlock } from "./submit-login.method.block.js";
3
+ import { SubmitLoginBlock } from "./submit-login.method.block.js";
4
4
 
5
5
  /**
6
6
  * Kind: helper (not a discoverable Block file)
7
- * Helper: typed alias over SubmitLoginActionBlock
7
+ * Helper: typed alias over SubmitLoginBlock
8
8
  * Route: saucedemo-web/methods/ (page URL /)
9
9
  *
10
10
  * DefinedBlock cast so linear Flows can chain .withVerify on Out=LoggedIn;
11
- * runtime still branches on bad credentials via SubmitLoginActionBlock.
11
+ * runtime still branches on bad credentials via SubmitLoginBlock.
12
12
  */
13
- export const SubmitLoginForFlow = SubmitLoginActionBlock as unknown as DefinedBlock<LoginPage, LoggedIn>;
13
+ export const SubmitLoginForFlow = SubmitLoginBlock as unknown as DefinedBlock<LoginPage, LoggedIn>;
@@ -1,6 +1,6 @@
1
1
  import { defineMethodBlock, checkpoint, Trait, type StubCtx } from "waygraph";
2
2
  import type { LoginPage, LoginSubmitOutcome } from "../../../states/checkout.states.js";
3
- import { LoginCreds } from "../../../states/checkout.mem-keys.js";
3
+ import { LoginSel } from "./login.sel.js";
4
4
 
5
5
  type LoginObserve = "success" | "failure";
6
6
 
@@ -9,30 +9,26 @@ type LoginObserve = "success" | "failure";
9
9
  * Helper: defineMethodBlock
10
10
  * Route: saucedemo-web/methods/ (page URL /)
11
11
  *
12
- * Fills credentials and submits - never page.goto (nav-login Page hub owns that).
12
+ * Clicks Login only - never page.goto (nav-login Page hub owns that), never
13
+ * fills fields (fill-username.method.block.ts / fill-password.method.block.ts
14
+ * already did that). One Block, one action: submit.
13
15
  * Branches: good creds -> LoggedIn; bad/locked -> LoginPage with error banner.
14
- * stubBefore/stubAfter drive the floating todo dock (Method fill/click advances
15
- * todoIndex mid-act; stubAfter marks complete / fail).
16
16
  */
17
- export const SubmitLoginActionBlock = defineMethodBlock<LoginPage, LoginSubmitOutcome>({
17
+ export const SubmitLoginBlock = defineMethodBlock<LoginPage, LoginSubmitOutcome>({
18
18
  name: "submit-login",
19
- description: "Logs a user in when credentials are valid; stays on LoginPage when auth fails.",
20
- requires: [LoginCreds.key],
19
+ description: "Submits the login form; stays on LoginPage when auth fails.",
21
20
  instruction: {
22
- async act(page, _input, mem) {
23
- const { username, password } = mem.get(LoginCreds.key);
24
- await page.locator("#user-name").fill(username);
25
- await page.locator("#password").fill(password);
21
+ async act(page) {
26
22
  // noWaitAfter: observe owns the inventory URL wait. Default click
27
23
  // navigation-wait can hang under waygraph auto's demo cursor patch.
28
- await page.locator("#login-button").click({ noWaitAfter: true });
24
+ await page.locator(LoginSel.loginButton).click({ noWaitAfter: true });
29
25
  },
30
26
  async observe(page): Promise<LoginObserve> {
31
27
  // Race inventory nav vs error banner - locked_out / wrong password show
32
28
  // Epic sadface immediately; do not burn the full inventory timeout.
33
29
  const inventory = page.waitForURL(/\/inventory\.html/, { timeout: 8_000 }).then(() => "success" as const);
34
30
  const errorBanner = page
35
- .locator('[data-test="error"]')
31
+ .locator(LoginSel.errorBanner)
36
32
  .first()
37
33
  .waitFor({ state: "visible", timeout: 8_000 })
38
34
  .then(() => "failure" as const);
@@ -46,40 +42,13 @@ export const SubmitLoginActionBlock = defineMethodBlock<LoginPage, LoginSubmitOu
46
42
  verify: (out) =>
47
43
  out.__state === "LoggedIn"
48
44
  ? [Trait.url({ pathname: "/inventory.html" })]
49
- : [Trait.visible('[data-test="error"]')],
50
- // Open lifecycle: banner title, todos, Screen Studio camera zoom,
51
- // sequential highlight queue (appear / dwell / fade), focus + color.
45
+ : [Trait.visible(LoginSel.errorBanner)],
52
46
  stubBefore: (ctx: StubCtx) => {
53
- ctx.title("Signing in · mobile");
54
- // 0.13.3: mobile portrait + touch; tap Login.
55
- ctx.device("mobile");
56
- ctx.portrait();
57
- ctx.todoId("saucedemo-login");
58
- ctx.todos([
59
- { id: "login-user", text: "Enter username" },
60
- { id: "login-pass", text: "Enter password" },
61
- { id: "login-submit", text: "Tap Login" },
62
- ]);
63
- ctx.todoIndex(0);
64
- ctx.zoom(1.35);
65
47
  ctx.highlights({
66
- username: {
67
- selector: "#user-name",
68
- label: "Username",
69
- focus: true,
70
- color: "#c9a6ff",
71
- zoom: 1.4,
72
- },
73
- password: {
74
- selector: "#password",
75
- label: "Password",
76
- focus: true,
77
- color: "#c9a6ff",
78
- zoom: 1.4,
79
- },
80
48
  submit: {
81
- selector: "#login-button",
49
+ selector: LoginSel.loginButton,
82
50
  label: "Login",
51
+ todo: "login-submit",
83
52
  focus: true,
84
53
  color: "#86efac",
85
54
  zoom: 1.55,
@@ -89,19 +58,19 @@ export const SubmitLoginActionBlock = defineMethodBlock<LoginPage, LoginSubmitOu
89
58
  });
90
59
  },
91
60
  stubAfter: (ctx: StubCtx) => {
92
- // Fail branch lands on LoginPage with Epic sadface - do not ring the
93
- // inventory shelf. Success (LoggedIn) hands off to shopFlow.
94
61
  if (ctx.out && ctx.out.__state === "LoginPage") {
95
62
  ctx.title("Login blocked");
96
- ctx.todoId("saucedemo-login");
97
- ctx.todos([
98
- { id: "login-user", text: "Enter username", done: true },
99
- { id: "login-pass", text: "Enter password", done: true },
100
- { id: "login-submit", text: "Click Login", done: true },
101
- ]);
102
- ctx.todoStyle("checklist");
63
+ ctx.todos(
64
+ "saucedemo",
65
+ [
66
+ { id: "login-user", text: "Enter username", done: true },
67
+ { id: "login-pass", text: "Enter password", done: true },
68
+ { id: "login-submit", text: "Click Login", done: true },
69
+ ],
70
+ { title: "Sign in", style: "checklist" },
71
+ );
103
72
  ctx.ring("error", {
104
- selector: '[data-test="error"]',
73
+ selector: LoginSel.errorBanner,
105
74
  label: "Login error banner",
106
75
  tone: "danger",
107
76
  focus: true,
@@ -111,16 +80,19 @@ export const SubmitLoginActionBlock = defineMethodBlock<LoginPage, LoginSubmitOu
111
80
  return;
112
81
  }
113
82
  ctx.banner("Inventory · landscape");
114
- // Rotate mobile to landscape on the product shelf (toast + lerp).
115
83
  ctx.landscape();
116
- ctx.todoId("saucedemo-login");
117
- ctx.todos([
118
- { id: "login-user", text: "Enter username" },
119
- { id: "login-pass", text: "Enter password" },
120
- { id: "login-submit", text: "Click Login" },
121
- ]);
122
- ctx.todoIndex(2);
123
- // Landed on inventory - hand off to shopFlow for product -> cart zoom.
84
+ ctx.todos(
85
+ "saucedemo",
86
+ [
87
+ { id: "login-user", text: "Enter username", done: true },
88
+ { id: "login-pass", text: "Enter password", done: true },
89
+ { id: "login-submit", text: "Tap Login", done: true },
90
+ { id: "cart-find", text: "Find the product" },
91
+ { id: "cart-add", text: "Add to cart" },
92
+ { id: "cart-open", text: "Open cart" },
93
+ ],
94
+ { title: "Device showcase", index: 3 },
95
+ );
124
96
  ctx.ring("shelf", {
125
97
  selector: ".inventory_list",
126
98
  label: "Product shelf",
@@ -134,7 +106,7 @@ export const SubmitLoginActionBlock = defineMethodBlock<LoginPage, LoginSubmitOu
134
106
  stubOnError: (ctx: StubCtx) => {
135
107
  ctx.title("Login failed");
136
108
  ctx.ring("error", {
137
- selector: '[data-test="error"]',
109
+ selector: LoginSel.errorBanner,
138
110
  label: "Login error banner",
139
111
  tone: "danger",
140
112
  focus: true,
@@ -1,5 +1,6 @@
1
1
  import { defineMethodBlock, checkpoint, Trait } from "waygraph";
2
2
  import type { LoggedIn, LoginPage } from "../../../states/checkout.states.js";
3
+ import { LoginSel } from "./login.sel.js";
3
4
 
4
5
  /**
5
6
  * Kind: Method
@@ -13,10 +14,10 @@ export const SubmitLogoutBlock = defineMethodBlock<LoggedIn, LoginPage>({
13
14
  description: "Opens the burger menu and logs out.",
14
15
  instruction: {
15
16
  async act(page) {
16
- await page.locator("#react-burger-menu-btn").click();
17
- await page.locator("#logout_sidebar_link").click();
17
+ await page.locator(LoginSel.burgerMenuButton).click();
18
+ await page.locator(LoginSel.logoutLink).click();
18
19
  },
19
20
  resolve: () => checkpoint("LoginPage"),
20
- verify: [Trait.visible("#login-button")],
21
+ verify: [Trait.visible(LoginSel.loginButton)],
21
22
  },
22
23
  });
@@ -1,23 +1,31 @@
1
1
  import { definePageBlock, Trait } from "waygraph";
2
2
  import type { LoginPage } from "../../states/checkout.states.js";
3
- import { SubmitLoginActionBlock } from "./methods/submit-login.method.block.js";
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; method submit-login hangs off this
11
- * page (stubBefore/stubAfter todos live on the Method). Name stays
12
- * `nav-login` so existing flows / chain specs keep working.
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("#login-button")],
25
+ verify: [Trait.visible(LoginSel.loginButton)],
20
26
  methods: {
21
- submitLogin: () => SubmitLoginActionBlock,
27
+ fillUsername: () => FillUsernameBlock,
28
+ fillPassword: () => FillPasswordBlock,
29
+ submitLogin: () => SubmitLoginBlock,
22
30
  },
23
31
  });
@@ -9,10 +9,15 @@ import type {
9
9
  OrderComplete,
10
10
  } from "../states/checkout.states.js";
11
11
  import { NavLoginBlock } from "../blocks/saucedemo-web/nav-login.block.js";
12
+ import { FillUsernameBlock } from "../blocks/saucedemo-web/methods/fill-username.method.block.js";
13
+ import { FillPasswordBlock } from "../blocks/saucedemo-web/methods/fill-password.method.block.js";
12
14
  import { SubmitLoginForFlow } from "../blocks/saucedemo-web/methods/submit-login-for-flow.js";
13
15
  import { AddToCartBlock } from "../blocks/saucedemo-web/inventory/methods/add-to-cart.effect.block.js";
14
16
  import { NavCartBlock } from "../blocks/saucedemo-web/cart/nav-cart.block.js";
15
17
  import { NavCheckoutInfoBlock } from "../blocks/saucedemo-web/cart/nav-checkout-info.block.js";
18
+ import { FillFirstNameBlock } from "../blocks/saucedemo-web/checkout-step-one/methods/fill-first-name.method.block.js";
19
+ import { FillLastNameBlock } from "../blocks/saucedemo-web/checkout-step-one/methods/fill-last-name.method.block.js";
20
+ import { FillPostalCodeBlock } from "../blocks/saucedemo-web/checkout-step-one/methods/fill-postal-code.method.block.js";
16
21
  import { SubmitCheckoutInfoBlock } from "../blocks/saucedemo-web/checkout-step-one/methods/submit-checkout-info.method.block.js";
17
22
  import { FinishOrderBlock } from "../blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.js";
18
23
  import { NavBackToProductsBlock } from "../blocks/saucedemo-web/inventory-item/nav-back-to-products.block.js";
@@ -23,21 +28,31 @@ const engine = new Engine({ headless: false, slowMo: 250 });
23
28
  // (proves OrderComplete -> LoggedIn without a goto teleport).
24
29
  export const checkoutThenBrowseAgainFlow = withTitle(
25
30
  engine.defineFlow<
31
+ LoginPage,
32
+ LoginPage,
26
33
  LoginPage,
27
34
  LoggedIn,
28
35
  ItemInCart,
29
36
  CartPage,
30
37
  CheckoutInfoPage,
38
+ CheckoutInfoPage,
39
+ CheckoutInfoPage,
40
+ CheckoutInfoPage,
31
41
  CheckoutOverviewPage,
32
42
  OrderComplete,
33
43
  LoggedIn
34
44
  >([
35
45
  start,
36
46
  NavLoginBlock,
47
+ FillUsernameBlock,
48
+ FillPasswordBlock,
37
49
  SubmitLoginForFlow,
38
50
  AddToCartBlock,
39
51
  NavCartBlock,
40
52
  NavCheckoutInfoBlock,
53
+ FillFirstNameBlock,
54
+ FillLastNameBlock,
55
+ FillPostalCodeBlock,
41
56
  SubmitCheckoutInfoBlock,
42
57
  FinishOrderBlock,
43
58
  NavBackToProductsBlock,
@@ -11,12 +11,23 @@ import { FfOwnerAuthBlock } from "../blocks/saucedemo-web/ff-owner-auth.block.js
11
11
  import { AddToCartBlock } from "../blocks/saucedemo-web/inventory/methods/add-to-cart.effect.block.js";
12
12
  import { NavCartBlock } from "../blocks/saucedemo-web/cart/nav-cart.block.js";
13
13
  import { NavCheckoutInfoBlock } from "../blocks/saucedemo-web/cart/nav-checkout-info.block.js";
14
+ import { FillFirstNameBlock } from "../blocks/saucedemo-web/checkout-step-one/methods/fill-first-name.method.block.js";
15
+ import { FillLastNameBlock } from "../blocks/saucedemo-web/checkout-step-one/methods/fill-last-name.method.block.js";
16
+ import { FillPostalCodeBlock } from "../blocks/saucedemo-web/checkout-step-one/methods/fill-postal-code.method.block.js";
14
17
  import { SubmitCheckoutInfoBlock } from "../blocks/saucedemo-web/checkout-step-one/methods/submit-checkout-info.method.block.js";
15
18
  import { FinishOrderBlock } from "../blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.js";
16
19
 
17
20
  const engine = new Engine({ headless: false, slowMo: 250 });
18
21
 
19
- // Auth is one FFCompose step so demo pacing skips login; --ff-expand for inners.
22
+ // Atomic nav/action per real URL after auth - the shape `waygraph auto` discovers.
23
+ // Auth is one FFCompose step (ff-owner-auth) so demo pacing skips login yap;
24
+ // use --ff-expand (or loginFlow) when you need per-step auth narration.
25
+ //
26
+ // Demo narration showcase (waygraph 0.11+ / FFCompose 0.12):
27
+ // - FF opaque: one gate for auth; stubs on interesting post-login blocks
28
+ // - Block stubs: add-to-cart / finish-order stubAfter
29
+ // - Flow fixtures: ticket-style captions
30
+ // - Slides on finish-order: multi-step yap with Next between slides
20
31
  export const checkoutFlow = withHighlightFixtures(
21
32
  withTitle(
22
33
  engine.defineFlow<
@@ -24,6 +35,9 @@ export const checkoutFlow = withHighlightFixtures(
24
35
  ItemInCart,
25
36
  CartPage,
26
37
  CheckoutInfoPage,
38
+ CheckoutInfoPage,
39
+ CheckoutInfoPage,
40
+ CheckoutInfoPage,
27
41
  CheckoutOverviewPage,
28
42
  OrderComplete
29
43
  >([
@@ -32,6 +46,9 @@ export const checkoutFlow = withHighlightFixtures(
32
46
  AddToCartBlock,
33
47
  NavCartBlock,
34
48
  NavCheckoutInfoBlock,
49
+ FillFirstNameBlock,
50
+ FillLastNameBlock,
51
+ FillPostalCodeBlock,
35
52
  SubmitCheckoutInfoBlock,
36
53
  FinishOrderBlock,
37
54
  end,
@@ -49,7 +66,9 @@ export const checkoutFlow = withHighlightFixtures(
49
66
  },
50
67
  },
51
68
  },
52
- "submit-login": {
69
+ // Kept for --ff-expand (inners become separate steps again: nav-login,
70
+ // fill-username, fill-password, submit-login).
71
+ "fill-username": {
53
72
  stubBefore: {
54
73
  username: {
55
74
  label: "Demo user",
@@ -57,7 +76,15 @@ export const checkoutFlow = withHighlightFixtures(
57
76
  tag: "AC",
58
77
  duration: true,
59
78
  },
79
+ },
80
+ },
81
+ "fill-password": {
82
+ stubBefore: {
60
83
  password: { label: "Password", detail: "Filled from Mem credentials.", duration: 1500 },
84
+ },
85
+ },
86
+ "submit-login": {
87
+ stubBefore: {
61
88
  submit: { label: "Sign in", tag: "GATE", duration: true, fastMode: 500 },
62
89
  },
63
90
  },
@@ -1,5 +1,7 @@
1
1
  import { Engine, start, end, withTitle } from "waygraph";
2
2
  import { NavLoginBlock } from "../blocks/saucedemo-web/nav-login.block.js";
3
+ import { FillUsernameBlock } from "../blocks/saucedemo-web/methods/fill-username.method.block.js";
4
+ import { FillPasswordBlock } from "../blocks/saucedemo-web/methods/fill-password.method.block.js";
3
5
  import { SubmitLoginForFlow } from "../blocks/saucedemo-web/methods/submit-login-for-flow.js";
4
6
  import { AddToCartBlock } from "../blocks/saucedemo-web/inventory/methods/add-to-cart.effect.block.js";
5
7
  import { NavCartBlock } from "../blocks/saucedemo-web/cart/nav-cart.block.js";
@@ -19,6 +21,8 @@ export const deviceShowcaseFlow = withTitle(
19
21
  engine.defineFlow([
20
22
  start,
21
23
  NavLoginBlock,
24
+ FillUsernameBlock,
25
+ FillPasswordBlock,
22
26
  SubmitLoginForFlow,
23
27
  AddToCartBlock,
24
28
  NavCartBlock,
@@ -1,5 +1,7 @@
1
1
  import { Engine, start, end, withTitle } from "waygraph";
2
2
  import { NavLoginBlock } from "../blocks/saucedemo-web/nav-login.block.js";
3
+ import { FillUsernameBlock } from "../blocks/saucedemo-web/methods/fill-username.method.block.js";
4
+ import { FillPasswordBlock } from "../blocks/saucedemo-web/methods/fill-password.method.block.js";
3
5
  import { SubmitLoginForFlow } from "../blocks/saucedemo-web/methods/submit-login-for-flow.js";
4
6
 
5
7
  const engine = new Engine();
@@ -7,6 +9,6 @@ const engine = new Engine();
7
9
  // The step-mode overlay prepends "Episode N: " itself - the title here is
8
10
  // just the label, not the full heading.
9
11
  export const loginFlow = withTitle(
10
- engine.defineFlow([start, NavLoginBlock, SubmitLoginForFlow, end]),
12
+ engine.defineFlow([start, NavLoginBlock, FillUsernameBlock, FillPasswordBlock, SubmitLoginForFlow, end]),
11
13
  "Sign In",
12
14
  );
@@ -2,6 +2,9 @@ import { Engine, start, end, withTitle } from "waygraph";
2
2
  import { AddToCartBlock } from "../blocks/saucedemo-web/inventory/methods/add-to-cart.effect.block.js";
3
3
  import { NavCartBlock } from "../blocks/saucedemo-web/cart/nav-cart.block.js";
4
4
  import { NavCheckoutInfoBlock } from "../blocks/saucedemo-web/cart/nav-checkout-info.block.js";
5
+ import { FillFirstNameBlock } from "../blocks/saucedemo-web/checkout-step-one/methods/fill-first-name.method.block.js";
6
+ import { FillLastNameBlock } from "../blocks/saucedemo-web/checkout-step-one/methods/fill-last-name.method.block.js";
7
+ import { FillPostalCodeBlock } from "../blocks/saucedemo-web/checkout-step-one/methods/fill-postal-code.method.block.js";
5
8
  import { SubmitCheckoutInfoBlock } from "../blocks/saucedemo-web/checkout-step-one/methods/submit-checkout-info.method.block.js";
6
9
  import { FinishOrderBlock } from "../blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.js";
7
10
 
@@ -15,6 +18,9 @@ export const shopFlow = withTitle(
15
18
  AddToCartBlock,
16
19
  NavCartBlock,
17
20
  NavCheckoutInfoBlock,
21
+ FillFirstNameBlock,
22
+ FillLastNameBlock,
23
+ FillPostalCodeBlock,
18
24
  SubmitCheckoutInfoBlock,
19
25
  FinishOrderBlock,
20
26
  end,