waygraph 0.16.2 → 0.16.4

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 (123) hide show
  1. package/README.md +12 -0
  2. package/dist/analysis/practices-check.d.ts +1 -1
  3. package/dist/analysis/practices-check.js +36 -0
  4. package/dist/beta.d.ts +6 -0
  5. package/dist/beta.js +5 -0
  6. package/dist/cli/commands/codemod-flows.js +2 -2
  7. package/dist/cli/commands/codemod-stubs.js +43 -1
  8. package/dist/cli/commands/pilot.js +3 -16
  9. package/dist/cli/commands/session-ops.js +26 -1
  10. package/dist/cli/flags.d.ts +1 -1
  11. package/dist/cli/flags.js +1 -1
  12. package/dist/cli/usage.js +6 -0
  13. package/dist/demo/narration/stub-ctx.js +126 -124
  14. package/dist/demo/overlay/cursor.js +1 -1
  15. package/dist/demo/overlay/inpage/banner.js +5 -0
  16. package/dist/demo/overlay/inpage/core.js +1 -0
  17. package/dist/demo/overlay/inpage/network.js +1 -1
  18. package/dist/demo/overlay/inpage/todos.js +0 -15
  19. package/dist/demo/overlay/network-capture.js +2 -2
  20. package/dist/demo/overlay/overlay-css.js +18 -21
  21. package/dist/demo/overlay/overlay-stage.js +1 -1
  22. package/dist/demo/overlay/phase-fixtures.js +5 -5
  23. package/dist/demo/overlay/pilot/shell.js +7 -5
  24. package/dist/demo/overlay/ui/components/ring.js +2 -2
  25. package/dist/demo/overlay/ui/overlay.css +98 -35
  26. package/dist/demo/overlay/ui/shadow.js +69 -2
  27. package/dist/demo/stepper/demo-log.js +8 -8
  28. package/dist/demo/stepper/slides.d.ts +1 -1
  29. package/dist/demo/stepper/slides.js +1 -1
  30. package/dist/demo/stepper/stepper.js +1 -1
  31. package/dist/engine/block/kind.d.ts +3 -0
  32. package/dist/engine/block/kind.js +11 -0
  33. package/dist/engine/errors.d.ts +12 -0
  34. package/dist/engine/errors.js +12 -0
  35. package/dist/engine/read/read-block.d.ts +61 -0
  36. package/dist/engine/read/read-block.js +94 -0
  37. package/dist/engine/read/read-key.d.ts +32 -0
  38. package/dist/engine/read/read-key.js +34 -0
  39. package/dist/engine/read/read-page.d.ts +19 -0
  40. package/dist/engine/read/read-page.js +50 -0
  41. package/dist/engine/read/readers.d.ts +82 -0
  42. package/dist/engine/read/readers.js +43 -0
  43. package/dist/engine/read/run-read.d.ts +17 -0
  44. package/dist/engine/read/run-read.js +156 -0
  45. package/dist/engine/run/connect.js +3 -2
  46. package/dist/engine/run/events.d.ts +28 -10
  47. package/dist/engine/run/events.js +52 -38
  48. package/dist/engine/run/run.js +25 -13
  49. package/dist/engine/stub/stub.d.ts +26 -21
  50. package/dist/index.d.ts +7 -4
  51. package/dist/index.js +9 -4
  52. package/dist/live/auto/auto.js +2 -3
  53. package/dist/live/auto/menu.js +3 -2
  54. package/dist/live/auto-session/auto-session.d.ts +9 -2
  55. package/dist/live/auto-session/auto-session.js +23 -20
  56. package/dist/live/auto-session/feed.d.ts +16 -0
  57. package/dist/live/auto-session/feed.js +71 -0
  58. package/dist/live/auto-session/helpers.d.ts +7 -0
  59. package/dist/live/auto-session/helpers.js +9 -0
  60. package/dist/live/auto-session/ipc.d.ts +15 -47
  61. package/dist/live/auto-session/ipc.js +34 -4
  62. package/dist/live/auto-session/protocol.d.ts +127 -0
  63. package/dist/live/auto-session/protocol.js +6 -0
  64. package/dist/live/auto-session/read.d.ts +25 -0
  65. package/dist/live/auto-session/read.js +50 -0
  66. package/dist/live/traverse/worker.d.ts +1 -0
  67. package/dist/live/traverse/worker.js +6 -1
  68. package/dist/manifest/manifest.d.ts +22 -2
  69. package/dist/manifest/manifest.js +27 -1
  70. package/dist/manifest/project.d.ts +10 -1
  71. package/dist/manifest/project.js +9 -12
  72. package/dist/manifest/read-blocks.d.ts +2 -0
  73. package/dist/manifest/read-blocks.js +23 -0
  74. package/dist/manifest/scan.d.ts +3 -2
  75. package/dist/manifest/scan.js +8 -4
  76. package/dist/runner/runner.d.ts +0 -1
  77. package/dist/runner/runner.js +6 -6
  78. package/dist/runtime/full-launch.d.ts +2 -1
  79. package/dist/runtime/full-launch.js +29 -27
  80. package/dist/runtime/run-log.d.ts +2 -0
  81. package/dist/runtime/run-log.js +13 -6
  82. package/examples/saucedemo/README.md +2 -2
  83. package/examples/saucedemo/src/blocks/SITE-MAP.md +3 -0
  84. package/examples/saucedemo/src/blocks/saucedemo-web/cart/cart.read.block.ts +26 -0
  85. package/examples/saucedemo/src/blocks/saucedemo-web/header.read.block.ts +25 -0
  86. package/examples/saucedemo/src/blocks/saucedemo-web/inventory/inventory.read.block.ts +28 -0
  87. package/examples/saucedemo/src/flows/api-demo.flow.ts +1 -1
  88. package/examples/saucedemo/src/flows/cart-bulk.flow.ts +1 -1
  89. package/examples/saucedemo/src/flows/cart-continue.flow.ts +1 -1
  90. package/examples/saucedemo/src/flows/catalog-logout.flow.ts +1 -1
  91. package/examples/saucedemo/src/flows/checkout-then-browse-again.flow.ts +1 -1
  92. package/examples/saucedemo/src/flows/checkout.flow.ts +11 -11
  93. package/examples/saucedemo/src/flows/login.flow.ts +1 -1
  94. package/examples/saucedemo/src/flows/shop.flow.ts +1 -1
  95. package/examples/saucedemo/src/flows/stub-on-error.flow.ts +1 -1
  96. package/examples/saucedemo/src/flows/viewer-blocked.flow.ts +1 -1
  97. package/examples/saucedemo/src/states/checkout.reads.ts +9 -0
  98. package/examples/saucedemo/src/stubs/device-showcase.ts +37 -37
  99. package/examples/saucedemo/src/stubs/finish-order.ts +2 -2
  100. package/examples/saucedemo/src/stubs/login.ts +5 -5
  101. package/package.json +5 -1
  102. package/templates/quickstart/src/flows/api-demo.flow.ts +1 -1
  103. package/templates/quickstart/src/flows/cart-bulk.flow.ts +1 -1
  104. package/templates/quickstart/src/flows/cart-continue.flow.ts +1 -1
  105. package/templates/quickstart/src/flows/catalog-logout.flow.ts +1 -1
  106. package/templates/quickstart/src/flows/checkout-then-browse-again.flow.ts +1 -1
  107. package/templates/quickstart/src/flows/checkout.flow.ts +11 -11
  108. package/templates/quickstart/src/flows/login.flow.ts +1 -1
  109. package/templates/quickstart/src/flows/shop.flow.ts +1 -1
  110. package/templates/quickstart/src/flows/stub-on-error.flow.ts +1 -1
  111. package/templates/quickstart/src/flows/viewer-blocked.flow.ts +1 -1
  112. package/templates/quickstart/src/stubs/device-showcase.ts +37 -37
  113. package/templates/quickstart/src/stubs/finish-order.ts +2 -2
  114. package/templates/quickstart/src/stubs/login.ts +5 -5
  115. package/templates/scaffold/src/flows/(external)/hoppscotch/auth.flow.ts +1 -1
  116. package/templates/scaffold/src/flows/(external)/hoppscotch/get.flow.ts +1 -1
  117. package/templates/scaffold/src/flows/(external)/hoppscotch/post.flow.ts +1 -1
  118. package/templates/scaffold/src/flows/(user-stories)/email-verification.flow.ts +4 -4
  119. package/templates/scaffold/src/flows/README.md +1 -1
  120. package/templates/scaffold/src/flows/home/cart.flow.ts +7 -7
  121. package/templates/scaffold/src/flows/home/hello.flow.ts +8 -8
  122. package/templates/skills/waygraph-convention.skill.md +10 -2
  123. package/templates/skills/waygraph-pilot.skill.md +7 -0
