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
package/examples/saucedemo/src/blocks/{actions → saucedemo-web/actions}/submit-login.action.block.ts
RENAMED
|
@@ -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/examples/saucedemo/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/examples/saucedemo/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/examples/saucedemo/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
|
|
|
@@ -8,14 +8,14 @@ import type {
|
|
|
8
8
|
CheckoutOverviewPage,
|
|
9
9
|
OrderComplete,
|
|
10
10
|
} from "../states/checkout.states.js";
|
|
11
|
-
import { NavLoginBlock } from "../blocks/nav-login.block.js";
|
|
12
|
-
import { SubmitLoginForFlow } from "../blocks/actions/submit-login-for-flow.js";
|
|
13
|
-
import { AddToCartBlock } from "../blocks/actions/add-to-cart.effect.block.js";
|
|
14
|
-
import { NavCartBlock } from "../blocks/nav-cart.block.js";
|
|
15
|
-
import { NavCheckoutInfoBlock } from "../blocks/nav-checkout-info.block.js";
|
|
16
|
-
import { SubmitCheckoutInfoBlock } from "../blocks/actions/submit-checkout-info.action.block.js";
|
|
17
|
-
import { FinishOrderBlock } from "../blocks/actions/finish-order.action.block.js";
|
|
18
|
-
import { NavBackToProductsBlock } from "../blocks/nav-back-to-products.block.js";
|
|
11
|
+
import { NavLoginBlock } from "../blocks/saucedemo-web/nav-login.block.js";
|
|
12
|
+
import { SubmitLoginForFlow } from "../blocks/saucedemo-web/actions/submit-login-for-flow.js";
|
|
13
|
+
import { AddToCartBlock } from "../blocks/saucedemo-web/inventory/actions/add-to-cart.effect.block.js";
|
|
14
|
+
import { NavCartBlock } from "../blocks/saucedemo-web/cart/nav-cart.block.js";
|
|
15
|
+
import { NavCheckoutInfoBlock } from "../blocks/saucedemo-web/cart/nav-checkout-info.block.js";
|
|
16
|
+
import { SubmitCheckoutInfoBlock } from "../blocks/saucedemo-web/checkout-step-one/actions/submit-checkout-info.action.block.js";
|
|
17
|
+
import { FinishOrderBlock } from "../blocks/saucedemo-web/checkout-step-two/actions/finish-order.action.block.js";
|
|
18
|
+
import { NavBackToProductsBlock } from "../blocks/saucedemo-web/inventory-item/nav-back-to-products.block.js";
|
|
19
19
|
|
|
20
20
|
const engine = new Engine({ headless: false, slowMo: 250 });
|
|
21
21
|
|
|
@@ -8,13 +8,13 @@ import type {
|
|
|
8
8
|
CheckoutOverviewPage,
|
|
9
9
|
OrderComplete,
|
|
10
10
|
} from "../states/checkout.states.js";
|
|
11
|
-
import { NavLoginBlock } from "../blocks/nav-login.block.js";
|
|
12
|
-
import { SubmitLoginForFlow } from "../blocks/actions/submit-login-for-flow.js";
|
|
13
|
-
import { AddToCartBlock } from "../blocks/actions/add-to-cart.effect.block.js";
|
|
14
|
-
import { NavCartBlock } from "../blocks/nav-cart.block.js";
|
|
15
|
-
import { NavCheckoutInfoBlock } from "../blocks/nav-checkout-info.block.js";
|
|
16
|
-
import { SubmitCheckoutInfoBlock } from "../blocks/actions/submit-checkout-info.action.block.js";
|
|
17
|
-
import { FinishOrderBlock } from "../blocks/actions/finish-order.action.block.js";
|
|
11
|
+
import { NavLoginBlock } from "../blocks/saucedemo-web/nav-login.block.js";
|
|
12
|
+
import { SubmitLoginForFlow } from "../blocks/saucedemo-web/actions/submit-login-for-flow.js";
|
|
13
|
+
import { AddToCartBlock } from "../blocks/saucedemo-web/inventory/actions/add-to-cart.effect.block.js";
|
|
14
|
+
import { NavCartBlock } from "../blocks/saucedemo-web/cart/nav-cart.block.js";
|
|
15
|
+
import { NavCheckoutInfoBlock } from "../blocks/saucedemo-web/cart/nav-checkout-info.block.js";
|
|
16
|
+
import { SubmitCheckoutInfoBlock } from "../blocks/saucedemo-web/checkout-step-one/actions/submit-checkout-info.action.block.js";
|
|
17
|
+
import { FinishOrderBlock } from "../blocks/saucedemo-web/checkout-step-two/actions/finish-order.action.block.js";
|
|
18
18
|
|
|
19
19
|
const engine = new Engine({ headless: false, slowMo: 250 });
|
|
20
20
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Engine, start, end, withTitle } from "waygraph";
|
|
2
|
-
import { NavLoginBlock } from "../blocks/nav-login.block.js";
|
|
3
|
-
import { SubmitLoginForFlow } from "../blocks/actions/submit-login-for-flow.js";
|
|
2
|
+
import { NavLoginBlock } from "../blocks/saucedemo-web/nav-login.block.js";
|
|
3
|
+
import { SubmitLoginForFlow } from "../blocks/saucedemo-web/actions/submit-login-for-flow.js";
|
|
4
4
|
|
|
5
5
|
const engine = new Engine();
|
|
6
6
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Engine, start, end, withTitle } from "waygraph";
|
|
2
|
-
import { AddToCartBlock } from "../blocks/actions/add-to-cart.effect.block.js";
|
|
3
|
-
import { NavCartBlock } from "../blocks/nav-cart.block.js";
|
|
4
|
-
import { NavCheckoutInfoBlock } from "../blocks/nav-checkout-info.block.js";
|
|
5
|
-
import { SubmitCheckoutInfoBlock } from "../blocks/actions/submit-checkout-info.action.block.js";
|
|
6
|
-
import { FinishOrderBlock } from "../blocks/actions/finish-order.action.block.js";
|
|
2
|
+
import { AddToCartBlock } from "../blocks/saucedemo-web/inventory/actions/add-to-cart.effect.block.js";
|
|
3
|
+
import { NavCartBlock } from "../blocks/saucedemo-web/cart/nav-cart.block.js";
|
|
4
|
+
import { NavCheckoutInfoBlock } from "../blocks/saucedemo-web/cart/nav-checkout-info.block.js";
|
|
5
|
+
import { SubmitCheckoutInfoBlock } from "../blocks/saucedemo-web/checkout-step-one/actions/submit-checkout-info.action.block.js";
|
|
6
|
+
import { FinishOrderBlock } from "../blocks/saucedemo-web/checkout-step-two/actions/finish-order.action.block.js";
|
|
7
7
|
|
|
8
8
|
const engine = new Engine();
|
|
9
9
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Engine, start, end } from "waygraph";
|
|
2
2
|
import type { LoginPage, LoggedIn, ItemInCart } from "../states/checkout.states.js";
|
|
3
|
-
import { NavLoginBlock } from "../blocks/nav-login.block.js";
|
|
4
|
-
import { SubmitLoginForFlow } from "../blocks/actions/submit-login-for-flow.js";
|
|
5
|
-
import { AddToCartBlock } from "../blocks/actions/add-to-cart.effect.block.js";
|
|
3
|
+
import { NavLoginBlock } from "../blocks/saucedemo-web/nav-login.block.js";
|
|
4
|
+
import { SubmitLoginForFlow } from "../blocks/saucedemo-web/actions/submit-login-for-flow.js";
|
|
5
|
+
import { AddToCartBlock } from "../blocks/saucedemo-web/inventory/actions/add-to-cart.effect.block.js";
|
|
6
6
|
|
|
7
7
|
const engine = new Engine();
|
|
8
8
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Engine, start, end, withTitle, withSessionReset } from "waygraph";
|
|
2
|
-
import { NavLoginBlock } from "../blocks/nav-login.block.js";
|
|
3
|
-
import { SubmitLoginActionBlock } from "../blocks/actions/submit-login.action.block.js";
|
|
2
|
+
import { NavLoginBlock } from "../blocks/saucedemo-web/nav-login.block.js";
|
|
3
|
+
import { SubmitLoginActionBlock } from "../blocks/saucedemo-web/actions/submit-login.action.block.js";
|
|
4
4
|
|
|
5
5
|
const engine = new Engine();
|
|
6
6
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { test, expect } from "@playwright/test";
|
|
2
2
|
import { MemPage, checkpoint, Trait } from "waygraph";
|
|
3
3
|
import { checkoutFlow } from "../src/flows/checkout.flow.js";
|
|
4
|
-
import { SubmitLoginActionBlock } from "../src/blocks/actions/submit-login.action.block.js";
|
|
4
|
+
import { SubmitLoginActionBlock } from "../src/blocks/saucedemo-web/actions/submit-login.action.block.js";
|
|
5
5
|
import { LoginCreds, SelectedItem } from "../src/states/checkout.mem-keys.js";
|
|
6
6
|
|
|
7
7
|
// checkoutFlow.withBlockVerify/modBlockVerify - a spec that only imports the
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { test, expect } from "@playwright/test";
|
|
2
2
|
import { MemPage, Engine, start, end } from "waygraph";
|
|
3
|
-
import { NavLoginBlock } from "../src/blocks/nav-login.block.js";
|
|
4
|
-
import { SubmitLoginActionBlock } from "../src/blocks/actions/submit-login.action.block.js";
|
|
3
|
+
import { NavLoginBlock } from "../src/blocks/saucedemo-web/nav-login.block.js";
|
|
4
|
+
import { SubmitLoginActionBlock } from "../src/blocks/saucedemo-web/actions/submit-login.action.block.js";
|
|
5
5
|
import { LoginCreds } from "../src/states/checkout.mem-keys.js";
|
|
6
6
|
|
|
7
7
|
test("submit-login: wrong password branches to LoginPage with error banner", async () => {
|
package/package.json
CHANGED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# waygraph quickstart (Sauce Demo)
|
|
2
|
+
|
|
3
|
+
Temp-dir template for `npx waygraph try demo`. Same Blocks as
|
|
4
|
+
`examples/saucedemo` (route-folder convention under `src/blocks/saucedemo-web/`).
|
|
5
|
+
|
|
6
|
+
Convention walkthrough on Pages:
|
|
7
|
+
https://deviate-dv8.github.io/waygraph/saucedemo/
|
|
8
|
+
|
|
9
|
+
Do not edit this tree as the long-lived showcase - edit `examples/saucedemo`,
|
|
10
|
+
then re-copy Blocks here when shipping a release that bumps `try demo`.
|