waygraph 0.7.11 → 0.7.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/auto-explore-run.js +15 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +61 -21
- package/dist/step-overlay.js +29 -20
- package/examples/saucedemo/README.md +35 -8
- package/examples/saucedemo/docs/CONVENTION.md +32 -14
- package/examples/saucedemo/package-lock.json +118 -0
- package/examples/saucedemo/scripts/capture-wrong-login.mjs +2 -2
- package/examples/saucedemo/scripts/prove-wrong-login-runtime.mjs +2 -2
- package/examples/saucedemo/src/blocks/SITE-MAP.md +43 -0
- package/examples/saucedemo/src/blocks/saucedemo-web/NAV.md +26 -0
- package/examples/saucedemo/src/blocks/saucedemo-web/actions/submit-login-for-flow.ts +13 -0
- package/examples/saucedemo/src/blocks/{actions → saucedemo-web/actions}/submit-login.action.block.ts +14 -10
- package/{templates/quickstart/src/blocks → examples/saucedemo/src/blocks/saucedemo-web}/actions/submit-logout.action.block.ts +8 -3
- package/examples/saucedemo/src/blocks/saucedemo-web/cart/NAV.md +22 -0
- package/{templates/quickstart/src/blocks → examples/saucedemo/src/blocks/saucedemo-web/cart}/nav-cart.block.ts +8 -3
- package/{templates/quickstart/src/blocks → examples/saucedemo/src/blocks/saucedemo-web/cart}/nav-checkout-info.block.ts +8 -1
- package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one/NAV.md +21 -0
- package/{templates/quickstart/src/blocks → examples/saucedemo/src/blocks/saucedemo-web/checkout-step-one}/actions/submit-checkout-info.action.block.ts +9 -6
- package/examples/saucedemo/src/blocks/saucedemo-web/checkout-step-two/NAV.md +21 -0
- package/{templates/quickstart/src/blocks → examples/saucedemo/src/blocks/saucedemo-web/checkout-step-two}/actions/finish-order.action.block.ts +8 -1
- package/examples/saucedemo/src/blocks/saucedemo-web/inventory/NAV.md +26 -0
- package/examples/saucedemo/src/blocks/{actions → saucedemo-web/inventory/actions}/add-to-cart.effect.block.ts +10 -4
- package/{templates/quickstart/src/blocks → examples/saucedemo/src/blocks/saucedemo-web/inventory}/actions/inventory-items.ts +8 -0
- package/{templates/quickstart/src/blocks → examples/saucedemo/src/blocks/saucedemo-web/inventory}/actions/remove-from-cart.effect.block.ts +10 -4
- package/examples/saucedemo/src/blocks/{nav-item-detail.block.ts → saucedemo-web/inventory/nav-item-detail.block.ts} +10 -4
- package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/NAV.md +25 -0
- package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/nav-back-to-inventory.block.ts +18 -0
- package/examples/saucedemo/src/blocks/saucedemo-web/inventory-item/nav-back-to-products.block.ts +18 -0
- package/examples/saucedemo/src/blocks/{nav-continue-shopping.block.ts → saucedemo-web/inventory-item/nav-continue-shopping.block.ts} +8 -2
- package/examples/saucedemo/src/blocks/{nav-login.block.ts → saucedemo-web/nav-login.block.ts} +8 -3
- package/examples/saucedemo/src/flows/cart-continue.flow.ts +2 -2
- package/examples/saucedemo/src/flows/cart-mem.flow.ts +1 -1
- package/examples/saucedemo/src/flows/catalog-logout.flow.ts +3 -3
- package/examples/saucedemo/src/flows/checkout-then-browse-again.flow.ts +8 -8
- package/examples/saucedemo/src/flows/checkout.flow.ts +7 -7
- package/examples/saucedemo/src/flows/login.flow.ts +2 -2
- package/examples/saucedemo/src/flows/shop.flow.ts +5 -5
- package/examples/saucedemo/src/flows/smoke.flow.ts +3 -3
- package/examples/saucedemo/src/flows/viewer-blocked.flow.ts +2 -2
- package/examples/saucedemo/tests/flow-block-verify.spec.ts +1 -1
- package/examples/saucedemo/tests/submit-login-branch.spec.ts +2 -2
- package/package.json +1 -1
- package/templates/quickstart/README.md +10 -0
- package/templates/quickstart/docs/CONVENTION.md +48 -26
- package/templates/quickstart/package.json +1 -1
- package/templates/quickstart/src/blocks/SITE-MAP.md +43 -0
- package/templates/quickstart/src/blocks/saucedemo-web/NAV.md +26 -0
- package/templates/quickstart/src/blocks/saucedemo-web/actions/submit-login-for-flow.ts +13 -0
- package/templates/quickstart/src/blocks/{actions → saucedemo-web/actions}/submit-login.action.block.ts +14 -10
- package/{examples/saucedemo/src/blocks → templates/quickstart/src/blocks/saucedemo-web}/actions/submit-logout.action.block.ts +8 -3
- package/templates/quickstart/src/blocks/saucedemo-web/cart/NAV.md +22 -0
- package/{examples/saucedemo/src/blocks → templates/quickstart/src/blocks/saucedemo-web/cart}/nav-cart.block.ts +8 -3
- package/{examples/saucedemo/src/blocks → templates/quickstart/src/blocks/saucedemo-web/cart}/nav-checkout-info.block.ts +8 -1
- package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-one/NAV.md +21 -0
- package/{examples/saucedemo/src/blocks → templates/quickstart/src/blocks/saucedemo-web/checkout-step-one}/actions/submit-checkout-info.action.block.ts +9 -6
- package/templates/quickstart/src/blocks/saucedemo-web/checkout-step-two/NAV.md +21 -0
- package/{examples/saucedemo/src/blocks → templates/quickstart/src/blocks/saucedemo-web/checkout-step-two}/actions/finish-order.action.block.ts +8 -1
- package/templates/quickstart/src/blocks/saucedemo-web/inventory/NAV.md +26 -0
- package/templates/quickstart/src/blocks/{actions → saucedemo-web/inventory/actions}/add-to-cart.effect.block.ts +10 -4
- package/{examples/saucedemo/src/blocks → templates/quickstart/src/blocks/saucedemo-web/inventory}/actions/inventory-items.ts +8 -0
- package/{examples/saucedemo/src/blocks → templates/quickstart/src/blocks/saucedemo-web/inventory}/actions/remove-from-cart.effect.block.ts +10 -4
- package/templates/quickstart/src/blocks/{nav-item-detail.block.ts → saucedemo-web/inventory/nav-item-detail.block.ts} +10 -4
- package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/NAV.md +25 -0
- package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/nav-back-to-inventory.block.ts +18 -0
- package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/nav-back-to-products.block.ts +18 -0
- package/templates/quickstart/src/blocks/{nav-continue-shopping.block.ts → saucedemo-web/inventory-item/nav-continue-shopping.block.ts} +8 -2
- package/templates/quickstart/src/blocks/{nav-login.block.ts → saucedemo-web/nav-login.block.ts} +8 -3
- package/templates/quickstart/src/flows/cart-continue.flow.ts +2 -2
- package/templates/quickstart/src/flows/cart-mem.flow.ts +1 -1
- package/templates/quickstart/src/flows/catalog-logout.flow.ts +3 -3
- package/templates/quickstart/src/flows/checkout-then-browse-again.flow.ts +8 -8
- package/templates/quickstart/src/flows/checkout.flow.ts +7 -7
- package/templates/quickstart/src/flows/login.flow.ts +2 -2
- package/templates/quickstart/src/flows/shop.flow.ts +5 -5
- package/templates/quickstart/src/flows/smoke.flow.ts +3 -3
- package/templates/quickstart/src/flows/viewer-blocked.flow.ts +2 -2
- package/examples/saucedemo/src/blocks/actions/submit-login-for-flow.ts +0 -10
- package/examples/saucedemo/src/blocks/nav-back-to-inventory.block.ts +0 -15
- package/examples/saucedemo/src/blocks/nav-back-to-products.block.ts +0 -14
- package/templates/quickstart/src/blocks/actions/submit-login-for-flow.ts +0 -10
- package/templates/quickstart/src/blocks/nav-back-to-inventory.block.ts +0 -15
- package/templates/quickstart/src/blocks/nav-back-to-products.block.ts +0 -14
|
@@ -1,42 +1,64 @@
|
|
|
1
1
|
# saucedemo waygraph conventions
|
|
2
2
|
|
|
3
|
-
Atomic nav/action
|
|
4
|
-
|
|
5
|
-
can discover a real state graph (not a fat multi-page Block).
|
|
3
|
+
Atomic Blocks - one nav / effect / action per real URL or on-page mutation so
|
|
4
|
+
`waygraph auto` can discover a real state graph (not a fat multi-page Block).
|
|
6
5
|
|
|
7
|
-
**
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
**TypeScript salt only.** `defineNavBlock`, `defineEffectBlock`, and plain
|
|
7
|
+
`defineBlock` are helpers that force a useful shape. At runtime everything is
|
|
8
|
+
still a `Block` - there is no separate Effect or Nav engine.
|
|
9
|
+
|
|
10
|
+
**Multi-route consumers:** folder layout must mirror Next.js `app/` page routes -
|
|
11
|
+
see package docs `docs/consumer.html` (no invented `root/`, `landing/`, or
|
|
10
12
|
`shell/nav/*` families; `/` lives at the namespace root).
|
|
11
13
|
|
|
12
|
-
## Block kinds
|
|
14
|
+
## Block kinds (file convention)
|
|
13
15
|
|
|
14
|
-
| Kind | File | `page.goto`? |
|
|
15
|
-
|
|
16
|
-
| Nav | `nav-*.block.ts`
|
|
17
|
-
|
|
|
16
|
+
| Kind | File | Helper | `page.goto`? |
|
|
17
|
+
|------|------|--------|--------------|
|
|
18
|
+
| Nav | `nav-*.block.ts` | `defineNavBlock` / `defineMemNavBlock` | Yes (`url` XOR `click`) |
|
|
19
|
+
| Effect | `*.effect.block.ts` | `defineEffectBlock` | No - mutates a live instance (add/remove/toggle) via mem + `instanceOptions` |
|
|
20
|
+
| Action | `*.action.block.ts` | `defineBlock` | No - forms, submit, logout, etc. |
|
|
18
21
|
|
|
19
22
|
Only an explicit `page.goto()` (or NavBlock `click`) counts as navigation - an
|
|
20
|
-
action that fills a form
|
|
21
|
-
changes URL as a side effect of `#continue`.
|
|
23
|
+
action/effect that fills a form or clicks a button stays non-nav even when the
|
|
24
|
+
app changes URL as a side effect of `#continue`.
|
|
22
25
|
|
|
23
26
|
## Layout
|
|
24
27
|
|
|
25
28
|
```text
|
|
26
29
|
src/blocks/
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
30
|
+
SITE-MAP.md
|
|
31
|
+
saucedemo-web/ # THIS FOLDER IS URL "/"
|
|
32
|
+
NAV.md
|
|
33
|
+
nav-login.block.ts
|
|
34
|
+
actions/
|
|
35
|
+
submit-login.action.block.ts
|
|
36
|
+
submit-login-for-flow.ts
|
|
37
|
+
submit-logout.action.block.ts
|
|
38
|
+
inventory/ # /inventory.html
|
|
39
|
+
NAV.md
|
|
40
|
+
nav-item-detail.block.ts
|
|
41
|
+
actions/
|
|
42
|
+
inventory-items.ts
|
|
43
|
+
add-to-cart.effect.block.ts
|
|
44
|
+
remove-from-cart.effect.block.ts
|
|
45
|
+
inventory-item/ # /inventory-item.html
|
|
46
|
+
NAV.md
|
|
47
|
+
nav-continue-shopping.block.ts
|
|
48
|
+
nav-back-to-products.block.ts
|
|
49
|
+
nav-back-to-inventory.block.ts
|
|
50
|
+
cart/ # /cart.html
|
|
51
|
+
NAV.md
|
|
52
|
+
nav-cart.block.ts
|
|
53
|
+
nav-checkout-info.block.ts
|
|
54
|
+
checkout-step-one/ # /checkout-step-one.html
|
|
55
|
+
NAV.md
|
|
56
|
+
actions/
|
|
57
|
+
submit-checkout-info.action.block.ts
|
|
58
|
+
checkout-step-two/ # /checkout-step-two.html
|
|
59
|
+
NAV.md
|
|
60
|
+
actions/
|
|
61
|
+
finish-order.action.block.ts
|
|
40
62
|
src/states/
|
|
41
63
|
src/flows/
|
|
42
64
|
```
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# SITE-MAP - Sauce Demo blocks
|
|
2
|
+
|
|
3
|
+
Namespace `saucedemo-web/` is URL `/` for [saucedemo.com](https://www.saucedemo.com).
|
|
4
|
+
Route folders mirror real Swag Labs paths (consumer convention).
|
|
5
|
+
|
|
6
|
+
```text
|
|
7
|
+
src/blocks/
|
|
8
|
+
SITE-MAP.md
|
|
9
|
+
saucedemo-web/ # URL /
|
|
10
|
+
NAV.md
|
|
11
|
+
nav-login.block.ts # Nav defineNavBlock url:/
|
|
12
|
+
actions/
|
|
13
|
+
submit-login.action.block.ts # Action defineBlock
|
|
14
|
+
submit-login-for-flow.ts # helper (not a discoverable *.block.ts alone)
|
|
15
|
+
submit-logout.action.block.ts # Action
|
|
16
|
+
inventory/ # URL /inventory.html
|
|
17
|
+
NAV.md
|
|
18
|
+
nav-item-detail.block.ts # Nav defineMemNavBlock (instance row)
|
|
19
|
+
actions/
|
|
20
|
+
inventory-items.ts # DOM helpers for Effects (not a Block)
|
|
21
|
+
add-to-cart.effect.block.ts # Effect defineEffectBlock
|
|
22
|
+
remove-from-cart.effect.block.ts
|
|
23
|
+
inventory-item/ # URL /inventory-item.html
|
|
24
|
+
NAV.md
|
|
25
|
+
nav-continue-shopping.block.ts
|
|
26
|
+
nav-back-to-products.block.ts
|
|
27
|
+
nav-back-to-inventory.block.ts
|
|
28
|
+
cart/ # URL /cart.html
|
|
29
|
+
NAV.md
|
|
30
|
+
nav-cart.block.ts # Nav click header cart
|
|
31
|
+
nav-checkout-info.block.ts
|
|
32
|
+
checkout-step-one/ # URL /checkout-step-one.html
|
|
33
|
+
NAV.md
|
|
34
|
+
actions/
|
|
35
|
+
submit-checkout-info.action.block.ts
|
|
36
|
+
checkout-step-two/ # URL /checkout-step-two.html
|
|
37
|
+
NAV.md
|
|
38
|
+
actions/
|
|
39
|
+
finish-order.action.block.ts
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Checkpoints and mem keys live under `src/states/`. Flows under `src/flows/`
|
|
43
|
+
compose Blocks into episodes for `waygraph demo` / Playwright.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# saucedemo-web/ - URL `/`
|
|
2
|
+
|
|
3
|
+
Login page for Swag Labs. This folder is the namespace root (`/` in the browser).
|
|
4
|
+
|
|
5
|
+
## URL
|
|
6
|
+
|
|
7
|
+
- `/` (login form)
|
|
8
|
+
|
|
9
|
+
## Nav blocks
|
|
10
|
+
|
|
11
|
+
| File | Helper | Notes |
|
|
12
|
+
|------|--------|-------|
|
|
13
|
+
| `nav-login.block.ts` | `defineNavBlock` | `url: "/"` - only goto onto login |
|
|
14
|
+
|
|
15
|
+
## Effects / actions
|
|
16
|
+
|
|
17
|
+
| File | Kind | Notes |
|
|
18
|
+
|------|------|-------|
|
|
19
|
+
| `actions/submit-login.action.block.ts` | Action | Form submit; branches LoggedIn vs LoginPage |
|
|
20
|
+
| `actions/submit-login-for-flow.ts` | helper | Typed alias for linear Flows |
|
|
21
|
+
| `actions/submit-logout.action.block.ts` | Action | Burger menu logout -> LoginPage |
|
|
22
|
+
|
|
23
|
+
## Related mem keys / checkpoints
|
|
24
|
+
|
|
25
|
+
- Mem: `saucedemo.credentials` (`LoginCreds`)
|
|
26
|
+
- Checkpoints: `LoginPage`, `LoggedIn` (success path of submit-login)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DefinedBlock } from "waygraph";
|
|
2
|
+
import type { LoginPage, LoggedIn } from "../../../states/checkout.states.js";
|
|
3
|
+
import { SubmitLoginActionBlock } from "./submit-login.action.block.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Kind: helper (not a discoverable Block file)
|
|
7
|
+
* Helper: typed alias over SubmitLoginActionBlock
|
|
8
|
+
* Route: saucedemo-web/actions/ (page URL /)
|
|
9
|
+
*
|
|
10
|
+
* DefinedBlock cast so linear Flows can chain .withVerify on Out=LoggedIn;
|
|
11
|
+
* runtime still branches on bad credentials via SubmitLoginActionBlock.
|
|
12
|
+
*/
|
|
13
|
+
export const SubmitLoginForFlow = SubmitLoginActionBlock as unknown as DefinedBlock<LoginPage, LoggedIn>;
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { defineBlock, checkpoint, Trait } from "waygraph";
|
|
2
|
-
import type { LoginPage, LoginSubmitOutcome } from "
|
|
3
|
-
import { LoginCreds } from "
|
|
2
|
+
import type { LoginPage, LoginSubmitOutcome } from "../../../states/checkout.states.js";
|
|
3
|
+
import { LoginCreds } from "../../../states/checkout.mem-keys.js";
|
|
4
4
|
|
|
5
5
|
type LoginObserve = "success" | "failure";
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Kind: Action
|
|
9
|
+
* Helper: defineBlock
|
|
10
|
+
* Route: saucedemo-web/actions/ (page URL /)
|
|
11
|
+
*
|
|
12
|
+
* Fills credentials and submits - never page.goto (nav-login owns that).
|
|
13
|
+
* Branches: good creds -> LoggedIn; bad/locked -> LoginPage with error banner.
|
|
14
|
+
*/
|
|
13
15
|
export const SubmitLoginActionBlock = defineBlock<LoginPage, LoginSubmitOutcome>({
|
|
14
16
|
name: "submit-login",
|
|
15
17
|
description: "Logs a user in when credentials are valid; stays on LoginPage when auth fails.",
|
|
@@ -19,11 +21,13 @@ export const SubmitLoginActionBlock = defineBlock<LoginPage, LoginSubmitOutcome>
|
|
|
19
21
|
const { username, password } = mem.get(LoginCreds.key);
|
|
20
22
|
await page.locator("#user-name").fill(username);
|
|
21
23
|
await page.locator("#password").fill(password);
|
|
22
|
-
|
|
24
|
+
// noWaitAfter: observe owns the inventory URL wait. Default click
|
|
25
|
+
// navigation-wait can hang under waygraph auto's demo cursor patch.
|
|
26
|
+
await page.locator("#login-button").click({ noWaitAfter: true });
|
|
23
27
|
},
|
|
24
28
|
async observe(page): Promise<LoginObserve> {
|
|
25
29
|
try {
|
|
26
|
-
await page.waitForURL(/\/inventory\.html/, { timeout:
|
|
30
|
+
await page.waitForURL(/\/inventory\.html/, { timeout: 8_000 });
|
|
27
31
|
return "success";
|
|
28
32
|
} catch {
|
|
29
33
|
return "failure";
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { defineBlock, checkpoint, Trait } from "waygraph";
|
|
2
|
-
import type { LoggedIn, LoginPage } from "
|
|
2
|
+
import type { LoggedIn, LoginPage } from "../../../states/checkout.states.js";
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Kind: Action
|
|
6
|
+
* Helper: defineBlock
|
|
7
|
+
* Route: saucedemo-web/actions/ (page URL / after logout)
|
|
8
|
+
*
|
|
9
|
+
* Burger menu Logout - real cycle back to LoginPage (same Checkpoint nav-login lands on).
|
|
10
|
+
*/
|
|
6
11
|
export const SubmitLogoutBlock = defineBlock<LoggedIn, LoginPage>({
|
|
7
12
|
name: "submit-logout",
|
|
8
13
|
description: "Opens the burger menu and logs out.",
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# cart/ - URL `/cart.html`
|
|
2
|
+
|
|
3
|
+
Shopping cart page and checkout entry.
|
|
4
|
+
|
|
5
|
+
## URL
|
|
6
|
+
|
|
7
|
+
- `/cart.html`
|
|
8
|
+
|
|
9
|
+
## Nav blocks
|
|
10
|
+
|
|
11
|
+
| File | Helper | Notes |
|
|
12
|
+
|------|--------|-------|
|
|
13
|
+
| `nav-cart.block.ts` | `defineNavBlock` | Header cart link (`click`, not url) |
|
|
14
|
+
| `nav-checkout-info.block.ts` | `defineNavBlock` | "Checkout" button -> step one |
|
|
15
|
+
|
|
16
|
+
## Effects / actions
|
|
17
|
+
|
|
18
|
+
(none on this route; cart mutations live under `inventory/actions/`)
|
|
19
|
+
|
|
20
|
+
## Related mem keys / checkpoints
|
|
21
|
+
|
|
22
|
+
- Checkpoints: `CartPage`, `CheckoutInfoPage`, `ItemInCart` / `LoggedIn` (cart contents)
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { defineNavBlock, Trait } from "waygraph";
|
|
2
|
-
import type { CartPage } from "
|
|
2
|
+
import type { CartPage } from "../../../states/checkout.states.js";
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Kind: Nav
|
|
6
|
+
* Helper: defineNavBlock
|
|
7
|
+
* Route: saucedemo-web/cart/ (= /cart.html)
|
|
8
|
+
*
|
|
9
|
+
* click, not url - header cart link from inventory-adjacent pages.
|
|
10
|
+
*/
|
|
6
11
|
export const NavCartBlock = defineNavBlock<CartPage>({
|
|
7
12
|
name: "nav-cart",
|
|
8
13
|
description: "Clicks the cart link in the header.",
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { defineNavBlock, Trait } from "waygraph";
|
|
2
|
-
import type { CheckoutInfoPage } from "
|
|
2
|
+
import type { CheckoutInfoPage } from "../../../states/checkout.states.js";
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Kind: Nav
|
|
6
|
+
* Helper: defineNavBlock
|
|
7
|
+
* Route: saucedemo-web/cart/ (click leaves /cart.html -> /checkout-step-one.html)
|
|
8
|
+
*
|
|
9
|
+
* Cart page "Checkout" button - owns the nav into step one.
|
|
10
|
+
*/
|
|
4
11
|
export const NavCheckoutInfoBlock = defineNavBlock<CheckoutInfoPage>({
|
|
5
12
|
name: "nav-checkout-info",
|
|
6
13
|
description: "Clicks 'Checkout' on the cart page.",
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# checkout-step-one/ - URL `/checkout-step-one.html`
|
|
2
|
+
|
|
3
|
+
Shipping info form before order overview.
|
|
4
|
+
|
|
5
|
+
## URL
|
|
6
|
+
|
|
7
|
+
- `/checkout-step-one.html`
|
|
8
|
+
|
|
9
|
+
## Nav blocks
|
|
10
|
+
|
|
11
|
+
(none - arrival is via `cart/nav-checkout-info.block.ts`)
|
|
12
|
+
|
|
13
|
+
## Effects / actions
|
|
14
|
+
|
|
15
|
+
| File | Kind | Notes |
|
|
16
|
+
|------|------|-------|
|
|
17
|
+
| `actions/submit-checkout-info.action.block.ts` | Action | Fill form + Continue -> overview |
|
|
18
|
+
|
|
19
|
+
## Related mem keys / checkpoints
|
|
20
|
+
|
|
21
|
+
- Checkpoints: `CheckoutInfoPage`, `CheckoutOverviewPage`
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { defineBlock, checkpoint, Trait } from "waygraph";
|
|
2
|
-
import type { CheckoutInfoPage, CheckoutOverviewPage } from "
|
|
2
|
+
import type { CheckoutInfoPage, CheckoutOverviewPage } from "../../../../states/checkout.states.js";
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Kind: Action
|
|
6
|
+
* Helper: defineBlock
|
|
7
|
+
* Route: saucedemo-web/checkout-step-one/actions/ (= /checkout-step-one.html)
|
|
8
|
+
*
|
|
9
|
+
* Fills shipping form and continues - never navigates itself
|
|
10
|
+
* (nav-checkout-info already got here).
|
|
11
|
+
*/
|
|
9
12
|
export const SubmitCheckoutInfoBlock = defineBlock<CheckoutInfoPage, CheckoutOverviewPage>({
|
|
10
13
|
name: "submit-checkout-info",
|
|
11
14
|
description: "Fills in the shipping info form and continues to the order overview.",
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# checkout-step-two/ - URL `/checkout-step-two.html`
|
|
2
|
+
|
|
3
|
+
Order overview / finish page.
|
|
4
|
+
|
|
5
|
+
## URL
|
|
6
|
+
|
|
7
|
+
- `/checkout-step-two.html`
|
|
8
|
+
|
|
9
|
+
## Nav blocks
|
|
10
|
+
|
|
11
|
+
(none - arrival is via submit-checkout-info Action)
|
|
12
|
+
|
|
13
|
+
## Effects / actions
|
|
14
|
+
|
|
15
|
+
| File | Kind | Notes |
|
|
16
|
+
|------|------|-------|
|
|
17
|
+
| `actions/finish-order.action.block.ts` | Action | Finish -> thank-you / OrderComplete |
|
|
18
|
+
|
|
19
|
+
## Related mem keys / checkpoints
|
|
20
|
+
|
|
21
|
+
- Checkpoints: `CheckoutOverviewPage`, `OrderComplete`
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { defineBlock, checkpoint, Trait, narrate } from "waygraph";
|
|
2
|
-
import type { CheckoutOverviewPage, OrderComplete } from "
|
|
2
|
+
import type { CheckoutOverviewPage, OrderComplete } from "../../../../states/checkout.states.js";
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Kind: Action
|
|
6
|
+
* Helper: defineBlock
|
|
7
|
+
* Route: saucedemo-web/checkout-step-two/actions/ (= /checkout-step-two.html)
|
|
8
|
+
*
|
|
9
|
+
* Places the order on the overview page - form/finish click, not a NavBlock.
|
|
10
|
+
*/
|
|
4
11
|
export const FinishOrderBlock = defineBlock<CheckoutOverviewPage, OrderComplete>({
|
|
5
12
|
name: "finish-order",
|
|
6
13
|
description: "Places the order and confirms the 'Thank you for your order!' completion page.",
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# inventory/ - URL `/inventory.html`
|
|
2
|
+
|
|
3
|
+
Product catalog after a successful login.
|
|
4
|
+
|
|
5
|
+
## URL
|
|
6
|
+
|
|
7
|
+
- `/inventory.html`
|
|
8
|
+
|
|
9
|
+
## Nav blocks
|
|
10
|
+
|
|
11
|
+
| File | Helper | Notes |
|
|
12
|
+
|------|--------|-------|
|
|
13
|
+
| `nav-item-detail.block.ts` | `defineMemNavBlock` | Opens mem-picked product detail; instance rows per card |
|
|
14
|
+
|
|
15
|
+
## Effects / actions
|
|
16
|
+
|
|
17
|
+
| File | Kind | Notes |
|
|
18
|
+
|------|------|-------|
|
|
19
|
+
| `actions/add-to-cart.effect.block.ts` | Effect | Add mem-picked item; instance menu |
|
|
20
|
+
| `actions/remove-from-cart.effect.block.ts` | Effect | Remove mem-picked item; may empty cart |
|
|
21
|
+
| `actions/inventory-items.ts` | helper | DOM collectors (not a Block) |
|
|
22
|
+
|
|
23
|
+
## Related mem keys / checkpoints
|
|
24
|
+
|
|
25
|
+
- Mem: `saucedemo.selectedItem` (`SelectedItem`)
|
|
26
|
+
- Checkpoints: `LoggedIn`, `ItemInCart`, `ItemDetailPage` (via MemNav)
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import { defineEffectBlock, checkpoint, type Checkpoint, type WaygraphInstanceOption } from "waygraph";
|
|
2
|
-
import type { ItemInCart } from "
|
|
3
|
-
import { SelectedItem } from "
|
|
2
|
+
import type { ItemInCart } from "../../../../states/checkout.states.js";
|
|
3
|
+
import { SelectedItem } from "../../../../states/checkout.mem-keys.js";
|
|
4
4
|
import { collectAddableItems } from "./inventory-items.js";
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Kind: Effect
|
|
8
|
+
* Helper: defineEffectBlock
|
|
9
|
+
* Route: saucedemo-web/inventory/actions/ (= /inventory.html)
|
|
10
|
+
*
|
|
11
|
+
* Mutates cart for the mem-picked product. waygraph auto lists one
|
|
12
|
+
* "Add ..." row per live Add button via instanceOptions.
|
|
13
|
+
*/
|
|
8
14
|
export const AddToCartBlock = defineEffectBlock<Checkpoint<string>, ItemInCart>({
|
|
9
15
|
name: "add-to-cart",
|
|
10
16
|
description: "Adds the item named by mem (saucedemo.selectedItem) to the cart.",
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import type { Page, Locator } from "@playwright/test";
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Kind: helper (not a Block)
|
|
5
|
+
* Route: saucedemo-web/inventory/actions/ (= /inventory.html)
|
|
6
|
+
*
|
|
7
|
+
* DOM collectors for Effect / MemNav instanceOptions. Discovery ignores this
|
|
8
|
+
* file (no *.block.ts suffix). Keep selectors here so add/remove/detail stay thin.
|
|
9
|
+
*/
|
|
10
|
+
|
|
3
11
|
/** Product slug + display name (saucedemo inventory / detail / cart). */
|
|
4
12
|
export type InventoryItem = { id: string; name: string };
|
|
5
13
|
|
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import { defineEffectBlock, checkpoint, type Checkpoint, type WaygraphInstanceOption } from "waygraph";
|
|
2
|
-
import type { RemoveFromCartOutcome } from "
|
|
3
|
-
import { SelectedItem } from "
|
|
2
|
+
import type { RemoveFromCartOutcome } from "../../../../states/checkout.states.js";
|
|
3
|
+
import { SelectedItem } from "../../../../states/checkout.mem-keys.js";
|
|
4
4
|
import { collectRemovableItems } from "./inventory-items.js";
|
|
5
5
|
|
|
6
6
|
type RemoveObserve = "still-has-items" | "cart-empty";
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Kind: Effect
|
|
10
|
+
* Helper: defineEffectBlock
|
|
11
|
+
* Route: saucedemo-web/inventory/actions/ (= /inventory.html)
|
|
12
|
+
*
|
|
13
|
+
* Removes the mem-picked product. After Add, waygraph auto shows matching
|
|
14
|
+
* "Remove ..." rows from live Remove buttons.
|
|
15
|
+
*/
|
|
10
16
|
export const RemoveFromCartBlock = defineEffectBlock<Checkpoint<string>, RemoveFromCartOutcome>({
|
|
11
17
|
name: "remove-from-cart",
|
|
12
18
|
description: "Removes the item named by mem (saucedemo.selectedItem) from the cart.",
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import { defineMemNavBlock, Trait, type WaygraphInstanceOption } from "waygraph";
|
|
2
|
-
import type { ItemDetailPage } from "
|
|
3
|
-
import { SelectedItem } from "
|
|
2
|
+
import type { ItemDetailPage } from "../../../states/checkout.states.js";
|
|
3
|
+
import { SelectedItem } from "../../../states/checkout.mem-keys.js";
|
|
4
4
|
import {
|
|
5
5
|
collectInventoryItems,
|
|
6
6
|
inventoryItemTitleSelector,
|
|
7
7
|
} from "./actions/inventory-items.js";
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Kind: Nav
|
|
11
|
+
* Helper: defineMemNavBlock
|
|
12
|
+
* Route: saucedemo-web/inventory/ (= /inventory.html)
|
|
13
|
+
*
|
|
14
|
+
* Opens the mem-picked product detail page. waygraph auto lists one
|
|
15
|
+
* "Open ... details" row per inventory card via instanceOptions.
|
|
16
|
+
*/
|
|
11
17
|
export const NavItemDetailBlock = defineMemNavBlock<ItemDetailPage>({
|
|
12
18
|
name: "nav-item-detail",
|
|
13
19
|
description: "Opens the product named by mem (saucedemo.selectedItem) on its detail page.",
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# inventory-item/ - URL `/inventory-item.html`
|
|
2
|
+
|
|
3
|
+
Single product detail page, plus nav edges that return to catalog
|
|
4
|
+
(continue shopping / back home / back to products).
|
|
5
|
+
|
|
6
|
+
## URL
|
|
7
|
+
|
|
8
|
+
- `/inventory-item.html` (detail)
|
|
9
|
+
- Related landings: `/inventory.html` (via back / continue-shopping clicks)
|
|
10
|
+
|
|
11
|
+
## Nav blocks
|
|
12
|
+
|
|
13
|
+
| File | Helper | Notes |
|
|
14
|
+
|------|--------|-------|
|
|
15
|
+
| `nav-continue-shopping.block.ts` | `defineNavBlock` | Cart "Continue Shopping" -> inventory |
|
|
16
|
+
| `nav-back-to-products.block.ts` | `defineNavBlock` | Order-complete "Back Home" -> inventory |
|
|
17
|
+
| `nav-back-to-inventory.block.ts` | `defineNavBlock` | Detail "Back to products" -> inventory |
|
|
18
|
+
|
|
19
|
+
## Effects / actions
|
|
20
|
+
|
|
21
|
+
(none on this route)
|
|
22
|
+
|
|
23
|
+
## Related mem keys / checkpoints
|
|
24
|
+
|
|
25
|
+
- Checkpoints: `ItemDetailPage`, `LoggedIn` (after back / continue), `OrderComplete` (from for back-to-products)
|
package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/nav-back-to-inventory.block.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { defineNavBlock, Trait } from "waygraph";
|
|
2
|
+
import type { LoggedIn } from "../../../states/checkout.states.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Kind: Nav
|
|
6
|
+
* Helper: defineNavBlock
|
|
7
|
+
* Route: saucedemo-web/inventory-item/ (= /inventory-item.html From)
|
|
8
|
+
*
|
|
9
|
+
* click, not url - detail page "Back to products". Separate Block from
|
|
10
|
+
* nav-back-to-products (different From Checkpoint; atomic convention).
|
|
11
|
+
*/
|
|
12
|
+
export const NavBackToInventoryBlock = defineNavBlock<LoggedIn>({
|
|
13
|
+
name: "nav-back-to-inventory",
|
|
14
|
+
description: "Clicks 'Back to products' on the item detail page.",
|
|
15
|
+
checkpoint: "LoggedIn",
|
|
16
|
+
click: "#back-to-products",
|
|
17
|
+
verify: [Trait.url({ pathname: "/inventory.html" })],
|
|
18
|
+
});
|
package/templates/quickstart/src/blocks/saucedemo-web/inventory-item/nav-back-to-products.block.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { defineNavBlock, Trait } from "waygraph";
|
|
2
|
+
import type { LoggedIn } from "../../../states/checkout.states.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Kind: Nav
|
|
6
|
+
* Helper: defineNavBlock
|
|
7
|
+
* Route: saucedemo-web/inventory-item/ (lands on /inventory.html)
|
|
8
|
+
*
|
|
9
|
+
* click, not url - order-complete "Back Home" proves the button path
|
|
10
|
+
* (a url NavBlock would teleport without exercising the control).
|
|
11
|
+
*/
|
|
12
|
+
export const NavBackToProductsBlock = defineNavBlock<LoggedIn>({
|
|
13
|
+
name: "nav-back-to-products",
|
|
14
|
+
description: "Clicks 'Back Home' on the order confirmation page.",
|
|
15
|
+
checkpoint: "LoggedIn",
|
|
16
|
+
click: "#back-to-products",
|
|
17
|
+
verify: [Trait.url({ pathname: "/inventory.html" })],
|
|
18
|
+
});
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import { defineNavBlock, Trait } from "waygraph";
|
|
2
|
-
import type { LoggedIn } from "
|
|
2
|
+
import type { LoggedIn } from "../../../states/checkout.states.js";
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Kind: Nav
|
|
6
|
+
* Helper: defineNavBlock
|
|
7
|
+
* Route: saucedemo-web/inventory-item/ (lands on /inventory.html)
|
|
8
|
+
*
|
|
9
|
+
* click, not url - cart page "Continue Shopping" proves the app's own path.
|
|
10
|
+
*/
|
|
5
11
|
export const NavContinueShoppingBlock = defineNavBlock<LoggedIn>({
|
|
6
12
|
name: "nav-continue-shopping",
|
|
7
13
|
description: "Clicks 'Continue Shopping' on the cart page.",
|
package/templates/quickstart/src/blocks/{nav-login.block.ts → saucedemo-web/nav-login.block.ts}
RENAMED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { defineNavBlock, Trait } from "waygraph";
|
|
2
|
-
import type { LoginPage } from "
|
|
2
|
+
import type { LoginPage } from "../../states/checkout.states.js";
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Kind: Nav
|
|
6
|
+
* Helper: defineNavBlock
|
|
7
|
+
* Route: saucedemo-web/ (= /)
|
|
8
|
+
*
|
|
9
|
+
* page.goto to the login form lives here only. submit-login Action never navigates.
|
|
10
|
+
*/
|
|
6
11
|
export const NavLoginBlock = defineNavBlock<LoginPage>({
|
|
7
12
|
name: "nav-login",
|
|
8
13
|
description: "Goes to the Swag Labs login page.",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Engine, start, end, withTitle } from "waygraph";
|
|
2
|
-
import { NavCartBlock } from "../blocks/nav-cart.block.js";
|
|
3
|
-
import { NavContinueShoppingBlock } from "../blocks/nav-continue-shopping.block.js";
|
|
2
|
+
import { NavCartBlock } from "../blocks/saucedemo-web/cart/nav-cart.block.js";
|
|
3
|
+
import { NavContinueShoppingBlock } from "../blocks/saucedemo-web/inventory-item/nav-continue-shopping.block.js";
|
|
4
4
|
|
|
5
5
|
const engine = new Engine();
|
|
6
6
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Engine, start, end } from "waygraph";
|
|
2
|
-
import { RemoveFromCartBlock } from "../blocks/actions/remove-from-cart.effect.block.js";
|
|
2
|
+
import { RemoveFromCartBlock } from "../blocks/saucedemo-web/inventory/actions/remove-from-cart.effect.block.js";
|
|
3
3
|
|
|
4
4
|
const engine = new Engine();
|
|
5
5
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Engine, start, end, withTitle } from "waygraph";
|
|
2
|
-
import { NavItemDetailBlock } from "../blocks/nav-item-detail.block.js";
|
|
3
|
-
import { NavBackToInventoryBlock } from "../blocks/nav-back-to-inventory.block.js";
|
|
4
|
-
import { SubmitLogoutBlock } from "../blocks/actions/submit-logout.action.block.js";
|
|
2
|
+
import { NavItemDetailBlock } from "../blocks/saucedemo-web/inventory/nav-item-detail.block.js";
|
|
3
|
+
import { NavBackToInventoryBlock } from "../blocks/saucedemo-web/inventory-item/nav-back-to-inventory.block.js";
|
|
4
|
+
import { SubmitLogoutBlock } from "../blocks/saucedemo-web/actions/submit-logout.action.block.js";
|
|
5
5
|
|
|
6
6
|
const engine = new Engine();
|
|
7
7
|
|