waygraph 0.15.53 → 0.15.54

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 (108) hide show
  1. package/dist/analysis/graph.d.ts +3 -0
  2. package/dist/auto-session/helpers.d.ts +10 -0
  3. package/dist/blocks-select.d.ts +3 -0
  4. package/dist/blocks-select.js +2 -0
  5. package/dist/config.d.ts +2 -0
  6. package/dist/core/blocks/api.d.ts +1 -0
  7. package/dist/core/blocks/method.d.ts +2 -0
  8. package/dist/core/blocks/method.js +1 -0
  9. package/dist/core/blocks/nav.d.ts +1 -0
  10. package/dist/core/blocks/page.d.ts +1 -0
  11. package/dist/core/branch-regression.d.ts +1 -0
  12. package/dist/core/compose.d.ts +1 -0
  13. package/dist/core/flow.d.ts +1 -0
  14. package/dist/core/map-builder.d.ts +8 -1
  15. package/dist/core/map-builder.js +1 -1
  16. package/dist/core/run-graph.d.ts +2 -0
  17. package/dist/core/run-graph.js +1 -0
  18. package/dist/errors.d.ts +1 -0
  19. package/dist/extensions.d.ts +1 -0
  20. package/dist/extensions.js +1 -0
  21. package/dist/highlights/demo-pace.d.ts +4 -0
  22. package/dist/highlights/demo-pace.js +4 -0
  23. package/dist/highlights/device.d.ts +2 -0
  24. package/dist/highlights/device.js +2 -0
  25. package/dist/highlights/types.d.ts +6 -0
  26. package/dist/session/auto-explore-run.js +6 -0
  27. package/dist/session/overlay-beacon.d.ts +7 -0
  28. package/dist/session/overlay-beacon.js +5 -0
  29. package/dist/session/pilot.d.ts +1 -0
  30. package/dist/traverse/coverage.d.ts +4 -0
  31. package/dist/traverse/coverage.js +3 -0
  32. package/dist/traverse/lease.d.ts +1 -0
  33. package/dist/traverse/lease.js +1 -0
  34. package/dist/traverse/run.d.ts +3 -0
  35. package/examples/routed-demo/src/flows/routed-demo-map.flow.ts +1 -1
  36. package/examples/routed-demo/src/flows/routed-demo.flow.ts +2 -2
  37. package/examples/saucedemo/README.md +11 -12
  38. package/examples/saucedemo/config/waygraph.config.ts +17 -0
  39. package/examples/saucedemo/docs/CONVENTION.md +1 -2
  40. package/examples/saucedemo/docs/HELPERS.md +1 -1
  41. package/examples/saucedemo/package-lock.json +10 -3
  42. package/examples/saucedemo/package.json +12 -29
  43. package/examples/saucedemo/src/blocks/saucedemo-web/cart/nav-cart.block.ts +0 -49
  44. package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.ts +22 -25
  45. package/examples/saucedemo/src/blocks/saucedemo-web/inventory/inventory.page.block.ts +0 -6
  46. package/examples/saucedemo/src/blocks/saucedemo-web/inventory/methods/add-to-cart.effect.block.ts +38 -96
  47. package/examples/saucedemo/src/blocks/saucedemo-web/methods/fill-password.method.block.ts +1 -26
  48. package/examples/saucedemo/src/blocks/saucedemo-web/methods/fill-username.method.block.ts +1 -45
  49. package/examples/saucedemo/src/blocks/saucedemo-web/methods/submit-login.method.block.ts +14 -77
  50. package/examples/saucedemo/src/flows/api-demo.flow.ts +17 -11
  51. package/examples/saucedemo/src/flows/cart-bulk.flow.ts +19 -14
  52. package/examples/saucedemo/src/flows/cart-continue.flow.ts +10 -8
  53. package/examples/saucedemo/src/flows/cart-mem.flow.ts +7 -7
  54. package/examples/saucedemo/src/flows/catalog-logout.flow.ts +13 -8
  55. package/examples/saucedemo/src/flows/checkout-then-browse-again.flow.ts +26 -48
  56. package/examples/saucedemo/src/flows/checkout.flow.ts +70 -86
  57. package/examples/saucedemo/src/flows/device-showcase.flow.ts +24 -25
  58. package/examples/saucedemo/src/flows/login.flow.ts +11 -18
  59. package/examples/saucedemo/src/flows/mem-stub-demo.flow.ts +9 -20
  60. package/examples/saucedemo/src/flows/shop.flow.ts +15 -20
  61. package/examples/saucedemo/src/flows/smoke.flow.ts +12 -27
  62. package/examples/saucedemo/src/flows/stub-on-error.flow.ts +24 -43
  63. package/examples/saucedemo/src/flows/viewer-blocked.flow.ts +26 -34
  64. package/examples/saucedemo/src/states/checkout.mem-stubs.ts +11 -0
  65. package/examples/saucedemo/src/stubs/device-showcase.ts +193 -0
  66. package/examples/saucedemo/src/stubs/login.ts +37 -0
  67. package/examples/saucedemo/tests/chain-flow-episodes.spec.ts +7 -9
  68. package/examples/saucedemo/tests/submit-login-branch.spec.ts +18 -5
  69. package/package.json +3 -2
  70. package/templates/quickstart/README.md +4 -7
  71. package/templates/quickstart/config/waygraph.config.ts +17 -0
  72. package/templates/quickstart/docs/CONVENTION.md +1 -2
  73. package/templates/quickstart/docs/HELPERS.md +1 -1
  74. package/templates/quickstart/package.json +14 -14
  75. package/templates/quickstart/src/blocks/SITE-MAP.md +14 -3
  76. package/templates/quickstart/src/blocks/saucedemo-web/cart/nav-cart.block.ts +0 -49
  77. package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.ts +22 -25
  78. package/templates/quickstart/src/blocks/saucedemo-web/inventory/inventory.page.block.ts +0 -6
  79. package/templates/quickstart/src/blocks/saucedemo-web/inventory/methods/add-to-cart.effect.block.ts +38 -96
  80. package/templates/quickstart/src/blocks/saucedemo-web/methods/fill-password.method.block.ts +1 -26
  81. package/templates/quickstart/src/blocks/saucedemo-web/methods/fill-username.method.block.ts +1 -45
  82. package/templates/quickstart/src/blocks/saucedemo-web/methods/submit-login.method.block.ts +14 -77
  83. package/templates/quickstart/src/flows/api-demo.flow.ts +43 -0
  84. package/templates/quickstart/src/flows/cart-bulk.flow.ts +19 -14
  85. package/templates/quickstart/src/flows/cart-continue.flow.ts +10 -8
  86. package/templates/quickstart/src/flows/cart-mem.flow.ts +7 -7
  87. package/templates/quickstart/src/flows/catalog-logout.flow.ts +13 -8
  88. package/templates/quickstart/src/flows/checkout-then-browse-again.flow.ts +26 -48
  89. package/templates/quickstart/src/flows/checkout.flow.ts +70 -63
  90. package/templates/quickstart/src/flows/device-showcase.flow.ts +24 -25
  91. package/templates/quickstart/src/flows/login.flow.ts +11 -18
  92. package/templates/quickstart/src/flows/mem-stub-demo.flow.ts +12 -0
  93. package/templates/quickstart/src/flows/shop.flow.ts +15 -20
  94. package/templates/quickstart/src/flows/smoke.flow.ts +12 -27
  95. package/templates/quickstart/src/flows/stub-on-error.flow.ts +31 -0
  96. package/templates/quickstart/src/flows/viewer-blocked.flow.ts +26 -34
  97. package/templates/quickstart/src/states/checkout.mem-stubs.ts +11 -0
  98. package/templates/quickstart/src/stubs/device-showcase.ts +193 -0
  99. package/templates/quickstart/src/stubs/login.ts +37 -0
  100. package/templates/quickstart/tests/chain-flow.spec.ts +7 -10
  101. package/templates/skills/waygraph-convention.skill.md +1 -1
  102. package/examples/saucedemo/playwright.config.ts +0 -19
  103. package/examples/saucedemo/scripts/drive-auto-cli.mjs +0 -93
  104. package/examples/saucedemo/scripts/prove-add-to-cart-menu.mjs +0 -126
  105. package/examples/saucedemo/scripts/prove-auto-graph.mjs +0 -92
  106. package/examples/saucedemo/scripts/prove-wrong-login-runtime.mjs +0 -63
  107. package/templates/quickstart/playwright.config.ts +0 -14
  108. package/templates/quickstart/scripts/drive-auto-cli.mjs +0 -93