@@ -10,7 +10,7 @@ export const cartBulkEpisode = engine
10
10
  .start()
11
11
  .method(
12
12
  AddAllToCartBlock.stubBefore((ctx) =>
13
- ctx.title("Cart bulk add/remove all"),
13
+ ctx.ui.title("Cart bulk add/remove all"),
14
14
  ),
15
15
  )
16
16
  .method(RemoveAllFromCartBlock)
@@ -7,7 +7,7 @@ export const cartContinueFlow = engine
7
7
  .map()
8
8
  .start()
9
9
  .gotoPage(
10
- NavCartBlock.stubBefore((ctx) => ctx.title("Cart then continue shopping")),
10
+ NavCartBlock.stubBefore((ctx) => ctx.ui.title("Cart then continue shopping")),
11
11
  )
12
12
  .gotoPage(NavContinueShoppingBlock)
13
13
  .end();
@@ -9,7 +9,7 @@ export const catalogLogoutFlow = engine
9
9
  .start()
10
10
  .gotoPage(
11
11
  NavItemDetailBlock.stubBefore((ctx) =>
12
- ctx.title("Catalog browse then logout"),
12
+ ctx.ui.title("Catalog browse then logout"),
13
13
  ),
14
14
  )
15
15
  .gotoPage(NavBackToInventoryBlock)
