waygraph 0.15.50 → 0.15.52
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/dist/analysis/graph.d.ts +1 -1
- package/dist/analysis/graph.js +10 -15
- package/dist/analysis/map-check.js +5 -2
- package/dist/analysis/practices-check.d.ts +0 -1
- package/dist/analysis/practices-check.js +17 -17
- package/dist/auto-session/session.d.ts +1 -1
- package/dist/auto-session/session.js +14 -8
- package/dist/blocks-select.d.ts +7 -4
- package/dist/blocks-select.js +0 -14
- package/dist/browser.d.ts +27 -0
- package/dist/browser.js +62 -0
- package/dist/cli/run-chain.js +5 -0
- package/dist/cli/usage.js +14 -1
- package/dist/cli.js +10 -1
- package/dist/commands/agent-dive-scaffold.d.ts +5 -0
- package/dist/commands/agent-dive-scaffold.js +7 -0
- package/dist/commands/extensions.d.ts +1 -0
- package/dist/commands/extensions.js +22 -0
- package/dist/commands/init.js +45 -2
- package/dist/commands/test.js +16 -2
- package/dist/commands/try.js +2 -1
- package/dist/commands/upgrade.d.ts +6 -0
- package/dist/commands/upgrade.js +107 -0
- package/dist/config.d.ts +47 -3
- package/dist/config.js +45 -12
- package/dist/core/block.d.ts +12 -0
- package/dist/core/block.js +36 -0
- package/dist/core/blocks/effect.d.ts +0 -3
- package/dist/core/blocks/method.d.ts +0 -6
- package/dist/core/blocks/nav.d.ts +11 -3
- package/dist/core/blocks/nav.js +8 -0
- package/dist/core/blocks/page.d.ts +0 -3
- package/dist/core/config.d.ts +5 -0
- package/dist/core/engine.d.ts +17 -16
- package/dist/core/engine.js +3 -3
- package/dist/core/flow.d.ts +17 -0
- package/dist/core/flow.js +44 -24
- package/dist/core/map-builder.d.ts +3 -3
- package/dist/core/map-builder.js +3 -3
- package/dist/env-file.d.ts +7 -7
- package/dist/env-file.js +29 -16
- package/dist/extensions.d.ts +21 -0
- package/dist/extensions.js +178 -0
- package/dist/highlights/types.d.ts +3 -2
- package/dist/index.d.ts +8 -3
- package/dist/index.js +4 -1
- package/dist/pilot-overlay/overlay-fixtures.d.ts +0 -7
- package/dist/pilot-overlay/overlay-fixtures.js +0 -45
- package/dist/playwright-config.d.ts +4 -0
- package/dist/playwright-config.js +15 -0
- package/dist/playwright.config.d.ts +2 -0
- package/dist/playwright.config.js +6 -0
- package/dist/runner/demo-log.js +1 -7
- package/dist/runner/inpage/banner.js +10 -2
- package/dist/runner/inpage/core.d.ts +1 -1
- package/dist/runner/inpage/core.js +8 -7
- package/dist/runner/main.js +27 -15
- package/dist/runner/rings.js +0 -49
- package/dist/session/auto-explore-run.js +21 -6
- package/dist/session/auto-explore.js +6 -4
- package/dist/session/step-overlay.js +3 -1
- package/dist/traverse/run.js +4 -1
- package/dist/types.d.ts +0 -3
- package/dist/ui/components/ring.js +1 -0
- package/dist/ui/overlay.css +1 -0
- package/dist/ui/shadow.d.ts +1 -3
- package/dist/ui/shadow.js +0 -4
- package/dist/ui/tokens.d.ts +0 -11
- package/dist/ui/tokens.js +0 -5
- package/dist/video-dir.d.ts +8 -0
- package/dist/video-dir.js +60 -0
- package/dist/webserver.d.ts +14 -0
- package/dist/webserver.js +95 -0
- package/examples/routed-demo/package.json +3 -3
- package/examples/routed-demo/playwright.config.ts +8 -8
- package/examples/routed-demo/scripts/fixture-server.mjs +12 -31
- package/examples/routed-demo/src/map/(app_base)/dashboard/_sel.ts +1 -3
- package/examples/routed-demo/src/map/(external)/docs/_sel.ts +1 -3
- package/examples/routed-demo/src/pages/dashboard.html +1 -1
- package/examples/routed-demo/src/pages/docs.html +1 -1
- package/examples/saucedemo/playwright.config.ts +2 -3
- package/examples/saucedemo/scripts/prove-add-to-cart-menu.mjs +2 -1
- package/examples/saucedemo/scripts/prove-auto-graph.mjs +2 -1
- package/examples/saucedemo/scripts/prove-wrong-login-runtime.mjs +2 -1
- package/examples/saucedemo/tests/flow-block-verify.spec.ts +2 -7
- package/package.json +10 -2
- package/templates/quickstart/playwright.config.ts +0 -6
- package/templates/scaffold/README.md +7 -3
- package/templates/scaffold/STRUCTURE.md +8 -6
- package/templates/scaffold/config/waygraph.config.ts +26 -0
- package/templates/scaffold/package.json +9 -13
- package/templates/scaffold/src/flows/README.md +5 -5
- package/templates/scaffold/src/flows/example.flow.ts +31 -17
- package/templates/scaffold/src/flows/hoppscotch-auth.flow.ts +35 -0
- package/templates/scaffold/src/flows/hoppscotch-get.flow.ts +23 -0
- package/templates/scaffold/src/flows/hoppscotch-post.flow.ts +33 -0
- package/templates/scaffold/src/flows/mail-verify.flow.ts +36 -75
- package/templates/scaffold/src/flows/shop.flow.ts +41 -65
- package/templates/scaffold/src/map/(app_base)/docs/_nav.block.ts +0 -9
- package/templates/scaffold/src/map/(app_base)/docs/_page.block.ts +0 -5
- package/templates/scaffold/src/map/(app_base)/docs/_sel.ts +2 -3
- package/templates/scaffold/src/map/(app_base)/docs/{docs.html → index.html} +1 -1
- package/templates/scaffold/src/map/(app_base)/home/_methods/add-item.effect.block.ts +4 -21
- package/templates/scaffold/src/map/(app_base)/home/_methods/assert-hello.method.block.ts +4 -30
- package/templates/scaffold/src/map/(app_base)/home/_methods/assert-item-added.method.block.ts +2 -19
- package/templates/scaffold/src/map/(app_base)/home/_methods/clear-cart.method.block.ts +0 -17
- package/templates/scaffold/src/map/(app_base)/home/_methods/remove-item.effect.block.ts +3 -16
- package/templates/scaffold/src/map/(app_base)/home/_nav.block.ts +3 -14
- package/templates/scaffold/src/map/(app_base)/home/_page.block.ts +0 -9
- package/templates/scaffold/src/map/(app_base)/home/_sel.ts +4 -4
- package/templates/scaffold/src/map/(app_base)/home/nav-verification-link.block.ts +1 -23
- package/templates/scaffold/src/map/(app_base)/index.html +17 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/assert-response-body.method.block.ts +21 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/assert-response-header.method.block.ts +19 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/assert-status.method.block.ts +20 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/pick-extension-interceptor.method.block.ts +18 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/read-response-body.method.block.ts +21 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/read-response-headers.method.block.ts +21 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/send-request.method.block.ts +15 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-bearer-token.method.block.ts +20 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-headers.method.block.ts +23 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-json-body.method.block.ts +36 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-method.method.block.ts +17 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-query-params.method.block.ts +22 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-url.method.block.ts +18 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/_nav.block.ts +11 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/_page.block.ts +36 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/_sel.ts +27 -0
- package/templates/scaffold/src/map/(external)/hoppscotch/settings/_nav.block.ts +10 -0
- package/templates/scaffold/src/map/(external)/mailpit/_methods/assert-email-content.method.block.ts +2 -27
- package/templates/scaffold/src/map/(external)/mailpit/_methods/assert-email-received.method.block.ts +2 -21
- package/templates/scaffold/src/map/(external)/mailpit/_methods/extract-email-link.method.block.ts +1 -19
- package/templates/scaffold/src/map/(external)/mailpit/_methods/open-message.method.block.ts +1 -11
- package/templates/scaffold/src/map/(external)/mailpit/_nav.block.ts +1 -9
- package/templates/scaffold/src/map/(external)/mailpit/_page.block.ts +0 -11
- package/templates/scaffold/src/states/demo.mem-keys.ts +20 -19
- package/templates/scaffold/src/states/demo.mem-stubs.ts +4 -0
- package/templates/scaffold/src/states/demo.states.ts +7 -1
- package/templates/scaffold/tests/README.md +3 -2
- package/templates/scaffold/tests/example.spec.ts +2 -3
- package/templates/scaffold/tests/hoppscotch.spec.ts +97 -0
- package/templates/scaffold/tests/mail-verify.spec.ts +2 -11
- package/templates/scaffold/tsconfig.json +1 -1
- package/templates/skills/waygraph-convention.skill.md +37 -6
- package/templates/skills/waygraph-pilot.skill.md +5 -6
- package/dist/runner/overlay-present.d.ts +0 -8
- package/dist/runner/overlay-present.js +0 -57
- package/dist/ui/components/banner.d.ts +0 -2
- package/dist/ui/components/banner.js +0 -10
- package/dist/ui/components/cursor.d.ts +0 -2
- package/dist/ui/components/cursor.js +0 -19
- package/examples/routed-demo/.waygraph-auto/4d4902b7.log +0 -0
- package/examples/routed-demo/.waygraph-auto/51ef462e.log +0 -0
- package/examples/routed-demo/.waygraph-auto/71527ad9.log +0 -0
- package/examples/routed-demo/.waygraph-auto/ca16778e.log +0 -0
- package/examples/routed-demo/scripts/with-fixture.mjs +0 -70
- package/examples/saucedemo/.waygraph-auto/00b0c55c.log +0 -22
- package/examples/saucedemo/.waygraph-auto/00d147d1.log +0 -21
- package/examples/saucedemo/.waygraph-auto/00e5d037.log +0 -5
- package/examples/saucedemo/.waygraph-auto/015be8f6.log +0 -6
- package/examples/saucedemo/.waygraph-auto/026e188e.log +0 -0
- package/examples/saucedemo/.waygraph-auto/02f7dd22.log +0 -20
- package/examples/saucedemo/.waygraph-auto/03df352d.log +0 -0
- package/examples/saucedemo/.waygraph-auto/0402cfcf.log +0 -6
- package/examples/saucedemo/.waygraph-auto/050e5b55.log +0 -0
- package/examples/saucedemo/.waygraph-auto/05d76fc3.log +0 -0
- package/examples/saucedemo/.waygraph-auto/062b581f.log +0 -20
- package/examples/saucedemo/.waygraph-auto/0681582b.log +0 -6
- package/examples/saucedemo/.waygraph-auto/07845ed1.log +0 -0
- package/examples/saucedemo/.waygraph-auto/07f3e964.log +0 -6
- package/examples/saucedemo/.waygraph-auto/0868ae4d.log +0 -0
- package/examples/saucedemo/.waygraph-auto/0924ddaa.log +0 -22
- package/examples/saucedemo/.waygraph-auto/092d6173.log +0 -5
- package/examples/saucedemo/.waygraph-auto/096fea05.log +0 -20
- package/examples/saucedemo/.waygraph-auto/09924510.log +0 -0
- package/examples/saucedemo/.waygraph-auto/0998c941.log +0 -21
- package/examples/saucedemo/.waygraph-auto/0a8c3719.log +0 -0
- package/examples/saucedemo/.waygraph-auto/0bf74300.log +0 -21
- package/examples/saucedemo/.waygraph-auto/0c01fd29.log +0 -4
- package/examples/saucedemo/.waygraph-auto/0c19e232.log +0 -5
- package/examples/saucedemo/.waygraph-auto/0c302590.log +0 -0
- package/examples/saucedemo/.waygraph-auto/0dee62d6.log +0 -5
- package/examples/saucedemo/.waygraph-auto/0eb4c081.log +0 -5
- package/examples/saucedemo/.waygraph-auto/0f0cb120.log +0 -0
- package/examples/saucedemo/.waygraph-auto/102c38ca.log +0 -0
- package/examples/saucedemo/.waygraph-auto/10fd431c.log +0 -0
- package/examples/saucedemo/.waygraph-auto/1122c13c.log +0 -0
- package/examples/saucedemo/.waygraph-auto/123d1cad.log +0 -5
- package/examples/saucedemo/.waygraph-auto/12ed8e28.log +0 -0
- package/examples/saucedemo/.waygraph-auto/13c6fe3c.log +0 -0
- package/examples/saucedemo/.waygraph-auto/1581b677.log +0 -0
- package/examples/saucedemo/.waygraph-auto/161cc8dd.log +0 -22
- package/examples/saucedemo/.waygraph-auto/164761a5.log +0 -6
- package/examples/saucedemo/.waygraph-auto/1905ceb2.log +0 -0
- package/examples/saucedemo/.waygraph-auto/1b1d55c6.log +0 -0
- package/examples/saucedemo/.waygraph-auto/1b80fd24.log +0 -6
- package/examples/saucedemo/.waygraph-auto/1bd7b7bf.log +0 -0
- package/examples/saucedemo/.waygraph-auto/1c30a3c2.log +0 -0
- package/examples/saucedemo/.waygraph-auto/1c58a174.log +0 -0
- package/examples/saucedemo/.waygraph-auto/1cb6f44c.log +0 -5
- package/examples/saucedemo/.waygraph-auto/1d90aa9a.log +0 -0
- package/examples/saucedemo/.waygraph-auto/1de7d889.log +0 -0
- package/examples/saucedemo/.waygraph-auto/1f233a4c.log +0 -6
- package/examples/saucedemo/.waygraph-auto/1fdb2100.log +0 -0
- package/examples/saucedemo/.waygraph-auto/20e66801.log +0 -0
- package/examples/saucedemo/.waygraph-auto/20e91af6.log +0 -5
- package/examples/saucedemo/.waygraph-auto/20ffdb77.log +0 -0
- package/examples/saucedemo/.waygraph-auto/22048fff.log +0 -4
- package/examples/saucedemo/.waygraph-auto/222d1d09.log +0 -0
- package/examples/saucedemo/.waygraph-auto/22f1a704.log +0 -5
- package/examples/saucedemo/.waygraph-auto/2324269a.log +0 -0
- package/examples/saucedemo/.waygraph-auto/232a1d81.log +0 -0
- package/examples/saucedemo/.waygraph-auto/239cced3.log +0 -20
- package/examples/saucedemo/.waygraph-auto/25204b46.log +0 -4
- package/examples/saucedemo/.waygraph-auto/2553d107.log +0 -0
- package/examples/saucedemo/.waygraph-auto/25e2e90f.log +0 -0
- package/examples/saucedemo/.waygraph-auto/2708455e.log +0 -22
- package/examples/saucedemo/.waygraph-auto/272a96fd.log +0 -20
- package/examples/saucedemo/.waygraph-auto/28d7be5d.log +0 -0
- package/examples/saucedemo/.waygraph-auto/2a577961.log +0 -0
- package/examples/saucedemo/.waygraph-auto/2a6a8266.log +0 -6
- package/examples/saucedemo/.waygraph-auto/2b3401cf.log +0 -20
- package/examples/saucedemo/.waygraph-auto/2b831907.log +0 -6
- package/examples/saucedemo/.waygraph-auto/2b9b56fc.log +0 -20
- package/examples/saucedemo/.waygraph-auto/2c79c73a.log +0 -0
- package/examples/saucedemo/.waygraph-auto/2c94a05b.log +0 -0
- package/examples/saucedemo/.waygraph-auto/2ceccd6d.log +0 -0
- package/examples/saucedemo/.waygraph-auto/2e2069e7.log +0 -0
- package/examples/saucedemo/.waygraph-auto/2e6bc35e.log +0 -6
- package/examples/saucedemo/.waygraph-auto/2efd1983.log +0 -0
- package/examples/saucedemo/.waygraph-auto/2f1b0c13.log +0 -6
- package/examples/saucedemo/.waygraph-auto/2f4f531e.log +0 -0
- package/examples/saucedemo/.waygraph-auto/2f8d4073.log +0 -6
- package/examples/saucedemo/.waygraph-auto/2fdbd916.log +0 -0
- package/examples/saucedemo/.waygraph-auto/30739278.log +0 -6
- package/examples/saucedemo/.waygraph-auto/30a5c848.log +0 -20
- package/examples/saucedemo/.waygraph-auto/31cb2e80.log +0 -0
- package/examples/saucedemo/.waygraph-auto/322d63cd.log +0 -0
- package/examples/saucedemo/.waygraph-auto/3239aa8a.log +0 -6
- package/examples/saucedemo/.waygraph-auto/326d87b7.log +0 -6
- package/examples/saucedemo/.waygraph-auto/331c6e8e.log +0 -0
- package/examples/saucedemo/.waygraph-auto/3351c0b6.log +0 -0
- package/examples/saucedemo/.waygraph-auto/33a50dc0.log +0 -0
- package/examples/saucedemo/.waygraph-auto/33df0770.log +0 -0
- package/examples/saucedemo/.waygraph-auto/340d624d.log +0 -0
- package/examples/saucedemo/.waygraph-auto/36367ccf.log +0 -0
- package/examples/saucedemo/.waygraph-auto/372536a5.log +0 -6
- package/examples/saucedemo/.waygraph-auto/37b56184.log +0 -0
- package/examples/saucedemo/.waygraph-auto/38f6799d.log +0 -0
- package/examples/saucedemo/.waygraph-auto/3a208bb8.log +0 -20
- package/examples/saucedemo/.waygraph-auto/3a412f3c.log +0 -0
- package/examples/saucedemo/.waygraph-auto/3a859bd7.log +0 -0
- package/examples/saucedemo/.waygraph-auto/3a8674d5.log +0 -6
- package/examples/saucedemo/.waygraph-auto/3bdb2f5a.log +0 -0
- package/examples/saucedemo/.waygraph-auto/3c1e5fe0.log +0 -22
- package/examples/saucedemo/.waygraph-auto/3cb0add7.log +0 -0
- package/examples/saucedemo/.waygraph-auto/3e3c0f3b.log +0 -0
- package/examples/saucedemo/.waygraph-auto/3e42f0d8.log +0 -0
- package/examples/saucedemo/.waygraph-auto/3f088138.log +0 -0
- package/examples/saucedemo/.waygraph-auto/401177a3.log +0 -0
- package/examples/saucedemo/.waygraph-auto/413d934d.log +0 -0
- package/examples/saucedemo/.waygraph-auto/4144071d.log +0 -0
- package/examples/saucedemo/.waygraph-auto/4176a3c6.log +0 -0
- package/examples/saucedemo/.waygraph-auto/41d0793d.log +0 -4
- package/examples/saucedemo/.waygraph-auto/41e6feae.log +0 -0
- package/examples/saucedemo/.waygraph-auto/424b4d5d.log +0 -0
- package/examples/saucedemo/.waygraph-auto/42e014d1.log +0 -0
- package/examples/saucedemo/.waygraph-auto/43253aba.log +0 -0
- package/examples/saucedemo/.waygraph-auto/432d09e3.log +0 -22
- package/examples/saucedemo/.waygraph-auto/438c6c53.log +0 -22
- package/examples/saucedemo/.waygraph-auto/4477db12.log +0 -0
- package/examples/saucedemo/.waygraph-auto/47247959.log +0 -0
- package/examples/saucedemo/.waygraph-auto/476cff76.log +0 -0
- package/examples/saucedemo/.waygraph-auto/4a1258b7.log +0 -0
- package/examples/saucedemo/.waygraph-auto/4ad09ece.log +0 -0
- package/examples/saucedemo/.waygraph-auto/4adcd179.log +0 -20
- package/examples/saucedemo/.waygraph-auto/4c9d9b16.log +0 -21
- package/examples/saucedemo/.waygraph-auto/4cebc228.log +0 -20
- package/examples/saucedemo/.waygraph-auto/4da39c36.log +0 -6
- package/examples/saucedemo/.waygraph-auto/4dbefa7e.log +0 -5
- package/examples/saucedemo/.waygraph-auto/4efa7035.log +0 -6
- package/examples/saucedemo/.waygraph-auto/505affdc.log +0 -4
- package/examples/saucedemo/.waygraph-auto/51bcb60a.log +0 -0
- package/examples/saucedemo/.waygraph-auto/527b6d76.log +0 -0
- package/examples/saucedemo/.waygraph-auto/5291bc78.log +0 -22
- package/examples/saucedemo/.waygraph-auto/535e8922.log +0 -0
- package/examples/saucedemo/.waygraph-auto/54274c39.log +0 -5
- package/examples/saucedemo/.waygraph-auto/5440ce7e.log +0 -0
- package/examples/saucedemo/.waygraph-auto/5738175f.log +0 -22
- package/examples/saucedemo/.waygraph-auto/573abedd.log +0 -0
- package/examples/saucedemo/.waygraph-auto/57ce5643.log +0 -22
- package/examples/saucedemo/.waygraph-auto/5984426b.log +0 -6
- package/examples/saucedemo/.waygraph-auto/5a682e7c.log +0 -22
- package/examples/saucedemo/.waygraph-auto/5b79320c.log +0 -21
- package/examples/saucedemo/.waygraph-auto/5b838485.log +0 -0
- package/examples/saucedemo/.waygraph-auto/5c55aaac.log +0 -21
- package/examples/saucedemo/.waygraph-auto/5d13bdde.log +0 -0
- package/examples/saucedemo/.waygraph-auto/5d285cd3.log +0 -0
- package/examples/saucedemo/.waygraph-auto/5ed00b16.log +0 -4
- package/examples/saucedemo/.waygraph-auto/60b9c066.log +0 -6
- package/examples/saucedemo/.waygraph-auto/610dd127.log +0 -0
- package/examples/saucedemo/.waygraph-auto/61105500.log +0 -5
- package/examples/saucedemo/.waygraph-auto/61333142.log +0 -5
- package/examples/saucedemo/.waygraph-auto/6134afe8.log +0 -20
- package/examples/saucedemo/.waygraph-auto/61937e83.log +0 -22
- package/examples/saucedemo/.waygraph-auto/625e7f65.log +0 -5
- package/examples/saucedemo/.waygraph-auto/62a0bdc9.log +0 -22
- package/examples/saucedemo/.waygraph-auto/6376fc15.log +0 -0
- package/examples/saucedemo/.waygraph-auto/63b0f4cd.log +0 -0
- package/examples/saucedemo/.waygraph-auto/6599cbca.log +0 -22
- package/examples/saucedemo/.waygraph-auto/6706ead4.log +0 -0
- package/examples/saucedemo/.waygraph-auto/67aaca30.log +0 -0
- package/examples/saucedemo/.waygraph-auto/685714af.log +0 -0
- package/examples/saucedemo/.waygraph-auto/68b10298.log +0 -0
- package/examples/saucedemo/.waygraph-auto/68be5e12.log +0 -0
- package/examples/saucedemo/.waygraph-auto/68df05a6.log +0 -22
- package/examples/saucedemo/.waygraph-auto/68fa0682.log +0 -0
- package/examples/saucedemo/.waygraph-auto/693f67c4.log +0 -20
- package/examples/saucedemo/.waygraph-auto/69ae030a.log +0 -6
- package/examples/saucedemo/.waygraph-auto/69e73f35.log +0 -6
- package/examples/saucedemo/.waygraph-auto/6b2333b0.log +0 -5
- package/examples/saucedemo/.waygraph-auto/6c4c3817.log +0 -0
- package/examples/saucedemo/.waygraph-auto/6c954911.log +0 -0
- package/examples/saucedemo/.waygraph-auto/6d65a439.log +0 -5
- package/examples/saucedemo/.waygraph-auto/6d700055.log +0 -0
- package/examples/saucedemo/.waygraph-auto/6ead848f.log +0 -0
- package/examples/saucedemo/.waygraph-auto/6f05bdc1.log +0 -0
- package/examples/saucedemo/.waygraph-auto/70279fc3.log +0 -0
- package/examples/saucedemo/.waygraph-auto/70c97639.log +0 -0
- package/examples/saucedemo/.waygraph-auto/72675b2d.log +0 -6
- package/examples/saucedemo/.waygraph-auto/731a14bd.log +0 -0
- package/examples/saucedemo/.waygraph-auto/733dd260.log +0 -5
- package/examples/saucedemo/.waygraph-auto/73a41843.log +0 -0
- package/examples/saucedemo/.waygraph-auto/75016486.log +0 -0
- package/examples/saucedemo/.waygraph-auto/752b01c6.log +0 -22
- package/examples/saucedemo/.waygraph-auto/75675227.log +0 -6
- package/examples/saucedemo/.waygraph-auto/756fd326.log +0 -20
- package/examples/saucedemo/.waygraph-auto/75e2e658.log +0 -0
- package/examples/saucedemo/.waygraph-auto/76128a2d.log +0 -0
- package/examples/saucedemo/.waygraph-auto/76ac1a86.log +0 -0
- package/examples/saucedemo/.waygraph-auto/77605295.log +0 -0
- package/examples/saucedemo/.waygraph-auto/7773a809.log +0 -0
- package/examples/saucedemo/.waygraph-auto/78043767.log +0 -20
- package/examples/saucedemo/.waygraph-auto/792671f4.log +0 -22
- package/examples/saucedemo/.waygraph-auto/796ab578.log +0 -0
- package/examples/saucedemo/.waygraph-auto/79915adb.log +0 -20
- package/examples/saucedemo/.waygraph-auto/7a398774.log +0 -6
- package/examples/saucedemo/.waygraph-auto/7a72f66e.log +0 -6
- package/examples/saucedemo/.waygraph-auto/7a984334.log +0 -4
- package/examples/saucedemo/.waygraph-auto/7b226350.log +0 -5
- package/examples/saucedemo/.waygraph-auto/7c6ee793.log +0 -20
- package/examples/saucedemo/.waygraph-auto/7c726dc4.log +0 -22
- package/examples/saucedemo/.waygraph-auto/7c72e8a5.log +0 -4
- package/examples/saucedemo/.waygraph-auto/7c99674f.log +0 -0
- package/examples/saucedemo/.waygraph-auto/7dbee625.log +0 -22
- package/examples/saucedemo/.waygraph-auto/7df66956.log +0 -0
- package/examples/saucedemo/.waygraph-auto/7e053160.log +0 -0
- package/examples/saucedemo/.waygraph-auto/7e8a6b62.log +0 -0
- package/examples/saucedemo/.waygraph-auto/7effd5b2.log +0 -20
- package/examples/saucedemo/.waygraph-auto/7f1b4864.log +0 -0
- package/examples/saucedemo/.waygraph-auto/7f94fd02.log +0 -0
- package/examples/saucedemo/.waygraph-auto/7fcb512f.log +0 -22
- package/examples/saucedemo/.waygraph-auto/7fdd47ee.log +0 -2
- package/examples/saucedemo/.waygraph-auto/802a0b5b.log +0 -0
- package/examples/saucedemo/.waygraph-auto/80322e0b.log +0 -0
- package/examples/saucedemo/.waygraph-auto/80a4978e.log +0 -6
- package/examples/saucedemo/.waygraph-auto/81257bf0.log +0 -0
- package/examples/saucedemo/.waygraph-auto/81cfe480.log +0 -22
- package/examples/saucedemo/.waygraph-auto/832f5add.log +0 -0
- package/examples/saucedemo/.waygraph-auto/8337b6ad.log +0 -0
- package/examples/saucedemo/.waygraph-auto/8481aa1c.log +0 -0
- package/examples/saucedemo/.waygraph-auto/8493928e.log +0 -0
- package/examples/saucedemo/.waygraph-auto/849ed45d.log +0 -0
- package/examples/saucedemo/.waygraph-auto/84dc6480.log +0 -6
- package/examples/saucedemo/.waygraph-auto/853bde43.log +0 -0
- package/examples/saucedemo/.waygraph-auto/8598b4c0.log +0 -0
- package/examples/saucedemo/.waygraph-auto/859a261d.log +0 -0
- package/examples/saucedemo/.waygraph-auto/86350ea6.log +0 -22
- package/examples/saucedemo/.waygraph-auto/86bb598a.log +0 -0
- package/examples/saucedemo/.waygraph-auto/86d09876.log +0 -22
- package/examples/saucedemo/.waygraph-auto/878ad01b.log +0 -4
- package/examples/saucedemo/.waygraph-auto/87c88ba5.log +0 -0
- package/examples/saucedemo/.waygraph-auto/87cb80ff.log +0 -0
- package/examples/saucedemo/.waygraph-auto/880b2e78.log +0 -6
- package/examples/saucedemo/.waygraph-auto/88527936.log +0 -5
- package/examples/saucedemo/.waygraph-auto/88eda676.log +0 -0
- package/examples/saucedemo/.waygraph-auto/893023ea.log +0 -5
- package/examples/saucedemo/.waygraph-auto/89416718.log +0 -0
- package/examples/saucedemo/.waygraph-auto/8996a857.log +0 -6
- package/examples/saucedemo/.waygraph-auto/8a08b68d.log +0 -6
- package/examples/saucedemo/.waygraph-auto/8a64ba0f.log +0 -6
- package/examples/saucedemo/.waygraph-auto/8b1cc2aa.log +0 -6
- package/examples/saucedemo/.waygraph-auto/8b73d13e.log +0 -6
- package/examples/saucedemo/.waygraph-auto/8be93021.log +0 -0
- package/examples/saucedemo/.waygraph-auto/8d960d31.log +0 -1
- package/examples/saucedemo/.waygraph-auto/8d9e5cd2.log +0 -21
- package/examples/saucedemo/.waygraph-auto/8e12e34f.log +0 -22
- package/examples/saucedemo/.waygraph-auto/8ec7d260.log +0 -0
- package/examples/saucedemo/.waygraph-auto/8ed43279.log +0 -0
- package/examples/saucedemo/.waygraph-auto/93acae32.log +0 -5
- package/examples/saucedemo/.waygraph-auto/94221b2b.log +0 -0
- package/examples/saucedemo/.waygraph-auto/96321a08.log +0 -0
- package/examples/saucedemo/.waygraph-auto/9742b6c2.log +0 -6
- package/examples/saucedemo/.waygraph-auto/9761c4c4.log +0 -6
- package/examples/saucedemo/.waygraph-auto/976394cd.log +0 -20
- package/examples/saucedemo/.waygraph-auto/982138cf.log +0 -0
- package/examples/saucedemo/.waygraph-auto/99cc93eb.log +0 -6
- package/examples/saucedemo/.waygraph-auto/9a26134c.log +0 -20
- package/examples/saucedemo/.waygraph-auto/9cbfbedc.log +0 -0
- package/examples/saucedemo/.waygraph-auto/9d827954.log +0 -20
- package/examples/saucedemo/.waygraph-auto/9dc147d2.log +0 -22
- package/examples/saucedemo/.waygraph-auto/9dd78c5e.log +0 -0
- package/examples/saucedemo/.waygraph-auto/a1ab5d29.log +0 -0
- package/examples/saucedemo/.waygraph-auto/a215a395.log +0 -22
- package/examples/saucedemo/.waygraph-auto/a23b7086.log +0 -4
- package/examples/saucedemo/.waygraph-auto/a35bd5ec.log +0 -0
- package/examples/saucedemo/.waygraph-auto/a4b36275.log +0 -0
- package/examples/saucedemo/.waygraph-auto/a4f8d355.log +0 -20
- package/examples/saucedemo/.waygraph-auto/a68995e9.log +0 -22
- package/examples/saucedemo/.waygraph-auto/a6e4f936.log +0 -22
- package/examples/saucedemo/.waygraph-auto/a7da862b.log +0 -0
- package/examples/saucedemo/.waygraph-auto/a82e2a48.log +0 -0
- package/examples/saucedemo/.waygraph-auto/a8645294.log +0 -0
- package/examples/saucedemo/.waygraph-auto/a94738b7.log +0 -0
- package/examples/saucedemo/.waygraph-auto/a952eb91.log +0 -0
- package/examples/saucedemo/.waygraph-auto/a9559653.log +0 -5
- package/examples/saucedemo/.waygraph-auto/aa1beafb.log +0 -0
- package/examples/saucedemo/.waygraph-auto/aa226dd0.log +0 -22
- package/examples/saucedemo/.waygraph-auto/aa478de2.log +0 -0
- package/examples/saucedemo/.waygraph-auto/aa7323f8.log +0 -20
- package/examples/saucedemo/.waygraph-auto/aaae4fb0.log +0 -20
- package/examples/saucedemo/.waygraph-auto/ac350fc7.log +0 -20
- package/examples/saucedemo/.waygraph-auto/ac5dde3d.log +0 -0
- package/examples/saucedemo/.waygraph-auto/acc1b63a.log +0 -0
- package/examples/saucedemo/.waygraph-auto/ad0bfad9.log +0 -5
- package/examples/saucedemo/.waygraph-auto/ad12d191.log +0 -0
- package/examples/saucedemo/.waygraph-auto/ae3a9b06.log +0 -0
- package/examples/saucedemo/.waygraph-auto/af2fae12.log +0 -0
- package/examples/saucedemo/.waygraph-auto/b04638f4.log +0 -6
- package/examples/saucedemo/.waygraph-auto/b0752c49.log +0 -0
- package/examples/saucedemo/.waygraph-auto/b14811d7.log +0 -6
- package/examples/saucedemo/.waygraph-auto/b2d2dbb2.log +0 -22
- package/examples/saucedemo/.waygraph-auto/b3d172f3.log +0 -0
- package/examples/saucedemo/.waygraph-auto/b48863e5.log +0 -22
- package/examples/saucedemo/.waygraph-auto/b5569336.log +0 -0
- package/examples/saucedemo/.waygraph-auto/b56968e1.log +0 -6
- package/examples/saucedemo/.waygraph-auto/b57921c5.log +0 -0
- package/examples/saucedemo/.waygraph-auto/b64e0620.log +0 -20
- package/examples/saucedemo/.waygraph-auto/b75168f7.log +0 -1
- package/examples/saucedemo/.waygraph-auto/b86a6218.log +0 -6
- package/examples/saucedemo/.waygraph-auto/b8e9e956.log +0 -22
- package/examples/saucedemo/.waygraph-auto/b9ab0983.log +0 -0
- package/examples/saucedemo/.waygraph-auto/b9b310ff.log +0 -21
- package/examples/saucedemo/.waygraph-auto/bb0e0e46.log +0 -0
- package/examples/saucedemo/.waygraph-auto/bc111745.log +0 -22
- package/examples/saucedemo/.waygraph-auto/bf7a77a2.log +0 -0
- package/examples/saucedemo/.waygraph-auto/bf85a598.log +0 -0
- package/examples/saucedemo/.waygraph-auto/bf8693e7.log +0 -0
- package/examples/saucedemo/.waygraph-auto/c0d6f353.log +0 -21
- package/examples/saucedemo/.waygraph-auto/c0febcf2.log +0 -20
- package/examples/saucedemo/.waygraph-auto/c4c52998.log +0 -6
- package/examples/saucedemo/.waygraph-auto/c52bac6d.log +0 -0
- package/examples/saucedemo/.waygraph-auto/c60cc55e.log +0 -0
- package/examples/saucedemo/.waygraph-auto/c809ceb4.log +0 -22
- package/examples/saucedemo/.waygraph-auto/c851cc53.log +0 -6
- package/examples/saucedemo/.waygraph-auto/c8987b67.log +0 -0
- package/examples/saucedemo/.waygraph-auto/c9d76e32.log +0 -0
- package/examples/saucedemo/.waygraph-auto/ca6de7e7.log +0 -0
- package/examples/saucedemo/.waygraph-auto/ca8561bc.log +0 -0
- package/examples/saucedemo/.waygraph-auto/cae91469.log +0 -0
- package/examples/saucedemo/.waygraph-auto/cb05d223.log +0 -0
- package/examples/saucedemo/.waygraph-auto/cb86d45b.log +0 -0
- package/examples/saucedemo/.waygraph-auto/cb9a1978.log +0 -6
- package/examples/saucedemo/.waygraph-auto/cbbc689c.log +0 -6
- package/examples/saucedemo/.waygraph-auto/cc989184.log +0 -20
- package/examples/saucedemo/.waygraph-auto/cd88364b.log +0 -0
- package/examples/saucedemo/.waygraph-auto/cd919e1d.log +0 -0
- package/examples/saucedemo/.waygraph-auto/ce584949.log +0 -5
- package/examples/saucedemo/.waygraph-auto/cf34b895.log +0 -2
- package/examples/saucedemo/.waygraph-auto/cfff9eef.log +0 -20
- package/examples/saucedemo/.waygraph-auto/d0f59b21.log +0 -4
- package/examples/saucedemo/.waygraph-auto/d1195079.log +0 -20
- package/examples/saucedemo/.waygraph-auto/d2ef067a.log +0 -5
- package/examples/saucedemo/.waygraph-auto/d37719a6.log +0 -0
- package/examples/saucedemo/.waygraph-auto/d425471f.log +0 -6
- package/examples/saucedemo/.waygraph-auto/d4afe93f.log +0 -5
- package/examples/saucedemo/.waygraph-auto/d50e58f0.log +0 -0
- package/examples/saucedemo/.waygraph-auto/d5293921.log +0 -0
- package/examples/saucedemo/.waygraph-auto/d62a22c2.log +0 -21
- package/examples/saucedemo/.waygraph-auto/d6d1761f.log +0 -22
- package/examples/saucedemo/.waygraph-auto/d6d5f411.log +0 -22
- package/examples/saucedemo/.waygraph-auto/d6df2771.log +0 -6
- package/examples/saucedemo/.waygraph-auto/d7075012.log +0 -21
- package/examples/saucedemo/.waygraph-auto/d846cd78.log +0 -0
- package/examples/saucedemo/.waygraph-auto/d934da78.log +0 -0
- package/examples/saucedemo/.waygraph-auto/d9ddc297.log +0 -0
- package/examples/saucedemo/.waygraph-auto/da0a06bf.log +0 -0
- package/examples/saucedemo/.waygraph-auto/da6ebb31.log +0 -0
- package/examples/saucedemo/.waygraph-auto/db4ac845.log +0 -0
- package/examples/saucedemo/.waygraph-auto/db6d7774.log +0 -0
- package/examples/saucedemo/.waygraph-auto/db81ba7d.log +0 -0
- package/examples/saucedemo/.waygraph-auto/db839827.log +0 -5
- package/examples/saucedemo/.waygraph-auto/dc58eb72.log +0 -0
- package/examples/saucedemo/.waygraph-auto/dddd057c.log +0 -20
- package/examples/saucedemo/.waygraph-auto/dde5e859.log +0 -22
- package/examples/saucedemo/.waygraph-auto/ddf975e6.log +0 -0
- package/examples/saucedemo/.waygraph-auto/de8cac58.log +0 -0
- package/examples/saucedemo/.waygraph-auto/de8cb83d.log +0 -6
- package/examples/saucedemo/.waygraph-auto/ded5511a.log +0 -6
- package/examples/saucedemo/.waygraph-auto/dedfcb18.log +0 -0
- package/examples/saucedemo/.waygraph-auto/def4d9b1.log +0 -0
- package/examples/saucedemo/.waygraph-auto/e03cfd8e.log +0 -0
- package/examples/saucedemo/.waygraph-auto/e1549e40.log +0 -0
- package/examples/saucedemo/.waygraph-auto/e1b0676d.log +0 -21
- package/examples/saucedemo/.waygraph-auto/e230f24e.log +0 -0
- package/examples/saucedemo/.waygraph-auto/e5111463.log +0 -0
- package/examples/saucedemo/.waygraph-auto/e5127c03.log +0 -22
- package/examples/saucedemo/.waygraph-auto/e5fc1d7c.log +0 -5
- package/examples/saucedemo/.waygraph-auto/e6fd2202.log +0 -0
- package/examples/saucedemo/.waygraph-auto/eb38d92e.log +0 -22
- package/examples/saucedemo/.waygraph-auto/edaa806d.log +0 -0
- package/examples/saucedemo/.waygraph-auto/edaf33de.log +0 -0
- package/examples/saucedemo/.waygraph-auto/edd40cbb.log +0 -20
- package/examples/saucedemo/.waygraph-auto/eddfbffc.log +0 -6
- package/examples/saucedemo/.waygraph-auto/ee86203e.log +0 -0
- package/examples/saucedemo/.waygraph-auto/ee9fa1ad.log +0 -5
- package/examples/saucedemo/.waygraph-auto/ef319474.log +0 -22
- package/examples/saucedemo/.waygraph-auto/f1f38eeb.log +0 -22
- package/examples/saucedemo/.waygraph-auto/f24b2915.log +0 -0
- package/examples/saucedemo/.waygraph-auto/f28eee8d.log +0 -0
- package/examples/saucedemo/.waygraph-auto/f2943898.log +0 -0
- package/examples/saucedemo/.waygraph-auto/f33bde90.log +0 -0
- package/examples/saucedemo/.waygraph-auto/f43de83c.log +0 -0
- package/examples/saucedemo/.waygraph-auto/f6ba7cb4.log +0 -6
- package/examples/saucedemo/.waygraph-auto/f7ac4d62.log +0 -20
- package/examples/saucedemo/.waygraph-auto/f86224c6.log +0 -0
- package/examples/saucedemo/.waygraph-auto/f929bb79.log +0 -0
- package/examples/saucedemo/.waygraph-auto/f92d4c6c.log +0 -22
- package/examples/saucedemo/.waygraph-auto/f92faf40.log +0 -5
- package/examples/saucedemo/.waygraph-auto/fa784369.log +0 -21
- package/examples/saucedemo/.waygraph-auto/fb55f723.log +0 -20
- package/examples/saucedemo/.waygraph-auto/fba3b738.log +0 -0
- package/examples/saucedemo/.waygraph-auto/fc917c18.log +0 -0
- package/examples/saucedemo/.waygraph-auto/fdf66b74.log +0 -0
- package/examples/saucedemo/.waygraph-auto/fe83305d.log +0 -0
- package/examples/saucedemo/.waygraph-auto/ff616932.log +0 -0
- package/examples/saucedemo/.waygraph-auto/ffdf2854.log +0 -6
- package/examples/saucedemo/scripts/capture-auto-headful.mjs +0 -120
- package/examples/saucedemo/scripts/capture-wrong-login.mjs +0 -141
- package/examples/saucedemo/scripts/demo-device-presets.mjs +0 -188
- package/examples/saucedemo/scripts/demo-orientation-gestures-video.mjs +0 -262
- package/examples/saucedemo/scripts/show-add-to-cart-menu.mjs +0 -123
- package/examples/saucedemo/scripts/show-auto-menu.mjs +0 -72
- package/templates/scaffold/playwright.config.ts +0 -28
- package/templates/scaffold/scripts/README.md +0 -13
- package/templates/scaffold/scripts/fixture-server.mjs +0 -50
- package/templates/scaffold/scripts/with-fixture.mjs +0 -69
- package/templates/scaffold/test-results/.last-run.json +0 -4
- /package/templates/scaffold/src/map/(app_base)/home/{home.html → index.html} +0 -0
package/templates/scaffold/src/map/(external)/hoppscotch/_methods/assert-status.method.block.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { defineAssertBlock, type Trait } from "waygraph";
|
|
2
|
+
import type { HoppscotchRest } from "../../../../states/demo.states.js";
|
|
3
|
+
import { ExpectedStatus } from "../../../../states/demo.mem-keys.js";
|
|
4
|
+
import { HoppscotchSel } from "../_sel.js";
|
|
5
|
+
|
|
6
|
+
const statusMatches: Trait = {
|
|
7
|
+
name: "response-status-matches",
|
|
8
|
+
async check(page, mem) {
|
|
9
|
+
const text = (await page.locator(HoppscotchSel.status).first().textContent()) ?? "";
|
|
10
|
+
return Number(text.match(/Status:\s*(\d+)/)?.[1]) === mem.get(ExpectedStatus);
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const AssertStatusBlock = defineAssertBlock<HoppscotchRest>({
|
|
15
|
+
name: "assert-status",
|
|
16
|
+
description: "Confirms the response status code equals the mem-supplied one.",
|
|
17
|
+
checkpoint: "HoppscotchRest",
|
|
18
|
+
requires: [ExpectedStatus],
|
|
19
|
+
verify: [statusMatches],
|
|
20
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { defineMethodBlock, checkpoint } from "waygraph";
|
|
2
|
+
import type { HoppscotchSettings } from "../../../../states/demo.states.js";
|
|
3
|
+
import { HoppscotchSel } from "../_sel.js";
|
|
4
|
+
|
|
5
|
+
export const PickExtensionInterceptorBlock = defineMethodBlock<HoppscotchSettings, HoppscotchSettings>({
|
|
6
|
+
name: "pick-extension-interceptor",
|
|
7
|
+
description: "Routes Hoppscotch's requests through the browser extension, which skips CORS.",
|
|
8
|
+
instruction: {
|
|
9
|
+
async act(page) {
|
|
10
|
+
const radio = page.locator(HoppscotchSel.extensionInterceptor);
|
|
11
|
+
await radio.waitFor({ timeout: 10_000 }).catch(() => {
|
|
12
|
+
throw new Error('Hoppscotch extension not loaded - add extensions: ["hoppscotch"] to waygraph.config.ts');
|
|
13
|
+
});
|
|
14
|
+
await radio.click();
|
|
15
|
+
},
|
|
16
|
+
resolve: () => checkpoint("HoppscotchSettings"),
|
|
17
|
+
},
|
|
18
|
+
});
|
package/templates/scaffold/src/map/(external)/hoppscotch/_methods/read-response-body.method.block.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { defineMethodBlock, checkpoint } from "waygraph";
|
|
2
|
+
import type { HoppscotchRest } from "../../../../states/demo.states.js";
|
|
3
|
+
import { ResponseBody } from "../../../../states/demo.mem-keys.js";
|
|
4
|
+
import { HoppscotchSel } from "../_sel.js";
|
|
5
|
+
|
|
6
|
+
export const ReadResponseBodyBlock = defineMethodBlock<HoppscotchRest, HoppscotchRest>({
|
|
7
|
+
name: "read-response-body",
|
|
8
|
+
description: "Reads the raw response body into mem.",
|
|
9
|
+
instruction: {
|
|
10
|
+
async act(page, _in, mem) {
|
|
11
|
+
await page.locator(HoppscotchSel.rawTab).click();
|
|
12
|
+
const body = page.locator(HoppscotchSel.responseEditor);
|
|
13
|
+
await body.waitFor();
|
|
14
|
+
mem.set(ResponseBody, (await body.innerText()).trim());
|
|
15
|
+
// Raw is the reliable place to read from; go back to the formatted JSON view so a recording ends on it.
|
|
16
|
+
const json = page.locator(HoppscotchSel.responseJsonTab);
|
|
17
|
+
if (await json.count()) await json.click();
|
|
18
|
+
},
|
|
19
|
+
resolve: () => checkpoint("HoppscotchRest"),
|
|
20
|
+
},
|
|
21
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { defineMethodBlock, checkpoint } from "waygraph";
|
|
2
|
+
import type { HoppscotchRest } from "../../../../states/demo.states.js";
|
|
3
|
+
import { ResponseHeaders } from "../../../../states/demo.mem-keys.js";
|
|
4
|
+
import { HoppscotchSel } from "../_sel.js";
|
|
5
|
+
|
|
6
|
+
export const ReadResponseHeadersBlock = defineMethodBlock<HoppscotchRest, HoppscotchRest>({
|
|
7
|
+
name: "read-response-headers",
|
|
8
|
+
description: "Reads the response headers (lower-cased names) into mem.",
|
|
9
|
+
instruction: {
|
|
10
|
+
async act(page, _in, mem) {
|
|
11
|
+
await page.locator(HoppscotchSel.responseHeadersTab).click();
|
|
12
|
+
const cells = page.locator(HoppscotchSel.responseHeaderCell);
|
|
13
|
+
await cells.first().waitFor();
|
|
14
|
+
const texts = (await cells.allInnerTexts()).map((t) => t.trim());
|
|
15
|
+
const headers: Record<string, string> = {};
|
|
16
|
+
for (let i = 0; i + 1 < texts.length; i += 2) headers[texts[i]!.toLowerCase()] = texts[i + 1]!;
|
|
17
|
+
mem.set(ResponseHeaders, headers);
|
|
18
|
+
},
|
|
19
|
+
resolve: () => checkpoint("HoppscotchRest"),
|
|
20
|
+
},
|
|
21
|
+
});
|
package/templates/scaffold/src/map/(external)/hoppscotch/_methods/send-request.method.block.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { defineMethodBlock, checkpoint } from "waygraph";
|
|
2
|
+
import type { HoppscotchRest } from "../../../../states/demo.states.js";
|
|
3
|
+
import { HoppscotchSel } from "../_sel.js";
|
|
4
|
+
|
|
5
|
+
export const SendRequestBlock = defineMethodBlock<HoppscotchRest, HoppscotchRest>({
|
|
6
|
+
name: "send-request",
|
|
7
|
+
description: "Sends the request and waits for the response status to appear.",
|
|
8
|
+
instruction: {
|
|
9
|
+
async act(page) {
|
|
10
|
+
await page.locator(HoppscotchSel.send).click();
|
|
11
|
+
await page.locator(HoppscotchSel.status).waitFor({ timeout: 20_000 });
|
|
12
|
+
},
|
|
13
|
+
resolve: () => checkpoint("HoppscotchRest"),
|
|
14
|
+
},
|
|
15
|
+
});
|
package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-bearer-token.method.block.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { defineMethodBlock, checkpoint } from "waygraph";
|
|
2
|
+
import type { HoppscotchRest } from "../../../../states/demo.states.js";
|
|
3
|
+
import { RequestBearerToken } from "../../../../states/demo.mem-keys.js";
|
|
4
|
+
import { HoppscotchSel } from "../_sel.js";
|
|
5
|
+
|
|
6
|
+
export const SetBearerTokenBlock = defineMethodBlock<HoppscotchRest, HoppscotchRest>({
|
|
7
|
+
name: "set-bearer-token",
|
|
8
|
+
description: "Sets the Authorization tab to Bearer and types the mem-supplied token.",
|
|
9
|
+
requires: [RequestBearerToken],
|
|
10
|
+
instruction: {
|
|
11
|
+
async act(page, _in, mem) {
|
|
12
|
+
await page.locator(HoppscotchSel.tab("Authorization")).click();
|
|
13
|
+
await page.locator(HoppscotchSel.authTypeMenu).click();
|
|
14
|
+
await page.locator(HoppscotchSel.menuItem("Bearer")).click();
|
|
15
|
+
await page.locator(HoppscotchSel.bearerToken).locator(HoppscotchSel.editor).click();
|
|
16
|
+
await page.keyboard.type(mem.get(RequestBearerToken));
|
|
17
|
+
},
|
|
18
|
+
resolve: () => checkpoint("HoppscotchRest"),
|
|
19
|
+
},
|
|
20
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { defineMethodBlock, checkpoint } from "waygraph";
|
|
2
|
+
import type { HoppscotchRest } from "../../../../states/demo.states.js";
|
|
3
|
+
import { RequestHeaders } from "../../../../states/demo.mem-keys.js";
|
|
4
|
+
import { HoppscotchSel } from "../_sel.js";
|
|
5
|
+
|
|
6
|
+
export const SetHeadersBlock = defineMethodBlock<HoppscotchRest, HoppscotchRest>({
|
|
7
|
+
name: "set-headers",
|
|
8
|
+
description: "Adds each mem-supplied header (name -> value) on the Headers tab.",
|
|
9
|
+
requires: [RequestHeaders],
|
|
10
|
+
instruction: {
|
|
11
|
+
async act(page, _in, mem) {
|
|
12
|
+
await page.locator(HoppscotchSel.tab("Headers")).click();
|
|
13
|
+
const headers = Object.entries(mem.get(RequestHeaders));
|
|
14
|
+
for (const [i, [name, value]] of headers.entries()) {
|
|
15
|
+
await page.locator(HoppscotchSel.keyCell).nth(i).locator(HoppscotchSel.editor).click();
|
|
16
|
+
await page.keyboard.type(name);
|
|
17
|
+
await page.locator(HoppscotchSel.valueCell).nth(i).locator(HoppscotchSel.editor).click();
|
|
18
|
+
await page.keyboard.type(value);
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
resolve: () => checkpoint("HoppscotchRest"),
|
|
22
|
+
},
|
|
23
|
+
});
|
package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-json-body.method.block.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { defineMethodBlock, checkpoint } from "waygraph";
|
|
2
|
+
import type { HoppscotchRest } from "../../../../states/demo.states.js";
|
|
3
|
+
import { RequestBody } from "../../../../states/demo.mem-keys.js";
|
|
4
|
+
import { HoppscotchSel } from "../_sel.js";
|
|
5
|
+
|
|
6
|
+
const spansLines = (text: string): boolean => {
|
|
7
|
+
try {
|
|
8
|
+
return JSON.stringify(JSON.parse(text), null, 2).includes("\n");
|
|
9
|
+
} catch {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const SetJsonBodyBlock = defineMethodBlock<HoppscotchRest, HoppscotchRest>({
|
|
15
|
+
name: "set-json-body",
|
|
16
|
+
description: "Sets the content type to application/json and types the mem-supplied body, prettified.",
|
|
17
|
+
requires: [RequestBody],
|
|
18
|
+
instruction: {
|
|
19
|
+
async act(page, _in, mem) {
|
|
20
|
+
await page.locator(HoppscotchSel.tab("Body")).click();
|
|
21
|
+
await page.locator(HoppscotchSel.contentTypeMenu).click();
|
|
22
|
+
await page.locator(HoppscotchSel.menuItem("application/json")).click();
|
|
23
|
+
const editor = page.locator(HoppscotchSel.visibleEditor).last();
|
|
24
|
+
await editor.click();
|
|
25
|
+
const body = mem.get(RequestBody);
|
|
26
|
+
await page.keyboard.type(body);
|
|
27
|
+
if (!spansLines(body)) return;
|
|
28
|
+
// Prettify is the third toolbar button (Clear, Wrap lines, Prettify); typed JSON stays on one line otherwise.
|
|
29
|
+
await page.locator(HoppscotchSel.bodyToolbarButton).nth(2).click();
|
|
30
|
+
if ((await editor.locator(HoppscotchSel.bodyLine).count()) < 2) {
|
|
31
|
+
throw new Error("set-json-body: Hoppscotch's Prettify button was not found, so the body stayed on one line");
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
resolve: () => checkpoint("HoppscotchRest"),
|
|
35
|
+
},
|
|
36
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { defineMethodBlock, checkpoint } from "waygraph";
|
|
2
|
+
import type { HoppscotchRest } from "../../../../states/demo.states.js";
|
|
3
|
+
import { RequestMethod } from "../../../../states/demo.mem-keys.js";
|
|
4
|
+
import { HoppscotchSel } from "../_sel.js";
|
|
5
|
+
|
|
6
|
+
export const SetMethodBlock = defineMethodBlock<HoppscotchRest, HoppscotchRest>({
|
|
7
|
+
name: "set-method",
|
|
8
|
+
description: "Picks the HTTP method (GET, POST, PUT, PATCH, DELETE, ...) from the request bar.",
|
|
9
|
+
requires: [RequestMethod],
|
|
10
|
+
instruction: {
|
|
11
|
+
async act(page, _in, mem) {
|
|
12
|
+
await page.locator(HoppscotchSel.methodInput).click();
|
|
13
|
+
await page.locator(HoppscotchSel.menuItem(mem.get(RequestMethod))).click();
|
|
14
|
+
},
|
|
15
|
+
resolve: () => checkpoint("HoppscotchRest"),
|
|
16
|
+
},
|
|
17
|
+
});
|
package/templates/scaffold/src/map/(external)/hoppscotch/_methods/set-query-params.method.block.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { defineMethodBlock, checkpoint } from "waygraph";
|
|
2
|
+
import type { HoppscotchRest } from "../../../../states/demo.states.js";
|
|
3
|
+
import { RequestParams } from "../../../../states/demo.mem-keys.js";
|
|
4
|
+
import { HoppscotchSel } from "../_sel.js";
|
|
5
|
+
|
|
6
|
+
export const SetQueryParamsBlock = defineMethodBlock<HoppscotchRest, HoppscotchRest>({
|
|
7
|
+
name: "set-query-params",
|
|
8
|
+
description: "Adds each mem-supplied query parameter (name -> value) on the Parameters tab.",
|
|
9
|
+
requires: [RequestParams],
|
|
10
|
+
instruction: {
|
|
11
|
+
async act(page, _in, mem) {
|
|
12
|
+
await page.locator(HoppscotchSel.tab("Parameters")).click();
|
|
13
|
+
for (const [i, [name, value]] of Object.entries(mem.get(RequestParams)).entries()) {
|
|
14
|
+
await page.locator(HoppscotchSel.keyCell).nth(i).locator(HoppscotchSel.editor).click();
|
|
15
|
+
await page.keyboard.type(name);
|
|
16
|
+
await page.locator(HoppscotchSel.valueCell).nth(i).locator(HoppscotchSel.editor).click();
|
|
17
|
+
await page.keyboard.type(value);
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
resolve: () => checkpoint("HoppscotchRest"),
|
|
21
|
+
},
|
|
22
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { defineMethodBlock, checkpoint } from "waygraph";
|
|
2
|
+
import type { HoppscotchRest } from "../../../../states/demo.states.js";
|
|
3
|
+
import { RequestUrl } from "../../../../states/demo.mem-keys.js";
|
|
4
|
+
import { HoppscotchSel } from "../_sel.js";
|
|
5
|
+
|
|
6
|
+
export const SetUrlBlock = defineMethodBlock<HoppscotchRest, HoppscotchRest>({
|
|
7
|
+
name: "set-url",
|
|
8
|
+
description: "Types the request URL into the request bar.",
|
|
9
|
+
requires: [RequestUrl],
|
|
10
|
+
instruction: {
|
|
11
|
+
async act(page, _in, mem) {
|
|
12
|
+
await page.locator(HoppscotchSel.urlInput).first().click();
|
|
13
|
+
await page.keyboard.press("Control+A");
|
|
14
|
+
await page.keyboard.type(mem.get(RequestUrl));
|
|
15
|
+
},
|
|
16
|
+
resolve: () => checkpoint("HoppscotchRest"),
|
|
17
|
+
},
|
|
18
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { defineNavBlock, Trait } from "waygraph";
|
|
2
|
+
import type { HoppscotchRest } from "../../../states/demo.states.js";
|
|
3
|
+
import { HoppscotchSel } from "./_sel.js";
|
|
4
|
+
|
|
5
|
+
export const NavHoppscotchRestBlock = defineNavBlock<HoppscotchRest>({
|
|
6
|
+
name: "nav-hoppscotch-rest",
|
|
7
|
+
checkpoint: "HoppscotchRest",
|
|
8
|
+
// Cross-origin, so a function: the Map folder rule only checks static URLs.
|
|
9
|
+
url: () => "https://hoppscotch.io/",
|
|
10
|
+
verify: [Trait.visible(HoppscotchSel.send)],
|
|
11
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { definePageBlock, Trait } from "waygraph";
|
|
2
|
+
import type { HoppscotchRest } from "../../../states/demo.states.js";
|
|
3
|
+
import { SetMethodBlock } from "./_methods/set-method.method.block.js";
|
|
4
|
+
import { SetUrlBlock } from "./_methods/set-url.method.block.js";
|
|
5
|
+
import { SetHeadersBlock } from "./_methods/set-headers.method.block.js";
|
|
6
|
+
import { SetJsonBodyBlock } from "./_methods/set-json-body.method.block.js";
|
|
7
|
+
import { SendRequestBlock } from "./_methods/send-request.method.block.js";
|
|
8
|
+
import { AssertStatusBlock } from "./_methods/assert-status.method.block.js";
|
|
9
|
+
import { ReadResponseBodyBlock } from "./_methods/read-response-body.method.block.js";
|
|
10
|
+
import { AssertResponseBodyBlock } from "./_methods/assert-response-body.method.block.js";
|
|
11
|
+
import { SetQueryParamsBlock } from "./_methods/set-query-params.method.block.js";
|
|
12
|
+
import { SetBearerTokenBlock } from "./_methods/set-bearer-token.method.block.js";
|
|
13
|
+
import { ReadResponseHeadersBlock } from "./_methods/read-response-headers.method.block.js";
|
|
14
|
+
import { AssertResponseHeaderBlock } from "./_methods/assert-response-header.method.block.js";
|
|
15
|
+
import { HoppscotchSel } from "./_sel.js";
|
|
16
|
+
|
|
17
|
+
export const HoppscotchRestPageBlock = definePageBlock<HoppscotchRest>({
|
|
18
|
+
name: "page-hoppscotch-rest",
|
|
19
|
+
description: "Hoppscotch REST client - build a request, send it, check the response.",
|
|
20
|
+
checkpoint: "HoppscotchRest",
|
|
21
|
+
verify: [Trait.visible(HoppscotchSel.send)],
|
|
22
|
+
methods: {
|
|
23
|
+
setMethod: () => SetMethodBlock,
|
|
24
|
+
setUrl: () => SetUrlBlock,
|
|
25
|
+
setHeaders: () => SetHeadersBlock,
|
|
26
|
+
setQueryParams: () => SetQueryParamsBlock,
|
|
27
|
+
setBearerToken: () => SetBearerTokenBlock,
|
|
28
|
+
setJsonBody: () => SetJsonBodyBlock,
|
|
29
|
+
sendRequest: () => SendRequestBlock,
|
|
30
|
+
assertStatus: () => AssertStatusBlock,
|
|
31
|
+
readResponseHeaders: () => ReadResponseHeadersBlock,
|
|
32
|
+
assertResponseHeader: () => AssertResponseHeaderBlock,
|
|
33
|
+
readResponseBody: () => ReadResponseBodyBlock,
|
|
34
|
+
assertResponseBody: () => AssertResponseBodyBlock,
|
|
35
|
+
},
|
|
36
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Structural selectors (roles, aria-labels), not bare text: waygraph's own demo overlay repeats page text.
|
|
2
|
+
export const HoppscotchSel = {
|
|
3
|
+
urlInput: ".cm-content",
|
|
4
|
+
send: "#send",
|
|
5
|
+
methodInput: "input#method",
|
|
6
|
+
/** The request's tab; the response has its own Headers tab, so take the first match. */
|
|
7
|
+
tab: (name: string) => `button.tab[aria-label='${name}'] >> nth=0`,
|
|
8
|
+
menuItem: (name: string) => `button[role=menuitem]:has(:text-is("${name}"))`,
|
|
9
|
+
keyCell: '[placeholder^="Key"]:visible',
|
|
10
|
+
valueCell: '[placeholder^="Value"]:visible',
|
|
11
|
+
contentTypeMenu: "label:text-is('Content Type') + span button",
|
|
12
|
+
bearerToken: '[placeholder^="Your Bearer Token"]',
|
|
13
|
+
authTypeMenu: "label:text-is('Authorization Type') + span button",
|
|
14
|
+
/** The element holding "Status: 201 • Created". */
|
|
15
|
+
status: "*:has(> span.text-secondary:text-is('Status:'))",
|
|
16
|
+
responseHeadersTab: "button.tab[aria-label='Headers'] >> nth=-1",
|
|
17
|
+
responseHeaderCell: "*:has(> span.text-secondary:text-is('Status:')) >> xpath=following::span[contains(@class,'select-all')]",
|
|
18
|
+
responseJsonTab: "button.tab[aria-label='JSON']",
|
|
19
|
+
rawTab: "button.tab[aria-label='Raw']",
|
|
20
|
+
responseEditor: "div.flex-col:has(> div.sticky label:text-is('Response Body')) .cm-content",
|
|
21
|
+
bodyToolbarButton: "div.sticky:has(label:text-is('Raw Request Body')) button",
|
|
22
|
+
bodyLine: ".cm-line",
|
|
23
|
+
editor: ".cm-content",
|
|
24
|
+
visibleEditor: ".cm-content:visible",
|
|
25
|
+
interceptorHeading: "h4:text('Interceptor')",
|
|
26
|
+
extensionInterceptor: 'button:has-text("Browser extension: v")',
|
|
27
|
+
} as const;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { defineNavBlock, Trait } from "waygraph";
|
|
2
|
+
import type { HoppscotchSettings } from "../../../../states/demo.states.js";
|
|
3
|
+
import { HoppscotchSel } from "../_sel.js";
|
|
4
|
+
|
|
5
|
+
export const NavHoppscotchSettingsBlock = defineNavBlock<HoppscotchSettings>({
|
|
6
|
+
name: "nav-hoppscotch-settings",
|
|
7
|
+
checkpoint: "HoppscotchSettings",
|
|
8
|
+
url: () => "https://hoppscotch.io/settings",
|
|
9
|
+
verify: [Trait.visible(HoppscotchSel.interceptorHeading)],
|
|
10
|
+
});
|
package/templates/scaffold/src/map/(external)/mailpit/_methods/assert-email-content.method.block.ts
CHANGED
|
@@ -3,13 +3,7 @@ import type { MailpitMessageOpen } from "../../../../states/demo.states.js";
|
|
|
3
3
|
import { ExpectedEmailContent } from "../../../../states/demo.mem-keys.js";
|
|
4
4
|
import { MailpitSel } from "../_sel.js";
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
* Mem-aware Trait: the expected copy varies per email scenario, so it can't
|
|
8
|
-
* be a static `Trait.frameContains(...)` call (which bakes its expected
|
|
9
|
-
* string in at Block-definition time) - a Trait's own `check(page, mem)`
|
|
10
|
-
* already receives mem, so a bespoke Trait reads it at check time instead.
|
|
11
|
-
* This is what lets one Block serve any number of different email templates.
|
|
12
|
-
*/
|
|
6
|
+
// Reads the expected copy from mem, so one Block serves any email template.
|
|
13
7
|
const bodyContainsExpectedText: Trait = {
|
|
14
8
|
name: "body-contains-expected-text",
|
|
15
9
|
async check(page, mem) {
|
|
@@ -19,26 +13,7 @@ const bodyContainsExpectedText: Trait = {
|
|
|
19
13
|
},
|
|
20
14
|
};
|
|
21
15
|
|
|
22
|
-
/**
|
|
23
|
-
* Kind: Assert
|
|
24
|
-
* Helper: defineAssertBlock
|
|
25
|
-
* Route: demo-external/mailpit/_methods/
|
|
26
|
-
*
|
|
27
|
-
* "Does the email actually say what it's supposed to" - not just "does a
|
|
28
|
-
* link exist somewhere in it." Reads the message body straight out of the
|
|
29
|
-
* preview iframe (the top-level page's own `Trait.text`/`Trait.visible`
|
|
30
|
-
* can't see inside an iframe at all - see docs/REFERENCE.md "Mail adapters" section).
|
|
31
|
-
* Self-loop on MailpitMessageOpen - no state change, verify only.
|
|
32
|
-
*
|
|
33
|
-
* Deliberately named for what it does, not for one scenario: the expected
|
|
34
|
-
* copy comes from mem (`ExpectedEmailContent`), not a hardcoded string in
|
|
35
|
-
* this file, so this one Block serves any number of different email
|
|
36
|
-
* scenarios - a Block named "assert-verification-email-content" would
|
|
37
|
-
* wrongly imply it only ever checks verification-email copy.
|
|
38
|
-
*
|
|
39
|
-
* Explicit `<MailpitMessageOpen>` type argument - see the same note on
|
|
40
|
-
* `assert-email-received.method.block.ts` for why this can't be inferred.
|
|
41
|
-
*/
|
|
16
|
+
/** The open message says what the scenario expects (copy comes from mem). */
|
|
42
17
|
export const AssertEmailContentBlock = defineAssertBlock<MailpitMessageOpen>({
|
|
43
18
|
name: "assert-email-content",
|
|
44
19
|
description: "Confirms the open message's body contains the mem-supplied expected copy.",
|
package/templates/scaffold/src/map/(external)/mailpit/_methods/assert-email-received.method.block.ts
CHANGED
|
@@ -3,12 +3,7 @@ import type { MailpitInbox } from "../../../../states/demo.states.js";
|
|
|
3
3
|
import { ExpectedRecipient } from "../../../../states/demo.mem-keys.js";
|
|
4
4
|
import { MailpitSel } from "../_sel.js";
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
* Mem-aware Trait: the selector depends on which recipient this run expects,
|
|
8
|
-
* so it can't be a static `Trait.visible(...)` string - a Trait's own
|
|
9
|
-
* `check(page, mem)` already receives mem, so a bespoke Trait object reads it
|
|
10
|
-
* directly instead of needing a new engine primitive.
|
|
11
|
-
*/
|
|
6
|
+
// Mem-aware: which recipient to look for is only known at run time.
|
|
12
7
|
const emailReceived: Trait = {
|
|
13
8
|
name: "email-received",
|
|
14
9
|
async check(page, mem) {
|
|
@@ -25,21 +20,7 @@ const emailReceived: Trait = {
|
|
|
25
20
|
},
|
|
26
21
|
};
|
|
27
22
|
|
|
28
|
-
/**
|
|
29
|
-
* Kind: Assert
|
|
30
|
-
* Helper: defineAssertBlock
|
|
31
|
-
* Route: demo-external/mailpit/_methods/
|
|
32
|
-
*
|
|
33
|
-
* "Did the email even arrive" - a lightweight existence check that does not
|
|
34
|
-
* open or consume the message, so it's safe to run before deciding to open
|
|
35
|
-
* anything. Self-loop on MailpitInbox - no state change, verify only.
|
|
36
|
-
*
|
|
37
|
-
* Explicit `<MailpitInbox>` type argument: `defineAssertBlock` defaults to
|
|
38
|
-
* wildcard `Checkpoint<string>` on both sides when uninferred, which only
|
|
39
|
-
* "works" when the assert sits last in a chain (nothing downstream narrows
|
|
40
|
-
* it) - this one sits between two specifically-typed Blocks, so it must be
|
|
41
|
-
* parameterized explicitly or `defineFlow`'s tuple typing breaks.
|
|
42
|
-
*/
|
|
23
|
+
/** A message for the expected recipient has arrived; nothing is opened or consumed. */
|
|
43
24
|
export const AssertEmailReceivedBlock = defineAssertBlock<MailpitInbox>({
|
|
44
25
|
name: "assert-email-received",
|
|
45
26
|
description: "Confirms a message addressed to the expected recipient has arrived.",
|
package/templates/scaffold/src/map/(external)/mailpit/_methods/extract-email-link.method.block.ts
CHANGED
|
@@ -3,25 +3,7 @@ import type { MailpitMessageOpen } from "../../../../states/demo.states.js";
|
|
|
3
3
|
import { EmailLink, ExpectedLinkPattern } from "../../../../states/demo.mem-keys.js";
|
|
4
4
|
import { MailpitSel } from "../_sel.js";
|
|
5
5
|
|
|
6
|
-
/**
|
|
7
|
-
* Kind: Method
|
|
8
|
-
* Helper: defineMethodBlock
|
|
9
|
-
* Route: demo-external/mailpit/_methods/
|
|
10
|
-
*
|
|
11
|
-
* Reads a link straight out of the open message's HTML preview iframe via a
|
|
12
|
-
* real DOM read (getAttribute) - no mail-catcher REST API - and stores it in
|
|
13
|
-
* mem. A separate NavBlock does the actual navigation: folding "read the
|
|
14
|
-
* link" and "go there" into one Block would repeat the exact compound-action
|
|
15
|
-
* anti-pattern `waygraph check` flags elsewhere.
|
|
16
|
-
*
|
|
17
|
-
* Deliberately named for what it does, not for one scenario: the
|
|
18
|
-
* link-matching substring comes from mem (`ExpectedLinkPattern`), not a
|
|
19
|
-
* hardcoded string, so this one Block serves any number of different email
|
|
20
|
-
* scenarios in a project (a signup confirmation, a password reset, a magic
|
|
21
|
-
* link, ...) by varying mem per run, not by writing a new Block per
|
|
22
|
-
* scenario - a Block named "extract-verification-link" would wrongly imply
|
|
23
|
-
* it only ever handles verification emails.
|
|
24
|
-
*/
|
|
6
|
+
/** Reads the link matching `ExpectedLinkPattern` out of the preview into mem; going there is a separate Nav. */
|
|
25
7
|
export const ExtractEmailLinkBlock = defineMethodBlock<MailpitMessageOpen, MailpitMessageOpen>({
|
|
26
8
|
name: "extract-email-link",
|
|
27
9
|
description: "Reads the link matching the mem-supplied pattern out of the open message's preview.",
|
|
@@ -4,17 +4,7 @@ import type { MailpitInbox, MailpitMessageOpen } from "../../../../states/demo.s
|
|
|
4
4
|
import { ExpectedRecipient } from "../../../../states/demo.mem-keys.js";
|
|
5
5
|
import { MailpitSel } from "../_sel.js";
|
|
6
6
|
|
|
7
|
-
/**
|
|
8
|
-
* Kind: Method
|
|
9
|
-
* Helper: defineMethodBlock
|
|
10
|
-
* Route: demo-external/mailpit/_methods/
|
|
11
|
-
*
|
|
12
|
-
* Opens the newest inbox row addressed to the mem-set recipient (not bare
|
|
13
|
-
* inbox position - a prior run's leftover mail for a different recipient
|
|
14
|
-
* would otherwise pick the wrong row). UI click only, no mail-catcher REST
|
|
15
|
-
* API - the row itself is a real link (`page.waitForURL` sees the client-side
|
|
16
|
-
* route change the same as any other in-page navigation).
|
|
17
|
-
*/
|
|
7
|
+
/** Opens the newest message for the expected recipient (matched by email, not position). */
|
|
18
8
|
export const OpenMessageBlock = defineMethodBlock<MailpitInbox, MailpitMessageOpen>({
|
|
19
9
|
name: "open-message",
|
|
20
10
|
description: "Opens the newest message addressed to the expected recipient.",
|
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
import { defineNavBlock, Trait } from "waygraph";
|
|
2
2
|
import type { MailpitInbox } from "../../../states/demo.states.js";
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
* Kind: Nav
|
|
6
|
-
* Helper: defineNavBlock
|
|
7
|
-
* Route: (external)/mailpit/ (cross-origin - a real Mailpit web UI, not this app)
|
|
8
|
-
*
|
|
9
|
-
* Cross-origin tooling lives under (external)/, never (app_base)/ - this is
|
|
10
|
-
* a dev-inbox screen, not part of the app under test. `WAYGRAPH_MAIL_URL`
|
|
11
|
-
* defaults to Mailpit's own usual local port.
|
|
12
|
-
*/
|
|
4
|
+
// Cross-origin, so it lives under (external)/ and the URL is a function.
|
|
13
5
|
const mailpitUrl = (): string => process.env.WAYGRAPH_MAIL_URL ?? "http://127.0.0.1:8025";
|
|
14
6
|
|
|
15
7
|
export const NavMailpitInboxBlock = defineNavBlock<MailpitInbox>({
|
|
@@ -5,17 +5,6 @@ import { OpenMessageBlock } from "./_methods/open-message.method.block.js";
|
|
|
5
5
|
import { AssertEmailContentBlock } from "./_methods/assert-email-content.method.block.js";
|
|
6
6
|
import { ExtractEmailLinkBlock } from "./_methods/extract-email-link.method.block.js";
|
|
7
7
|
|
|
8
|
-
/**
|
|
9
|
-
* Kind: Page
|
|
10
|
-
* Helper: definePageBlock
|
|
11
|
-
* Route: (external)/mailpit/ (= http://127.0.0.1:8025/ by default)
|
|
12
|
-
*
|
|
13
|
-
* Hub for the Mailpit dev-inbox screen. Arrival-only (no url/click) -
|
|
14
|
-
* nav-mailpit-inbox owns the goto. Methods: confirm the email arrived, open
|
|
15
|
-
* it, confirm its content, then read its link - all mem-driven (recipient,
|
|
16
|
-
* link pattern, expected content), so this one page's methods serve any
|
|
17
|
-
* number of different email scenarios, not just one.
|
|
18
|
-
*/
|
|
19
8
|
export const MailpitInboxPageBlock = definePageBlock<MailpitInbox>({
|
|
20
9
|
name: "page-mailpit-inbox",
|
|
21
10
|
description: "Mailpit dev inbox hub - confirm arrival/content, open the expected message, read its link.",
|
|
@@ -1,31 +1,32 @@
|
|
|
1
1
|
import { key, keyGroup } from "waygraph";
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
* Which catalog row `add-item` / `remove-item` act on.
|
|
5
|
-
* `waygraph auto` fills this via Effect `instanceOptions` (one menu row per live button).
|
|
6
|
-
*/
|
|
3
|
+
/** The catalog row `add-item` / `remove-item` act on; `waygraph auto` fills it from `instanceOptions`. */
|
|
7
4
|
export const SelectedItem = keyGroup<{ id: string; name: string }>("demo.selectedItem");
|
|
8
5
|
|
|
9
6
|
/** The link read out of the opened message - set by extract-email-link. */
|
|
10
7
|
export const EmailLink = keyGroup<{ url: string }>("demo.emailLink");
|
|
11
8
|
|
|
12
|
-
/**
|
|
13
|
-
* The recipient open-message looks for in the inbox. Mailpit lists newest
|
|
14
|
-
* first, but `.first()` alone picks the wrong row once more than one
|
|
15
|
-
* recipient's mail is sitting in the same inbox - match by mem, not position.
|
|
16
|
-
*/
|
|
9
|
+
/** Matched by email, not inbox position, so one inbox can hold several recipients' mail. */
|
|
17
10
|
export const ExpectedRecipient = keyGroup<{ email: string }>("demo.expectedRecipient");
|
|
18
11
|
|
|
19
|
-
/**
|
|
20
|
-
* Substring the link's `href` must contain - lets the same extract-email-link
|
|
21
|
-
* Block serve any number of different email templates/scenarios in one
|
|
22
|
-
* project without a new Block per scenario. Only the mem values change per
|
|
23
|
-
* run, not the Blocks.
|
|
24
|
-
*/
|
|
12
|
+
/** Substring the link's `href` must contain; mem varies per scenario, the Blocks do not. */
|
|
25
13
|
export const ExpectedLinkPattern = key<string>("demo.expectedLinkPattern");
|
|
26
14
|
|
|
27
|
-
/**
|
|
28
|
-
* The substring the open message's body must contain - same reuse reasoning
|
|
29
|
-
* as ExpectedLinkPattern: one Block, many scenarios, driven by mem.
|
|
30
|
-
*/
|
|
15
|
+
/** Substring the open message's body must contain. */
|
|
31
16
|
export const ExpectedEmailContent = key<string>("demo.expectedEmailContent");
|
|
17
|
+
|
|
18
|
+
export const RequestMethod = key<string>("demo.requestMethod");
|
|
19
|
+
export const RequestUrl = key<string>("demo.requestUrl");
|
|
20
|
+
export const RequestHeaders = key<Record<string, string>>("demo.requestHeaders");
|
|
21
|
+
export const RequestParams = key<Record<string, string>>("demo.requestParams");
|
|
22
|
+
export const RequestBearerToken = key<string>("demo.requestBearerToken");
|
|
23
|
+
/** Raw JSON text typed into the request body editor. */
|
|
24
|
+
export const RequestBody = key<string>("demo.requestBody");
|
|
25
|
+
export const ExpectedStatus = key<number>("demo.expectedStatus");
|
|
26
|
+
/** Substring the response body must contain. */
|
|
27
|
+
export const ExpectedResponseText = key<string>("demo.expectedResponseText");
|
|
28
|
+
/** The raw response body, set by read-response-body. */
|
|
29
|
+
export const ResponseBody = key<string>("demo.responseBody");
|
|
30
|
+
/** Response headers (lower-cased names), set by read-response-headers. */
|
|
31
|
+
export const ResponseHeaders = key<Record<string, string>>("demo.responseHeaders");
|
|
32
|
+
export const ExpectedResponseHeader = keyGroup<{ name: string; value: string }>("demo.expectedResponseHeader");
|
|
@@ -4,6 +4,8 @@ export type Home = Checkpoint<"Home">;
|
|
|
4
4
|
export type HomeVerified = Checkpoint<"HomeVerified">;
|
|
5
5
|
export type ItemInCart = Checkpoint<"ItemInCart">;
|
|
6
6
|
export type CartEmpty = Checkpoint<"CartEmpty">;
|
|
7
|
+
/** Anywhere an item can be added from: fresh on Home, or after the cart was emptied. */
|
|
8
|
+
export type CanAddItem = Home | CartEmpty;
|
|
7
9
|
|
|
8
10
|
// --- Mailpit (external tool surface, src/map/(external)/mailpit/) ---
|
|
9
11
|
|
|
@@ -13,5 +15,9 @@ export type MailpitInbox = Checkpoint<"MailpitInbox">;
|
|
|
13
15
|
/** The message addressed to the expected recipient is open; preview iframe visible. */
|
|
14
16
|
export type MailpitMessageOpen = Checkpoint<"MailpitMessageOpen">;
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
// --- Hoppscotch (external API client, src/map/(external)/hoppscotch/) ---
|
|
19
|
+
|
|
20
|
+
export type HoppscotchSettings = Checkpoint<"HoppscotchSettings">;
|
|
21
|
+
export type HoppscotchRest = Checkpoint<"HoppscotchRest">;
|
|
22
|
+
|
|
17
23
|
export type Docs = Checkpoint<"Docs">;
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
Real `@playwright/test` specs, run through `waygraph test` (an alias for `playwright test`,
|
|
4
4
|
plus `waygraph test ui`/`report`/`show-trace` for Playwright's own UI Mode/HTML report/trace
|
|
5
|
-
viewer). These run against the offline fixture
|
|
6
|
-
network - that's what makes `npm test` green immediately after
|
|
5
|
+
viewer). These run against the offline fixture pages under `src/map/` (opened directly via `file://`,
|
|
6
|
+
no server), not a live network - that's what makes `npm test` green immediately after
|
|
7
|
+
`waygraph init`.
|
|
7
8
|
|
|
8
9
|
A spec here typically runs a `*.flow.ts` from `src/flows/` and asserts on its result, rather
|
|
9
10
|
than driving the page directly - the flow already encodes the real path and its own `verify`
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { test, expect } from "@playwright/test";
|
|
2
|
-
import { MemPage, checkpoint } from "waygraph";
|
|
2
|
+
import { MemPage, checkpoint, seedMemStub } from "waygraph";
|
|
3
3
|
import { exampleFlow } from "../src/flows/example.flow.js";
|
|
4
4
|
import { shopFlow } from "../src/flows/shop.flow.js";
|
|
5
|
-
import { SelectedItem } from "../src/states/demo.mem-keys.js";
|
|
6
5
|
|
|
7
6
|
test("example flow reaches Docs (home -> assert -> sibling docs/ page)", async ({ context }) => {
|
|
8
7
|
const result = await exampleFlow.run(context, new MemPage());
|
|
@@ -11,7 +10,7 @@ test("example flow reaches Docs (home -> assert -> sibling docs/ page)", async (
|
|
|
11
10
|
|
|
12
11
|
test("shop flow adds then clears (Effect + Method)", async ({ context }) => {
|
|
13
12
|
const mem = new MemPage();
|
|
14
|
-
mem
|
|
13
|
+
seedMemStub(mem, shopFlow);
|
|
15
14
|
const result = await shopFlow.run(context, mem);
|
|
16
15
|
expect(result).toEqual(checkpoint("CartEmpty"));
|
|
17
16
|
});
|