@@ -1,5 +1,8 @@
1
- import { defineMethodBlock, checkpoint, Trait, type StubCtx } from "waygraph";
2
- import type { LoginPage, LoginSubmitOutcome } from "../../../states/checkout.states.js";
1
+ import { defineMethodBlock, checkpoint, Trait } from "waygraph";
2
+ import type {
3
+ LoginPage,
4
+ LoginSubmitOutcome,
5
+ } from "../../../states/checkout.states.js";
3
6
  import { LoginSel } from "./login.sel.js";
4
7
 
5
8
  type LoginObserve = "success" | "failure";
@@ -14,7 +17,10 @@ type LoginObserve = "success" | "failure";
14
17
  * already did that). One Block, one action: submit.
15
18
  * Branches: good creds -> LoggedIn; bad/locked -> LoginPage with error banner.
16
19
  */
17
- export const SubmitLoginBlock = defineMethodBlock<LoginPage, LoginSubmitOutcome>({
20
+ export const SubmitLoginBlock = defineMethodBlock<
21
+ LoginPage,
22
+ LoginSubmitOutcome
23
+ >({
18
24
  name: "submit-login",
19
25
  description: "Submits the login form; stays on LoginPage when auth fails.",
20
26
  instruction: {
@@ -26,7 +32,9 @@ export const SubmitLoginBlock = defineMethodBlock<LoginPage, LoginSubmitOutcome>
26
32
  async observe(page): Promise<LoginObserve> {
27
33
  // Race inventory nav vs error banner - locked_out / wrong password show
28
34
  // Epic sadface immediately; do not burn the full inventory timeout.
29
- const inventory = page.waitForURL(/\/inventory\.html/, { timeout: 8_000 }).then(() => "success" as const);
35
+ const inventory = page
36
+ .waitForURL(/\/inventory\.html/, { timeout: 8_000 })
37
+ .then(() => "success" as const);
30
38
  const errorBanner = page
31
39
  .locator(LoginSel.errorBanner)
32
40
  .first()
@@ -38,82 +46,11 @@ export const SubmitLoginBlock = defineMethodBlock<LoginPage, LoginSubmitOutcome>
38
46
  return "failure";
39
47
  }
40
48
  },
41
- resolve: (observed) => checkpoint(observed === "success" ? "LoggedIn" : "LoginPage"),
49
+ resolve: (observed) =>
50
+ checkpoint(observed === "success" ? "LoggedIn" : "LoginPage"),
42
51
  verify: (out) =>
43
52
  out.__state === "LoggedIn"
44
53
  ? [Trait.url({ pathname: "/inventory.html" })]
45
54
  : [Trait.visible(LoginSel.errorBanner)],
46
- stubBefore: (ctx: StubCtx) => {
47
- ctx.highlights({
48
- submit: {
49
- selector: LoginSel.loginButton,
50
- label: "Login",
51
- detail: "tone: warning (yellow)",
52
- todo: "login-submit",
53
- tone: "warning",
54
- focus: true,
55
- zoom: 1.55,
56
- weight: "bold",
57
- gesture: "tap",
58
- },
59
- });
60
- },
61
- stubAfter: (ctx: StubCtx) => {
62
- if (ctx.out && ctx.out.__state === "LoginPage") {
63
- ctx.title("Login blocked");
64
- ctx.todos(
65
- "saucedemo",
66
- [
67
- { id: "login-user", text: "Enter username", done: true },
68
- { id: "login-pass", text: "Enter password", done: true },
69
- { id: "login-submit", text: "Click Login", done: true },
70
- ],
71
- { title: "Sign in", style: "checklist" },
72
- );
73
- ctx.ring("error", {
74
- selector: LoginSel.errorBanner,
75
- label: "Login error banner",
76
- detail: "tone: danger (red)",
77
- tone: "danger",
78
- focus: true,
79
- duration: true,
80
- });
81
- return;
82
- }
83
- ctx.banner("Inventory · landscape");
84
- ctx.landscape();
85
- ctx.todos(
86
- "saucedemo",
87
- [
88
- { id: "login-user", text: "Enter username", done: true },
89
- { id: "login-pass", text: "Enter password", done: true },
90
- { id: "login-submit", text: "Tap Login", done: true },
91
- { id: "cart-find", text: "Find the product" },
92
- { id: "cart-add", text: "Add to cart" },
93
- { id: "cart-open", text: "Open cart" },
94
- ],
95
- { title: "Device showcase", index: 3 },
96
- );
97
- ctx.ring("shelf", {
98
- selector: ".inventory_list",
99
- label: "Product shelf",
100
- detail: "tone: success (green) - ready to shop",
101
- tone: "success",
102
- focus: true,
103
- zoom: 1.25,
104
- duration: true,
105
- });
106
- },
107
- stubOnError: (ctx: StubCtx) => {
108
- ctx.title("Login failed");
109
- ctx.ring("error", {
110
- selector: LoginSel.errorBanner,
111
- label: "Login error banner",
112
- detail: "tone: danger (red)",
113
- tone: "danger",
114
- focus: true,
115
- duration: true,
116
- });
117
- },
118
55
  },
119
56
  });
@@ -1,5 +1,6 @@
1
- import { Engine, start, end, withTitle, chainFlow, checkpoint, defineApiBlock } from "waygraph";
1
+ import { checkpoint, defineApiBlock } from "waygraph";
2
2
  import type { Checkpoint, StubCtx } from "waygraph";
3
+ import { engine } from "../../config/waygraph.config.js";
3
4
  import { loginFlow } from "./login.flow.js";
4
5
 
5
6
  /**
@@ -17,21 +18,26 @@ import { loginFlow } from "./login.flow.js";
17
18
  export type BackendHealthy = Checkpoint<"BackendHealthy">;
18
19
  export type BackendDown = Checkpoint<"BackendDown">;
19
20
 
20
- const engine = new Engine();
21
-
22
21
  const CheckBackendHealth = defineApiBlock<any, BackendHealthy | BackendDown>({
23
22
  name: "check-backend-health",
24
- call: ({ request }) => request.get("https://jsonplaceholder.typicode.com/todos/1"),
25
- resolve: (result) => (result.ok ? checkpoint("BackendHealthy") : checkpoint("BackendDown")),
23
+ call: ({ request }) =>
24
+ request.get("https://jsonplaceholder.typicode.com/todos/1"),
25
+ resolve: (result) =>
26
+ result.ok ? checkpoint("BackendHealthy") : checkpoint("BackendDown"),
26
27
  stubBefore: (ctx: StubCtx<BackendHealthy | BackendDown>) => {
27
28
  ctx.title("Checking backend health · real HTTP request, no browser");
28
29
  },
29
30
  });
30
31
 
31
- export const apiDemoEpisode = withTitle(
32
- engine.defineFlow([start, CheckBackendHealth, end]),
33
- "Backend health check (defineApiBlock)",
34
- );
32
+ export const apiDemoEpisode = engine
33
+ .map()
34
+ .start()
35
+ .method(CheckBackendHealth)
36
+ .end();
35
37
 
36
- /** Full demo: Sign In (FE) -> backend health check (BE), one narrated Flow. */
37
- export const apiDemoFlow = chainFlow(loginFlow, apiDemoEpisode);
38
+ export const apiDemoFlow = engine
39
+ .map({ memStub: true })
40
+ .start()
41
+ .flow(loginFlow)
42
+ .flow(apiDemoEpisode)
43
+ .end();
@@ -1,19 +1,24 @@
1
- import { Engine, start, end, withTitle, chainFlow } from "waygraph";
1
+ import { engine } from "../../config/waygraph.config.js";
2
+ import "../states/checkout.mem-stubs.js";
2
3
  import { loginFlow } from "./login.flow.js";
3
4
  import { AddAllToCartBlock } from "../blocks/saucedemo-web/inventory/methods/add-all-to-cart.method.block.js";
4
5
  import { RemoveAllFromCartBlock } from "../blocks/saucedemo-web/inventory/methods/remove-all-from-cart.method.block.js";
5
6
 
6
- const engine = new Engine();
7
+ /** Add every item, then remove them all (the bulk Methods). */
8
+ export const cartBulkEpisode = engine
9
+ .map()
10
+ .start()
11
+ .method(
12
+ AddAllToCartBlock.stubBefore((ctx) =>
13
+ ctx.title("Cart bulk add/remove all"),
14
+ ),
15
+ )
16
+ .method(RemoveAllFromCartBlock)
17
+ .end();
7
18
 
8
- /**
9
- * Episode after login: drain every Add button, then every Remove button.
10
- * Proves bulk Methods + round-trip (LoggedIn <-> ItemInCart) without
11
- * instanceOptions. Pair with loginFlow via chainFlow for `waygraph demo`.
12
- */
13
- export const cartBulkEpisode = withTitle(
14
- engine.defineFlow([start, AddAllToCartBlock, RemoveAllFromCartBlock, end]),
15
- "Cart bulk add/remove all",
16
- );
17
-
18
- /** Full demo: Sign In -> Add all -> Remove all. */
19
- export const cartBulkFlow = chainFlow(loginFlow, cartBulkEpisode);
19
+ export const cartBulkFlow = engine
20
+ .map({ memStub: true })
21
+ .start()
22
+ .flow(loginFlow)
23
+ .flow(cartBulkEpisode)
24
+ .end();
@@ -1,11 +1,13 @@
1
- import { Engine, start, end, withTitle } from "waygraph";
1
+ import { engine } from "../../config/waygraph.config.js";
2
+ import "../states/checkout.mem-stubs.js";
2
3
  import { NavCartBlock } from "../blocks/saucedemo-web/cart/nav-cart.block.js";
3
4
  import { NavContinueShoppingBlock } from "../blocks/saucedemo-web/inventory-item/nav-continue-shopping.block.js";
4
5
 
5
- const engine = new Engine();
6
-
7
- // Open cart and continue shopping - wires orphan nav-continue-shopping Block.
8
- export const cartContinueFlow = withTitle(
9
- engine.defineFlow([start, NavCartBlock, NavContinueShoppingBlock, end]),
10
- "Cart then continue shopping",
11
- );
6
+ export const cartContinueFlow = engine
7
+ .map()
8
+ .start()
9
+ .gotoPage(
10
+ NavCartBlock.stubBefore((ctx) => ctx.title("Cart then continue shopping")),
11
+ )
12
+ .gotoPage(NavContinueShoppingBlock)
13
+ .end();
@@ -1,9 +1,9 @@
1
- import { Engine, start, end } from "waygraph";
1
+ import { engine } from "../../config/waygraph.config.js";
2
+ import "../states/checkout.mem-stubs.js";
2
3
  import { RemoveFromCartBlock } from "../blocks/saucedemo-web/inventory/methods/remove-from-cart.effect.block.js";
3
4
 
4
- const engine = new Engine();
5
-
6
- // Registers remove-from-cart in the discoverable graph so waygraph auto can
7
- // offer live "Remove … from cart" rows. Not a product checkout path - Add /
8
- // Remove pairing for interactive explore.
9
- export const cartMemFlow = engine.defineFlow([start, RemoveFromCartBlock, end]);
5
+ export const cartMemFlow = engine
6
+ .map()
7
+ .start()
8
+ .method(RemoveFromCartBlock)
9
+ .end();
@@ -1,12 +1,17 @@
1
- import { Engine, start, end, withTitle } from "waygraph";
1
+ import { engine } from "../../config/waygraph.config.js";
2
+ import "../states/checkout.mem-stubs.js";
2
3
  import { NavItemDetailBlock } from "../blocks/saucedemo-web/inventory/nav-item-detail.block.js";
3
4
  import { NavBackToInventoryBlock } from "../blocks/saucedemo-web/inventory-item/nav-back-to-inventory.block.js";
4
5
  import { SubmitLogoutBlock } from "../blocks/saucedemo-web/methods/submit-logout.method.block.js";
5
6
 
6
- const engine = new Engine();
7
-
8
- // Browse one product, return to inventory, log out - wires orphan catalog + logout Blocks.
9
- export const catalogLogoutFlow = withTitle(
10
- engine.defineFlow([start, NavItemDetailBlock, NavBackToInventoryBlock, SubmitLogoutBlock, end]),
11
- "Catalog browse then logout",
12
- );
7
+ export const catalogLogoutFlow = engine
8
+ .map()
9
+ .start()
10
+ .gotoPage(
11
+ NavItemDetailBlock.stubBefore((ctx) =>
12
+ ctx.title("Catalog browse then logout"),
13
+ ),
14
+ )
15
+ .gotoPage(NavBackToInventoryBlock)
16
+ .method(SubmitLogoutBlock)
17
+ .end();
@@ -1,13 +1,5 @@
1
- import { Engine, start, end, withTitle } from "waygraph";
2
- import type {
3
- LoginPage,
4
- LoggedIn,
5
- ItemInCart,
6
- CartPage,
7
- CheckoutInfoPage,
8
- CheckoutOverviewPage,
9
- OrderComplete,
10
- } from "../states/checkout.states.js";
1
+ import { engine } from "../../config/waygraph.config.js";
2
+ import "../states/checkout.mem-stubs.js";
11
3
  import { NavLoginBlock } from "../blocks/saucedemo-web/nav-login.block.js";
12
4
  import { FillUsernameBlock } from "../blocks/saucedemo-web/methods/fill-username.method.block.js";
13
5
  import { FillPasswordBlock } from "../blocks/saucedemo-web/methods/fill-password.method.block.js";
@@ -22,41 +14,27 @@ import { SubmitCheckoutInfoBlock } from "../blocks/saucedemo-web/checkout-step-o
22
14
  import { FinishOrderBlock } from "../blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.js";
23
15
  import { NavBackToProductsBlock } from "../blocks/saucedemo-web/inventory-item/nav-back-to-products.block.js";
24
16
 
25
- const engine = new Engine({ headless: false, slowMo: 250 });
26
-
27
- // Same atomic checkout chain, plus click-based nav-back-to-products
28
- // (proves OrderComplete -> LoggedIn without a goto teleport).
29
- export const checkoutThenBrowseAgainFlow = withTitle(
30
- engine.defineFlow<
31
- LoginPage,
32
- LoginPage,
33
- LoginPage,
34
- LoggedIn,
35
- ItemInCart,
36
- CartPage,
37
- CheckoutInfoPage,
38
- CheckoutInfoPage,
39
- CheckoutInfoPage,
40
- CheckoutInfoPage,
41
- CheckoutOverviewPage,
42
- OrderComplete,
43
- LoggedIn
44
- >([
45
- start,
46
- NavLoginBlock,
47
- FillUsernameBlock,
48
- FillPasswordBlock,
49
- SubmitLoginForFlow,
50
- AddToCartBlock,
51
- NavCartBlock,
52
- NavCheckoutInfoBlock,
53
- FillFirstNameBlock,
54
- FillLastNameBlock,
55
- FillPostalCodeBlock,
56
- SubmitCheckoutInfoBlock,
57
- FinishOrderBlock,
58
- NavBackToProductsBlock,
59
- end,
60
- ]),
61
- "Owner: Checkout, then click Back Home (click-based NavBlock demo)",
62
- );
17
+ /** Full checkout, then the "Back Home" click-based Nav Block returns to the catalogue. */
18
+ export const checkoutThenBrowseAgainFlow = engine
19
+ .map({ memStub: true })
20
+ .start()
21
+ .gotoPage(
22
+ NavLoginBlock.stubBefore((ctx) =>
23
+ ctx.title(
24
+ "Owner: Checkout, then click Back Home (click-based NavBlock demo)",
25
+ ),
26
+ ),
27
+ )
28
+ .method(FillUsernameBlock)
29
+ .method(FillPasswordBlock)
30
+ .method(SubmitLoginForFlow)
31
+ .method(AddToCartBlock)
32
+ .gotoPage(NavCartBlock)
33
+ .gotoPage(NavCheckoutInfoBlock)
34
+ .method(FillFirstNameBlock)
35
+ .method(FillLastNameBlock)
36
+ .method(FillPostalCodeBlock)
37
+ .method(SubmitCheckoutInfoBlock)
38
+ .method(FinishOrderBlock)
39
+ .gotoPage(NavBackToProductsBlock)
40
+ .end();
@@ -1,4 +1,5 @@
1
- import { Engine, withTitle } from "waygraph";
1
+ import { engine } from "../../config/waygraph.config.js";
2
+ import "../states/checkout.mem-stubs.js";
2
3
  import { NavLoginBlock } from "../blocks/saucedemo-web/nav-login.block.js";
3
4
  import { FillUsernameBlock } from "../blocks/saucedemo-web/methods/fill-username.method.block.js";
4
5
  import { FillPasswordBlock } from "../blocks/saucedemo-web/methods/fill-password.method.block.js";
@@ -13,88 +14,71 @@ import { SubmitCheckoutInfoBlock } from "../blocks/saucedemo-web/checkout-step-o
13
14
  import { FinishOrderBlock } from "../blocks/saucedemo-web/checkout-step-two/methods/finish-order.method.block.js";
14
15
  import { LoginSel } from "../blocks/saucedemo-web/methods/login.sel.js";
15
16
 
16
- const engine = new Engine({ headless: false, slowMo: 250 });
17
-
18
- /**
19
- * Owner checkout via map() with inline `{ ff: true }` (no separate
20
- * FfOwnerAuthBlock, no HighlightFixtureMap, no .ffStart()/.ffEnd() bracket -
21
- * the three auth steps below merge into one fast-forward block just by
22
- * flagging each one). Auth collapses to one blitz step; post-login blocks
23
- * keep their own ctx stubBefore/stubAfter. Call-site decorate example on
24
- * fill-username when --ff-expand shows inners again.
25
- *
26
- * Also demonstrates two other recent conventions on the checkout-step-one
27
- * leg: ctx.caption() (bottom subtitle-bar, ported from zsign's help-center
28
- * clip engine) narrating each field, and ctx.titlePos() moving the banner
29
- * left -> center -> right across three consecutive steps.
30
- */
31
- export const checkoutFlow = withTitle(
32
- engine
33
- .map()
34
- .start()
35
- .gotoPage(NavLoginBlock, { ff: true })
36
- .method(
37
- FillUsernameBlock.stubBefore((ctx) => {
38
- ctx.ring("username", {
39
- selector: LoginSel.username,
40
- label: "Demo user",
41
- detail: "standard_user from Mem - library block stays neutral underneath",
42
- tag: "AC",
43
- duration: true,
44
- focus: true,
45
- });
46
- }),
47
- { ff: true },
48
- )
49
- .method(
50
- FillPasswordBlock.stubBefore((ctx) => {
51
- ctx.ring("password", {
52
- selector: LoginSel.password,
53
- label: "Password",
54
- detail: "Filled from Mem credentials.",
55
- duration: 1500,
56
- focus: true,
57
- });
58
- }),
59
- { ff: true },
60
- )
61
- .method(
62
- SubmitLoginForFlow.stubBefore((ctx) => {
63
- ctx.ring("submit", {
64
- selector: LoginSel.loginButton,
65
- label: "Sign in",
66
- tag: "GATE",
67
- duration: true,
68
- fastMode: 500,
69
- focus: true,
70
- weight: "bold",
71
- });
72
- }),
73
- { ff: true },
74
- )
75
- .method(AddToCartBlock)
76
- .gotoPage(NavCartBlock)
77
- .gotoPage(NavCheckoutInfoBlock)
78
- .method(
79
- FillFirstNameBlock.stubBefore((ctx) => {
80
- ctx.caption("Enter the first name on the order");
81
- ctx.titlePos("left");
82
- }),
83
- )
84
- .method(
85
- FillLastNameBlock.stubBefore((ctx) => {
86
- ctx.caption("Enter the last name on the order");
87
- ctx.titlePos("center");
88
- }),
89
- )
90
- .method(
91
- FillPostalCodeBlock.stubBefore((ctx) => {
92
- ctx.caption("Enter a postal code to calculate shipping");
93
- ctx.titlePos("right");
94
- }),
95
- )
96
- .method(SubmitCheckoutInfoBlock.stubBefore((ctx) => ctx.hideCaption()))
97
- .method(FinishOrderBlock)
98
- .end(),
99
- "Owner: Full Checkout",
100
- );
17
+ export const checkoutFlow = engine
18
+ .map({ memStub: true })
19
+ .start()
20
+ .gotoPage(NavLoginBlock, { ff: true })
21
+ .method(
22
+ FillUsernameBlock.stubBefore((ctx) => {
23
+ ctx.ring("username", {
24
+ selector: LoginSel.username,
25
+ label: "Demo user",
26
+ detail:
27
+ "standard_user from Mem - library block stays neutral underneath",
28
+ tag: "AC",
29
+ duration: true,
30
+ focus: true,
31
+ });
32
+ }),
33
+ { ff: true },
34
+ )
35
+ .method(
36
+ FillPasswordBlock.stubBefore((ctx) => {
37
+ ctx.ring("password", {
38
+ selector: LoginSel.password,
39
+ label: "Password",
40
+ detail: "Filled from Mem credentials.",
41
+ duration: 1500,
42
+ focus: true,
43
+ });
44
+ }),
45
+ { ff: true },
46
+ )
47
+ .method(
48
+ SubmitLoginForFlow.stubBefore((ctx) => {
49
+ ctx.ring("submit", {
50
+ selector: LoginSel.loginButton,
51
+ label: "Sign in",
52
+ tag: "GATE",
53
+ duration: true,
54
+ fastMode: 500,
55
+ focus: true,
56
+ weight: "bold",
57
+ });
58
+ }),
59
+ { ff: true },
60
+ )
61
+ .method(AddToCartBlock.stubBefore((ctx) => ctx.title("Owner: Full Checkout")))
62
+ .gotoPage(NavCartBlock)
63
+ .gotoPage(NavCheckoutInfoBlock)
64
+ .method(
65
+ FillFirstNameBlock.stubBefore((ctx) => {
66
+ ctx.caption("Enter the first name on the order");
67
+ ctx.titlePos("left");
68
+ }),
69
+ )
70
+ .method(
71
+ FillLastNameBlock.stubBefore((ctx) => {
72
+ ctx.caption("Enter the last name on the order");
73
+ ctx.titlePos("center");
74
+ }),
75
+ )
76
+ .method(
77
+ FillPostalCodeBlock.stubBefore((ctx) => {
78
+ ctx.caption("Enter a postal code to calculate shipping");
79
+ ctx.titlePos("right");
80
+ }),
81
+ )
82
+ .method(SubmitCheckoutInfoBlock.stubBefore((ctx) => ctx.hideCaption()))
83
+ .method(FinishOrderBlock)
84
+ .end();
@@ -1,32 +1,31 @@
1
- import { Engine, start, end, withTitle } from "waygraph";
1
+ import { engine } from "../../config/waygraph.config.js";
2
+ import "../states/checkout.mem-stubs.js";
2
3
  import { NavLoginBlock } from "../blocks/saucedemo-web/nav-login.block.js";
3
4
  import { FillUsernameBlock } from "../blocks/saucedemo-web/methods/fill-username.method.block.js";
4
5
  import { FillPasswordBlock } from "../blocks/saucedemo-web/methods/fill-password.method.block.js";
5
6
  import { SubmitLoginForFlow } from "../blocks/saucedemo-web/methods/submit-login-for-flow.js";
6
7
  import { AddToCartBlock } from "../blocks/saucedemo-web/inventory/methods/add-to-cart.effect.block.js";
7
8
  import { NavCartBlock } from "../blocks/saucedemo-web/cart/nav-cart.block.js";
9
+ import { deviceShowcase as d } from "../stubs/device-showcase.js";
8
10
 
9
- const engine = new Engine();
10
-
11
- /**
12
- * Short device/orientation showcase (0.13.3+):
13
- * login mobile portrait -> land on inventory landscape ->
14
- * add-to-cart tablet portrait -> open cart tablet landscape -> desktop
15
- *
16
- * Run:
17
- * npm run demo:device
18
- * npm run demo:device:video
19
- */
20
- export const deviceShowcaseFlow = withTitle(
21
- engine.defineFlow([
22
- start,
23
- NavLoginBlock,
24
- FillUsernameBlock,
25
- FillPasswordBlock,
26
- SubmitLoginForFlow,
27
- AddToCartBlock,
28
- NavCartBlock,
29
- end,
30
- ]),
31
- "Device showcase",
32
- );
11
+ /** Sign in on a phone, shop on a tablet, open the cart in landscape: the device and zoom narration in src/stubs/device-showcase.ts. */
12
+ export const deviceShowcaseFlow = engine
13
+ .map({ memStub: true })
14
+ .start()
15
+ .gotoPage(NavLoginBlock)
16
+ .method(
17
+ FillUsernameBlock.stubBefore(d.username.before).stubAfter(d.username.after),
18
+ )
19
+ .method(
20
+ FillPasswordBlock.stubBefore(d.password.before).stubAfter(d.password.after),
21
+ )
22
+ .method(
23
+ SubmitLoginForFlow.stubBefore(d.submit.before).stubAfter(d.submit.after),
24
+ )
25
+ .method(
26
+ AddToCartBlock.stubBefore(d.addToCart.before).stubAfter(d.addToCart.after),
27
+ )
28
+ .gotoPage(
29
+ NavCartBlock.stubBefore(d.openCart.before).stubAfter(d.openCart.after),
30
+ )
31
+ .end();
@@ -1,23 +1,16 @@
1
- import { Engine, withTitle } from "waygraph";
1
+ import { engine } from "../../config/waygraph.config.js";
2
+ import "../states/checkout.mem-stubs.js";
2
3
  import { NavLoginBlock } from "../blocks/saucedemo-web/nav-login.block.js";
3
4
  import { FillUsernameBlock } from "../blocks/saucedemo-web/methods/fill-username.method.block.js";
4
5
  import { FillPasswordBlock } from "../blocks/saucedemo-web/methods/fill-password.method.block.js";
5
6
  import { SubmitLoginForFlow } from "../blocks/saucedemo-web/methods/submit-login-for-flow.js";
6
7
 
7
- const engine = new Engine();
8
-
9
- // The step-mode overlay prepends "Episode N: " itself - the title here is
10
- // just the label, not the full heading.
11
- // map() + ctx stubs on the Method blocks (see fill-username / fill-password /
12
- // submit-login) - no HighlightFixtureMap.
13
- export const loginFlow = withTitle(
14
- engine
15
- .map()
16
- .start()
17
- .gotoPage(NavLoginBlock)
18
- .method(FillUsernameBlock)
19
- .method(FillPasswordBlock)
20
- .method(SubmitLoginForFlow)
21
- .end(),
22
- "Sign In",
23
- );
8
+ /** Standard user signs in. Credentials come from the memStub in src/states/checkout.mem-stubs.ts unless --data / mem set them. */
9
+ export const loginFlow = engine
10
+ .map({ memStub: true })
11
+ .start()
12
+ .gotoPage(NavLoginBlock.stubBefore((ctx) => ctx.title("Sign In")))
13
+ .method(FillUsernameBlock)
14
+ .method(FillPasswordBlock)
15
+ .method(SubmitLoginForFlow)
16
+ .end();
@@ -1,23 +1,12 @@
1
- import { Engine, withMemStub, registerMemStub } from "waygraph";
1
+ import { engine } from "../../config/waygraph.config.js";
2
+ import "../states/checkout.mem-stubs.js";
2
3
  import { NavLoginBlock } from "../blocks/saucedemo-web/nav-login.block.js";
3
4
  import { FillUsernameBlock } from "../blocks/saucedemo-web/methods/fill-username.method.block.js";
4
- import { LoginCreds } from "../states/checkout.mem-keys.js";
5
5
 
6
- /**
7
- * Test-only fixture for waygraph's own `--mem-stub` CLI flag
8
- * (tests/cli/mem-stub.spec.ts) - not part of the saucedemo showcase's own
9
- * demo/story. Registers a fake LoginCreds so `waygraph run
10
- * mem-stub-demo.flow.ts --mem-stub` succeeds with zero --data, proving the
11
- * registry + preflight fallback work against the real CLI, not just the
12
- * in-process engine tests in tests/core/mem-stub.spec.ts.
13
- */
14
- registerMemStub(LoginCreds.key, () => ({
15
- username: "standard_user",
16
- password: "secret_sauce",
17
- }));
18
-
19
- const engine = new Engine();
20
-
21
- export const memStubDemoFlow = withMemStub(
22
- engine.map().start().gotoPage(NavLoginBlock).method(FillUsernameBlock).end(),
23
- );
6
+ /** memStub: the credentials are never supplied; src/states/checkout.mem-stubs.ts fills them. */
7
+ export const memStubDemoFlow = engine
8
+ .map({ memStub: true })
9
+ .start()
10
+ .gotoPage(NavLoginBlock)
11
+ .method(FillUsernameBlock)
12
+ .end();