@@ -21,7 +21,7 @@ export const checkoutThenBrowseAgainFlow = engine
21
21
  .start()
22
22
  .gotoPage(
23
23
  NavLoginBlock.stubBefore((ctx) =>
24
- ctx.title(
24
+ ctx.ui.title(
25
25
  "Owner: Checkout, then click Back Home (click-based NavBlock demo)",
26
26
  ),
27
27
  ),
@@ -21,7 +21,7 @@ export const checkoutFlow = engine
21
21
  .gotoPage(NavLoginBlock, { ff: true })
22
22
  .method(
23
23
  FillUsernameBlock.stubBefore((ctx) => {
24
- ctx.ring("username", {
24
+ ctx.ui.ring("username", {
25
25
  selector: LoginSel.username,
26
26
  label: "Demo user",
27
27
  detail:
@@ -35,7 +35,7 @@ export const checkoutFlow = engine
35
35
  )
36
36
  .method(
37
37
  FillPasswordBlock.stubBefore((ctx) => {
38
- ctx.ring("password", {
38
+ ctx.ui.ring("password", {
39
39
  selector: LoginSel.password,
40
40
  label: "Password",
41
41
  detail: "Filled from Mem credentials.",
@@ -47,7 +47,7 @@ export const checkoutFlow = engine
47
47
  )
48
48
  .method(
49
49
  SubmitLoginForFlow.stubBefore((ctx) => {
50
- ctx.ring("submit", {
50
+ ctx.ui.ring("submit", {
51
51
  selector: LoginSel.loginButton,
52
52
  label: "Sign in",
53
53
  tag: "GATE",
@@ -59,27 +59,27 @@ export const checkoutFlow = engine
59
59
  }),
60
60
  { ff: true },
61
61
  )
62
- .method(AddToCartBlock.stubBefore((ctx) => ctx.title("Owner: Full Checkout")))
62
+ .method(AddToCartBlock.stubBefore((ctx) => ctx.ui.title("Owner: Full Checkout")))
63
63
  .gotoPage(NavCartBlock)
64
64
  .gotoPage(NavCheckoutInfoBlock)
65
65
  .method(
66
66
  FillFirstNameBlock.stubBefore((ctx) => {
67
- ctx.caption("Enter the first name on the order");
68
- ctx.titlePos("left");
67
+ ctx.ui.caption("Enter the first name on the order");
68
+ ctx.ui.titlePos("left");
69
69
  }),
70
70
  )
71
71
  .method(
72
72
  FillLastNameBlock.stubBefore((ctx) => {
73
- ctx.caption("Enter the last name on the order");
74
- ctx.titlePos("center");
73
+ ctx.ui.caption("Enter the last name on the order");
74
+ ctx.ui.titlePos("center");
75
75
  }),
76
76
  )
77
77
  .method(
78
78
  FillPostalCodeBlock.stubBefore((ctx) => {
79
- ctx.caption("Enter a postal code to calculate shipping");
80
- ctx.titlePos("right");
79
+ ctx.ui.caption("Enter a postal code to calculate shipping");
80
+ ctx.ui.titlePos("right");
81
81
  }),
82
82
  )
83
- .method(SubmitCheckoutInfoBlock.stubBefore((ctx) => ctx.hideCaption()))
83
+ .method(SubmitCheckoutInfoBlock.stubBefore((ctx) => ctx.ui.hideCaption()))
84
84
  .method(FinishOrderBlock.stubBefore(placingOrder).stubAfter(orderPlacedYap))
85
85
  .end();
@@ -9,7 +9,7 @@ import { SubmitLoginForFlow } from "../blocks/saucedemo-web/methods/submit-login
9
9
  export const loginFlow = engine
10
10
  .map({ memStub: true })
11
11
  .start()
12
- .gotoPage(NavLoginBlock.stubBefore((ctx) => ctx.title("Sign In")))
12
+ .gotoPage(NavLoginBlock.stubBefore((ctx) => ctx.ui.title("Sign In")))
13
13
  .method(FillUsernameBlock)
14
14
  .method(FillPasswordBlock)
15
15
  .method(SubmitLoginForFlow)
@@ -14,7 +14,7 @@ import { orderPlacedYap, placingOrder } from "../stubs/finish-order.js";
14
14
  export const shopFlow = engine
15
15
  .map({ memStub: true })
16
16
  .start()
17
- .method(AddToCartBlock.stubBefore((ctx) => ctx.title("Shop & Checkout")))
17
+ .method(AddToCartBlock.stubBefore((ctx) => ctx.ui.title("Shop & Checkout")))
18
18
  .gotoPage(NavCartBlock)
19
19
  .gotoPage(NavCheckoutInfoBlock)
20
20
  .method(FillFirstNameBlock)
@@ -19,7 +19,7 @@ export const stubOnErrorFlow = engine
19
19
  .start()
20
20
  .gotoPage(
21
21
  NavLoginBlock.stubBefore((ctx) =>
22
- ctx.title("stubOnError: locked_out fail rings"),
22
+ ctx.ui.title("stubOnError: locked_out fail rings"),
23
23
  ),
24
24
  )
25
25
  .method(FillUsernameBlock)
@@ -19,7 +19,7 @@ export const viewerBlockedFlow = engine
19
19
  .start()
20
20
  .gotoPage(
21
21
  NavLoginBlock.stubBefore((ctx) =>
22
- ctx.title("Viewer: Blocked Login Attempt"),
22
+ ctx.ui.title("Viewer: Blocked Login Attempt"),
23
23
  ),
24
24
  )
25
25
  .method(FillUsernameBlock)
@@ -0,0 +1,9 @@
1
+ import { reads } from "waygraph/beta";
2
+
3
+ // What the store's pages show, by namespace: the Read Blocks fill these, `pilot read` returns them as JSON.
4
+ export const Catalog = reads("catalog")<{
5
+ items: { name: string; price: number; inCart: boolean }[];
6
+ sort: string;
7
+ }>();
8
+ export const Cart = reads("cart")<{ lines: { name: string; qty: number; price: number }[] }>();
9
+ export const Header = reads("header")<{ title: string; cartCount: number }>();
@@ -38,13 +38,13 @@ function checklist(done: number, index: number) {
38
38
  export const deviceShowcase = {
39
39
  username: {
40
40
  before: (ctx: StubCtx) => {
41
- ctx.title("Signing in · mobile");
42
- ctx.device("mobile");
43
- ctx.orientation("portrait");
44
- ctx.todos("saucedemo", ...checklist(0, 0));
45
- ctx.zoom(1.35);
41
+ ctx.ui.title("Signing in · mobile");
42
+ ctx.ui.device("mobile");
43
+ ctx.ui.orientation("portrait");
44
+ ctx.ui.todos("saucedemo", ...checklist(0, 0));
45
+ ctx.ui.zoom(1.35);
46
46
  const fromMem = ctx.mem?.get(LoginCreds.key)?.username;
47
- ctx.ring("username", {
47
+ ctx.ui.ring("username", {
48
48
  selector: LoginSel.username,
49
49
  label: "Username",
50
50
  detail: fromMem
@@ -57,12 +57,12 @@ export const deviceShowcase = {
57
57
  });
58
58
  },
59
59
  after: (ctx: StubCtx) => {
60
- ctx.todos("saucedemo", ...checklist(1, 1));
60
+ ctx.ui.todos("saucedemo", ...checklist(1, 1));
61
61
  },
62
62
  },
63
63
  password: {
64
64
  before: (ctx: StubCtx) => {
65
- ctx.ring("password", {
65
+ ctx.ui.ring("password", {
66
66
  selector: LoginSel.password,
67
67
  label: "Password",
68
68
  detail: "tone: planned (purple)",
@@ -73,12 +73,12 @@ export const deviceShowcase = {
73
73
  });
74
74
  },
75
75
  after: (ctx: StubCtx) => {
76
- ctx.todos("saucedemo", ...checklist(2, 2));
76
+ ctx.ui.todos("saucedemo", ...checklist(2, 2));
77
77
  },
78
78
  },
79
79
  submit: {
80
80
  before: (ctx: StubCtx) => {
81
- ctx.ring("submit", {
81
+ ctx.ui.ring("submit", {
82
82
  selector: LoginSel.loginButton,
83
83
  label: "Login",
84
84
  detail: "tone: warning (yellow)",
@@ -91,10 +91,10 @@ export const deviceShowcase = {
91
91
  });
92
92
  },
93
93
  after: (ctx: StubCtx) => {
94
- ctx.title("Inventory · landscape");
95
- ctx.orientation("landscape");
96
- ctx.todos("saucedemo", ...checklist(3, 3));
97
- ctx.ring("shelf", {
94
+ ctx.ui.title("Inventory · landscape");
95
+ ctx.ui.orientation("landscape");
96
+ ctx.ui.todos("saucedemo", ...checklist(3, 3));
97
+ ctx.ui.ring("shelf", {
98
98
  selector: ".inventory_list",
99
99
  label: "Product shelf",
100
100
  detail: "tone: success (green) - ready to shop",
@@ -107,13 +107,13 @@ export const deviceShowcase = {
107
107
  },
108
108
  addToCart: {
109
109
  before: (ctx: StubCtx) => {
110
- ctx.title("Pick a product · tablet");
111
- ctx.device("tablet");
112
- ctx.orientation("portrait");
113
- ctx.todos("saucedemo", ...checklist(3, 3));
114
- ctx.zoom(1.35);
115
- ctx.zoomOut(false);
116
- ctx.ring("product", {
110
+ ctx.ui.title("Pick a product · tablet");
111
+ ctx.ui.device("tablet");
112
+ ctx.ui.orientation("portrait");
113
+ ctx.ui.todos("saucedemo", ...checklist(3, 3));
114
+ ctx.ui.zoom(1.35);
115
+ ctx.ui.zoomOut(false);
116
+ ctx.ui.ring("product", {
117
117
  selector: InventorySel.title(PRODUCT_ID),
118
118
  label: "Sauce Labs Backpack",
119
119
  detail: "tone: info (blue)",
@@ -122,7 +122,7 @@ export const deviceShowcase = {
122
122
  zoom: 1.45,
123
123
  zoomOut: false,
124
124
  });
125
- ctx.ring("add", {
125
+ ctx.ui.ring("add", {
126
126
  selector: InventorySel.addBtn(PRODUCT_ID),
127
127
  label: "Add to cart",
128
128
  detail: "tone: success (green)",
@@ -134,10 +134,10 @@ export const deviceShowcase = {
134
134
  });
135
135
  },
136
136
  after: (ctx: StubCtx) => {
137
- ctx.title("In the cart");
138
- ctx.todos("saucedemo", ...checklist(4, 4));
139
- ctx.zoomOut(false);
140
- ctx.ring("badge", {
137
+ ctx.ui.title("In the cart");
138
+ ctx.ui.todos("saucedemo", ...checklist(4, 4));
139
+ ctx.ui.zoomOut(false);
140
+ ctx.ui.ring("badge", {
141
141
  selector: InventorySel.cartBadge,
142
142
  label: "Cart badge",
143
143
  detail: "tone: success (green) - count updated",
@@ -150,12 +150,12 @@ export const deviceShowcase = {
150
150
  },
151
151
  openCart: {
152
152
  before: (ctx: StubCtx) => {
153
- ctx.title("Open cart · landscape");
154
- ctx.orientation("landscape");
155
- ctx.todos("saucedemo", ...checklist(5, 5));
156
- ctx.zoom(1.4);
157
- ctx.zoomOut(false);
158
- ctx.ring("cart", {
153
+ ctx.ui.title("Open cart · landscape");
154
+ ctx.ui.orientation("landscape");
155
+ ctx.ui.todos("saucedemo", ...checklist(5, 5));
156
+ ctx.ui.zoom(1.4);
157
+ ctx.ui.zoomOut(false);
158
+ ctx.ui.ring("cart", {
159
159
  selector: CartSel.cartLink,
160
160
  label: "Cart",
161
161
  detail: "tone: planned (purple) - open cart",
@@ -167,11 +167,11 @@ export const deviceShowcase = {
167
167
  });
168
168
  },
169
169
  after: (ctx: StubCtx) => {
170
- ctx.title("Your cart · desktop");
171
- ctx.hideDevice();
172
- ctx.hideTodos();
173
- ctx.zoomOut(true);
174
- ctx.ring("items", {
170
+ ctx.ui.title("Your cart · desktop");
171
+ ctx.ui.hideDevice();
172
+ ctx.ui.hideTodos();
173
+ ctx.ui.zoomOut(true);
174
+ ctx.ui.ring("items", {
175
175
  selector: InventorySel.cartItem,
176
176
  label: "Cart items",
177
177
  detail: "tone: success (green) - product in cart",
@@ -3,12 +3,12 @@ import { CheckoutOverviewSel } from "../blocks/saucedemo-web/checkout-step-two/m
3
3
 
4
4
  /** Rings Finish while the order is placed. */
5
5
  export function placingOrder(ctx: StubCtx): void {
6
- ctx.ring("finish", { selector: CheckoutOverviewSel.finishBtn, label: "Placing the order" });
6
+ ctx.ui.ring("finish", { selector: CheckoutOverviewSel.finishBtn, label: "Placing the order" });
7
7
  }
8
8
 
9
9
  /** Yap slides after the order is placed. They play on the completion page, so they ring its header, not #finish. */
10
10
  export function orderPlacedYap(ctx: StubCtx): void {
11
- ctx.slides([
11
+ ctx.ui.slides([
12
12
  {
13
13
  caption: "Checkout is a short pipeline",
14
14
  detail: "Cart -> info -> overview -> done. You just placed the order.",
@@ -3,8 +3,8 @@ import { LoginSel } from "../blocks/saucedemo-web/methods/login.sel.js";
3
3
 
4
4
  /** What a refused login looks like on screen: the title, a finished checklist and the error banner. */
5
5
  export function loginRefused(ctx: StubCtx): void {
6
- ctx.title("Login blocked");
7
- ctx.todos(
6
+ ctx.ui.title("Login blocked");
7
+ ctx.ui.todos(
8
8
  "saucedemo",
9
9
  [
10
10
  { id: "login-user", text: "Enter username", done: true },
@@ -13,7 +13,7 @@ export function loginRefused(ctx: StubCtx): void {
13
13
  ],
14
14
  { title: "Sign in", style: "checklist" },
15
15
  );
16
- ctx.ring("error", {
16
+ ctx.ui.ring("error", {
17
17
  selector: LoginSel.errorBanner,
18
18
  label: "Login error banner",
19
19
  detail: "tone: danger (red)",
@@ -25,8 +25,8 @@ export function loginRefused(ctx: StubCtx): void {
25
25
 
26
26
  /** Rings the error banner when the login step itself throws. */
27
27
  export function loginFailed(ctx: StubCtx): void {
28
- ctx.title("Login failed");
29
- ctx.ring("error", {
28
+ ctx.ui.title("Login failed");
29
+ ctx.ui.ring("error", {
30
30
  selector: LoginSel.errorBanner,
31
31
  label: "Login error banner",
32
32
  detail: "tone: danger (red)",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "waygraph",
3
- "version": "0.16.2",
3
+ "version": "0.16.4",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": ">=22"
@@ -14,6 +14,10 @@
14
14
  "types": "./dist/index.d.ts",
15
15
  "default": "./dist/index.js"
16
16
  },
17
+ "./beta": {
18
+ "types": "./dist/beta.d.ts",
19
+ "default": "./dist/beta.js"
20
+ },
17
21
  "./runner": {
18
22
  "default": "./dist/runner/runner.js"
19
23
  }
@@ -32,7 +32,7 @@ export const apiDemoEpisode = engine
32
32
  .start()
33
33
  .method(
34
34
  CheckBackendHealth.stubBefore((ctx) => {
35
- ctx.title("Checking backend health · real HTTP request, no browser");
35
+ ctx.ui.title("Checking backend health · real HTTP request, no browser");
36
36
  }),
37
37
  )
38
38
  .end();
@@ -10,7 +10,7 @@ export const cartBulkEpisode = engine
10
10
  .start()
11
11
  .method(
12
12
  AddAllToCartBlock.stubBefore((ctx) =>
13
- ctx.title("Cart bulk add/remove all"),
13
+ ctx.ui.title("Cart bulk add/remove all"),
14
14
  ),
15
15
  )
16
16
  .method(RemoveAllFromCartBlock)
@@ -7,7 +7,7 @@ export const cartContinueFlow = engine
7
7
  .map()
8
8
  .start()
9
9
  .gotoPage(
10
- NavCartBlock.stubBefore((ctx) => ctx.title("Cart then continue shopping")),
10
+ NavCartBlock.stubBefore((ctx) => ctx.ui.title("Cart then continue shopping")),
11
11
  )
12
12
  .gotoPage(NavContinueShoppingBlock)
13
13
  .end();
@@ -9,7 +9,7 @@ export const catalogLogoutFlow = engine
9
9
  .start()
10
10
  .gotoPage(
11
11
  NavItemDetailBlock.stubBefore((ctx) =>
12
- ctx.title("Catalog browse then logout"),
12
+ ctx.ui.title("Catalog browse then logout"),
13
13
  ),
14
14
  )
15
15
  .gotoPage(NavBackToInventoryBlock)
@@ -21,7 +21,7 @@ export const checkoutThenBrowseAgainFlow = engine
21
21
  .start()
22
22
  .gotoPage(
23
23
  NavLoginBlock.stubBefore((ctx) =>
24
- ctx.title(
24
+ ctx.ui.title(
25
25
  "Owner: Checkout, then click Back Home (click-based NavBlock demo)",
26
26
  ),
27
27
  ),
@@ -21,7 +21,7 @@ export const checkoutFlow = engine
21
21
  .gotoPage(NavLoginBlock, { ff: true })
22
22
  .method(
23
23
  FillUsernameBlock.stubBefore((ctx) => {
24
- ctx.ring("username", {
24
+ ctx.ui.ring("username", {
25
25
  selector: LoginSel.username,
26
26
  label: "Demo user",
27
27
  detail:
@@ -35,7 +35,7 @@ export const checkoutFlow = engine
35
35
  )
36
36
  .method(
37
37
  FillPasswordBlock.stubBefore((ctx) => {
38
- ctx.ring("password", {
38
+ ctx.ui.ring("password", {
39
39
  selector: LoginSel.password,
40
40
  label: "Password",
41
41
  detail: "Filled from Mem credentials.",
@@ -47,7 +47,7 @@ export const checkoutFlow = engine
47
47
  )
48
48
  .method(
49
49
  SubmitLoginForFlow.stubBefore((ctx) => {
50
- ctx.ring("submit", {
50
+ ctx.ui.ring("submit", {
51
51
  selector: LoginSel.loginButton,
52
52
  label: "Sign in",
53
53
  tag: "GATE",
@@ -59,27 +59,27 @@ export const checkoutFlow = engine
59
59
  }),
60
60
  { ff: true },
61
61
  )
62
- .method(AddToCartBlock.stubBefore((ctx) => ctx.title("Owner: Full Checkout")))
62
+ .method(AddToCartBlock.stubBefore((ctx) => ctx.ui.title("Owner: Full Checkout")))
63
63
  .gotoPage(NavCartBlock)
64
64
  .gotoPage(NavCheckoutInfoBlock)
65
65
  .method(
66
66
  FillFirstNameBlock.stubBefore((ctx) => {
67
- ctx.caption("Enter the first name on the order");
68
- ctx.titlePos("left");
67
+ ctx.ui.caption("Enter the first name on the order");
68
+ ctx.ui.titlePos("left");
69
69
  }),
70
70
  )
71
71
  .method(
72
72
  FillLastNameBlock.stubBefore((ctx) => {
73
- ctx.caption("Enter the last name on the order");
74
- ctx.titlePos("center");
73
+ ctx.ui.caption("Enter the last name on the order");
74
+ ctx.ui.titlePos("center");
75
75
  }),
76
76
  )
77
77
  .method(
78
78
  FillPostalCodeBlock.stubBefore((ctx) => {
79
- ctx.caption("Enter a postal code to calculate shipping");
80
- ctx.titlePos("right");
79
+ ctx.ui.caption("Enter a postal code to calculate shipping");
80
+ ctx.ui.titlePos("right");
81
81
  }),
82
82
  )
83
- .method(SubmitCheckoutInfoBlock.stubBefore((ctx) => ctx.hideCaption()))
83
+ .method(SubmitCheckoutInfoBlock.stubBefore((ctx) => ctx.ui.hideCaption()))
84
84
  .method(FinishOrderBlock.stubBefore(placingOrder).stubAfter(orderPlacedYap))
85
85
  .end();
@@ -9,7 +9,7 @@ import { SubmitLoginForFlow } from "../blocks/saucedemo-web/methods/submit-login
9
9
  export const loginFlow = engine
10
10
  .map({ memStub: true })
11
11
  .start()
12
- .gotoPage(NavLoginBlock.stubBefore((ctx) => ctx.title("Sign In")))
12
+ .gotoPage(NavLoginBlock.stubBefore((ctx) => ctx.ui.title("Sign In")))
13
13
  .method(FillUsernameBlock)
14
14
  .method(FillPasswordBlock)
15
15
  .method(SubmitLoginForFlow)
@@ -14,7 +14,7 @@ import { orderPlacedYap, placingOrder } from "../stubs/finish-order.js";
14
14
  export const shopFlow = engine
15
15
  .map({ memStub: true })
16
16
  .start()
17
- .method(AddToCartBlock.stubBefore((ctx) => ctx.title("Shop & Checkout")))
17
+ .method(AddToCartBlock.stubBefore((ctx) => ctx.ui.title("Shop & Checkout")))
18
18
  .gotoPage(NavCartBlock)
19
19
  .gotoPage(NavCheckoutInfoBlock)
20
20
  .method(FillFirstNameBlock)
@@ -19,7 +19,7 @@ export const stubOnErrorFlow = engine
19
19
  .start()
20
20
  .gotoPage(
21
21
  NavLoginBlock.stubBefore((ctx) =>
22
- ctx.title("stubOnError: locked_out fail rings"),
22
+ ctx.ui.title("stubOnError: locked_out fail rings"),
23
23
  ),
24
24
  )
25
25
  .method(FillUsernameBlock)
@@ -19,7 +19,7 @@ export const viewerBlockedFlow = engine
19
19
  .start()
20
20
  .gotoPage(
21
21
  NavLoginBlock.stubBefore((ctx) =>
22
- ctx.title("Viewer: Blocked Login Attempt"),
22
+ ctx.ui.title("Viewer: Blocked Login Attempt"),
23
23
  ),
24
24
  )
25
25
  .method(FillUsernameBlock)
@@ -38,13 +38,13 @@ function checklist(done: number, index: number) {
38
38
  export const deviceShowcase = {
39
39
  username: {
40
40
  before: (ctx: StubCtx) => {
41
- ctx.title("Signing in · mobile");
42
- ctx.device("mobile");
43
- ctx.orientation("portrait");
44
- ctx.todos("saucedemo", ...checklist(0, 0));
45
- ctx.zoom(1.35);
41
+ ctx.ui.title("Signing in · mobile");
42
+ ctx.ui.device("mobile");
43
+ ctx.ui.orientation("portrait");
44
+ ctx.ui.todos("saucedemo", ...checklist(0, 0));
45
+ ctx.ui.zoom(1.35);
46
46
  const fromMem = ctx.mem?.get(LoginCreds.key)?.username;
47
- ctx.ring("username", {
47
+ ctx.ui.ring("username", {
48
48
  selector: LoginSel.username,
49
49
  label: "Username",
50
50
  detail: fromMem
@@ -57,12 +57,12 @@ export const deviceShowcase = {
57
57
  });
58
58
  },
59
59
  after: (ctx: StubCtx) => {
60
- ctx.todos("saucedemo", ...checklist(1, 1));
60
+ ctx.ui.todos("saucedemo", ...checklist(1, 1));
61
61
  },
62
62
  },
63
63
  password: {
64
64
  before: (ctx: StubCtx) => {
65
- ctx.ring("password", {
65
+ ctx.ui.ring("password", {
66
66
  selector: LoginSel.password,
67
67
  label: "Password",
68
68
  detail: "tone: planned (purple)",
@@ -73,12 +73,12 @@ export const deviceShowcase = {
73
73
  });
74
74
  },
75
75
  after: (ctx: StubCtx) => {
76
- ctx.todos("saucedemo", ...checklist(2, 2));
76
+ ctx.ui.todos("saucedemo", ...checklist(2, 2));
77
77
  },
78
78
  },
79
79
  submit: {
80
80
  before: (ctx: StubCtx) => {
81
- ctx.ring("submit", {
81
+ ctx.ui.ring("submit", {
82
82
  selector: LoginSel.loginButton,
83
83
  label: "Login",
84
84
  detail: "tone: warning (yellow)",
@@ -91,10 +91,10 @@ export const deviceShowcase = {
91
91
  });
92
92
  },
93
93
  after: (ctx: StubCtx) => {
94
- ctx.title("Inventory · landscape");
95
- ctx.orientation("landscape");
96
- ctx.todos("saucedemo", ...checklist(3, 3));
97
- ctx.ring("shelf", {
94
+ ctx.ui.title("Inventory · landscape");
95
+ ctx.ui.orientation("landscape");
96
+ ctx.ui.todos("saucedemo", ...checklist(3, 3));
97
+ ctx.ui.ring("shelf", {
98
98
  selector: ".inventory_list",
99
99
  label: "Product shelf",
100
100
  detail: "tone: success (green) - ready to shop",
@@ -107,13 +107,13 @@ export const deviceShowcase = {
107
107
  },
108
108
  addToCart: {
109
109
  before: (ctx: StubCtx) => {
110
- ctx.title("Pick a product · tablet");
111
- ctx.device("tablet");
112
- ctx.orientation("portrait");
113
- ctx.todos("saucedemo", ...checklist(3, 3));
114
- ctx.zoom(1.35);
115
- ctx.zoomOut(false);
116
- ctx.ring("product", {
110
+ ctx.ui.title("Pick a product · tablet");
111
+ ctx.ui.device("tablet");
112
+ ctx.ui.orientation("portrait");
113
+ ctx.ui.todos("saucedemo", ...checklist(3, 3));
114
+ ctx.ui.zoom(1.35);
115
+ ctx.ui.zoomOut(false);
116
+ ctx.ui.ring("product", {
117
117
  selector: InventorySel.title(PRODUCT_ID),
118
118
  label: "Sauce Labs Backpack",
119
119
  detail: "tone: info (blue)",
@@ -122,7 +122,7 @@ export const deviceShowcase = {
122
122
  zoom: 1.45,
123
123
  zoomOut: false,
124
124
  });
125
- ctx.ring("add", {
125
+ ctx.ui.ring("add", {
126
126
  selector: InventorySel.addBtn(PRODUCT_ID),
127
127
  label: "Add to cart",
128
128
  detail: "tone: success (green)",
@@ -134,10 +134,10 @@ export const deviceShowcase = {
134
134
  });
135
135
  },
136
136
  after: (ctx: StubCtx) => {
137
- ctx.title("In the cart");
138
- ctx.todos("saucedemo", ...checklist(4, 4));
139
- ctx.zoomOut(false);
140
- ctx.ring("badge", {
137
+ ctx.ui.title("In the cart");
138
+ ctx.ui.todos("saucedemo", ...checklist(4, 4));
139
+ ctx.ui.zoomOut(false);
140
+ ctx.ui.ring("badge", {
141
141
  selector: InventorySel.cartBadge,
142
142
  label: "Cart badge",
143
143
  detail: "tone: success (green) - count updated",
@@ -150,12 +150,12 @@ export const deviceShowcase = {
150
150
  },
151
151
  openCart: {
152
152
  before: (ctx: StubCtx) => {
153
- ctx.title("Open cart · landscape");
154
- ctx.orientation("landscape");
155
- ctx.todos("saucedemo", ...checklist(5, 5));
156
- ctx.zoom(1.4);
157
- ctx.zoomOut(false);
158
- ctx.ring("cart", {
153
+ ctx.ui.title("Open cart · landscape");
154
+ ctx.ui.orientation("landscape");
155
+ ctx.ui.todos("saucedemo", ...checklist(5, 5));
156
+ ctx.ui.zoom(1.4);
157
+ ctx.ui.zoomOut(false);
158
+ ctx.ui.ring("cart", {
159
159
  selector: CartSel.cartLink,
160
160
  label: "Cart",
161
161
  detail: "tone: planned (purple) - open cart",
@@ -167,11 +167,11 @@ export const deviceShowcase = {
167
167
  });
168
168
  },
169
169
  after: (ctx: StubCtx) => {
170
- ctx.title("Your cart · desktop");
171
- ctx.hideDevice();
172
- ctx.hideTodos();
173
- ctx.zoomOut(true);
174
- ctx.ring("items", {
170
+ ctx.ui.title("Your cart · desktop");
171
+ ctx.ui.hideDevice();
172
+ ctx.ui.hideTodos();
173
+ ctx.ui.zoomOut(true);
174
+ ctx.ui.ring("items", {
175
175
  selector: InventorySel.cartItem,
176
176
  label: "Cart items",
177
177
  detail: "tone: success (green) - product in cart",