waygraph 0.15.50 → 0.15.51
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/map-check.js +5 -2
- package/dist/analysis/practices-check.js +17 -4
- package/dist/auto-session/session.js +2 -1
- package/dist/browser-path.d.ts +5 -0
- package/dist/browser-path.js +18 -0
- package/dist/cli/run-chain.js +1 -0
- package/dist/commands/init.js +5 -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 +0 -3
- package/dist/core/blocks/page.d.ts +0 -3
- package/dist/core/flow.js +3 -6
- package/dist/highlights/types.d.ts +3 -2
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2 -0
- package/dist/runner/inpage/banner.js +10 -2
- package/dist/runner/main.js +10 -6
- package/dist/session/auto-explore-run.js +13 -2
- package/dist/traverse/run.js +2 -1
- package/dist/types.d.ts +0 -3
- package/dist/webserver.d.ts +14 -0
- package/dist/webserver.js +91 -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 +5 -3
- package/templates/scaffold/STRUCTURE.md +3 -4
- package/templates/scaffold/package.json +8 -12
- package/templates/scaffold/playwright.config.ts +2 -18
- package/templates/scaffold/src/map/(app_base)/docs/_nav.block.ts +1 -1
- 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 +12 -13
- package/templates/scaffold/src/map/(app_base)/home/_methods/assert-hello.method.block.ts +19 -22
- package/templates/scaffold/src/map/(app_base)/home/_methods/clear-cart.method.block.ts +7 -8
- package/templates/scaffold/src/map/(app_base)/home/_methods/remove-item.effect.block.ts +4 -8
- package/templates/scaffold/src/map/(app_base)/home/_nav.block.ts +10 -10
- package/templates/scaffold/src/map/(app_base)/home/_sel.ts +2 -4
- package/templates/scaffold/src/map/(app_base)/index.html +17 -0
- package/templates/scaffold/src/states/demo.states.ts +2 -0
- package/templates/scaffold/tests/README.md +3 -2
- package/templates/scaffold/tsconfig.json +1 -1
- package/templates/skills/waygraph-convention.skill.md +5 -3
- package/templates/skills/waygraph-pilot.skill.md +1 -1
- 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/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
|
@@ -117,12 +117,15 @@ export async function checkMap(projectDir) {
|
|
|
117
117
|
continue; // only statically-urled Nav/Page Blocks are checkable
|
|
118
118
|
let pathname;
|
|
119
119
|
try {
|
|
120
|
-
|
|
120
|
+
// Relative URLs (the normal baseUrl case) are paths from the app root.
|
|
121
|
+
pathname = new URL(navUrl, "http://app.invalid/").pathname;
|
|
121
122
|
}
|
|
122
123
|
catch {
|
|
123
|
-
continue;
|
|
124
|
+
continue;
|
|
124
125
|
}
|
|
125
126
|
const urlSegments = pathname.split("/").filter(Boolean);
|
|
127
|
+
if (urlSegments.at(-1) === "index.html")
|
|
128
|
+
urlSegments.pop(); // /docs/index.html is the docs/ folder
|
|
126
129
|
const folderSegments = realSegments(relative(mapRoot, file));
|
|
127
130
|
const matches = urlSegments.length === folderSegments.length && urlSegments.every((s, i) => s === folderSegments[i]);
|
|
128
131
|
if (!matches) {
|
|
@@ -5,8 +5,20 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { readFileSync, readdirSync } from "node:fs";
|
|
7
7
|
import { dirname, relative } from "node:path";
|
|
8
|
-
/** define*Block
|
|
9
|
-
const
|
|
8
|
+
/** Every define*Block<In, Out> / <Out> generic list - args may themselves be Checkpoint<...>. */
|
|
9
|
+
const BLOCK_GENERICS = /\bdefine(?:Method|Effect|MemEffect|Page|Nav|MemNav|NavClick|Action)Block\s*<\s*((?:Checkpoint\s*<[^>]*>|[^,<>])+?)\s*(?:,\s*((?:Checkpoint\s*<[^>]*>|[^,<>])+?)\s*)?>/g;
|
|
10
|
+
/**
|
|
11
|
+
* A wildcard Out (the Block's result is untyped). A wildcard In is fine - it's the documented
|
|
12
|
+
* "reachable from anywhere" form (graph.ts treats it like a NavBlock's "*").
|
|
13
|
+
*/
|
|
14
|
+
function hasWildcardOut(src) {
|
|
15
|
+
for (const m of src.matchAll(BLOCK_GENERICS)) {
|
|
16
|
+
const out = (m[2] ?? m[1]).trim();
|
|
17
|
+
if (/^Checkpoint\s*<\s*string\s*>$/.test(out))
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
10
22
|
/** defineAssertBlock({ … }) with no explicit Out type — defaults to wildcard. */
|
|
11
23
|
const ASSERT_NO_TYPE_ARG = /\bdefineAssertBlock\s*\(\s*\{/;
|
|
12
24
|
/** defineAssertBlock, any form - used to scope the empty-verify check below. */
|
|
@@ -74,11 +86,12 @@ export function collectPracticeWarnings(projectDir, walkDir, opts) {
|
|
|
74
86
|
const rel = relative(projectDir, file).replace(/\\/g, "/");
|
|
75
87
|
const src = readFileSync(file, "utf-8");
|
|
76
88
|
const ignore = ignoredKindsForFile(src);
|
|
77
|
-
if (!isIgnored("wildcard-checkpoint", ignore) &&
|
|
89
|
+
if (!isIgnored("wildcard-checkpoint", ignore) && hasWildcardOut(src)) {
|
|
78
90
|
warnings.push({
|
|
79
91
|
kind: "wildcard-checkpoint",
|
|
80
92
|
file: rel,
|
|
81
|
-
detail: '
|
|
93
|
+
detail: "the Block's output is Checkpoint<string>, so its result is untyped — use a typed Checkpoint from " +
|
|
94
|
+
"src/states/ (e.g. defineMethodBlock<LoginPage, LoggedIn>); a wildcard input is fine",
|
|
82
95
|
});
|
|
83
96
|
}
|
|
84
97
|
if (!isIgnored("assert-no-type-arg", ignore) && ASSERT_NO_TYPE_ARG.test(src)) {
|
|
@@ -9,6 +9,7 @@ import { collectKnownInteractionSelectors, unmappedInteractionsPageScript } from
|
|
|
9
9
|
import { runStubPhase } from "../highlights.js";
|
|
10
10
|
import { verboseLog } from "./verbose-log.js";
|
|
11
11
|
import { findBlockPathDetailed } from "../analysis/graph.js";
|
|
12
|
+
import { chromiumExecutablePath } from "../browser-path.js";
|
|
12
13
|
/**
|
|
13
14
|
* Non-interactive explore session: same graph/library/mem/browser setup
|
|
14
15
|
* `runAutoExplore` runs in `--cli` mode, driven by `applyPick` instead of a
|
|
@@ -67,7 +68,7 @@ export class AutoSession {
|
|
|
67
68
|
const headless = init.headless ?? true;
|
|
68
69
|
const engine = new Engine({ headless });
|
|
69
70
|
const { chromium } = await import("@playwright/test");
|
|
70
|
-
const executablePath =
|
|
71
|
+
const executablePath = chromiumExecutablePath();
|
|
71
72
|
// Real gap found live: a headed (--non-headless) session kept a fixed
|
|
72
73
|
// 1280x720 content area even when the user maximized/fullscreened the
|
|
73
74
|
// actual window - `viewport: null` alone only makes the PAGE track the
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CHROME_PATH / CHROMIUM_PATH, if set and the file exists. A stale path (browser uninstalled)
|
|
3
|
+
* falls back to Playwright's bundled Chromium with a one-time warning instead of failing the run.
|
|
4
|
+
*/
|
|
5
|
+
export declare function chromiumExecutablePath(): string | undefined;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
let warned = false;
|
|
3
|
+
/**
|
|
4
|
+
* CHROME_PATH / CHROMIUM_PATH, if set and the file exists. A stale path (browser uninstalled)
|
|
5
|
+
* falls back to Playwright's bundled Chromium with a one-time warning instead of failing the run.
|
|
6
|
+
*/
|
|
7
|
+
export function chromiumExecutablePath() {
|
|
8
|
+
const path = process.env.CHROME_PATH || process.env.CHROMIUM_PATH;
|
|
9
|
+
if (!path)
|
|
10
|
+
return undefined;
|
|
11
|
+
if (existsSync(path))
|
|
12
|
+
return path;
|
|
13
|
+
if (!warned) {
|
|
14
|
+
warned = true;
|
|
15
|
+
console.error(`waygraph: CHROME_PATH/CHROMIUM_PATH "${path}" does not exist - using Playwright's bundled Chromium`);
|
|
16
|
+
}
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
package/dist/cli/run-chain.js
CHANGED
|
@@ -49,6 +49,7 @@ export async function runChain(projectDir, spec) {
|
|
|
49
49
|
const scriptPath = join(projectDir, `.waygraph-chain-${process.pid}.mjs`);
|
|
50
50
|
writeFileSync(scriptPath, CHAIN_RUNNER_BOOTSTRAP);
|
|
51
51
|
try {
|
|
52
|
+
// webServer is started inside the child (runner/main.js), never here - see CHAIN_RUNNER_BOOTSTRAP.
|
|
52
53
|
const code = await new Promise((res, rej) => {
|
|
53
54
|
const child = spawn(process.execPath, ["--import", tsxEsm, scriptPath, projectDir, expanded], {
|
|
54
55
|
stdio: "inherit",
|
package/dist/commands/init.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { packageRoot } from "../cli/util.js";
|
|
3
3
|
import { basename, join, relative, resolve } from "node:path";
|
|
4
4
|
import { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
|
|
5
|
+
import { pathToFileURL } from "node:url";
|
|
5
6
|
function initCommand(projectName) {
|
|
6
7
|
if (!projectName) {
|
|
7
8
|
console.error("waygraph init: missing <project-name>, e.g. waygraph init my-app");
|
|
@@ -30,8 +31,12 @@ function initCommand(projectName) {
|
|
|
30
31
|
writeFileSync(join(targetDir, ".gitignore"), readFileSync(gitignoreSrc, "utf-8"));
|
|
31
32
|
rmSync(gitignoreSrc);
|
|
32
33
|
}
|
|
34
|
+
// Demo pages open via file://; the absolute path is only known once copied, so it's filled in here.
|
|
35
|
+
const appBaseUrl = pathToFileURL(join(targetDir, "src", "map", "(app_base)", "index.html")).href;
|
|
33
36
|
const packageJsonPath = join(targetDir, "package.json");
|
|
34
37
|
writeFileSync(packageJsonPath, readFileSync(packageJsonPath, "utf-8").replaceAll("__PROJECT_NAME__", pkgName));
|
|
38
|
+
const playwrightConfigPath = join(targetDir, "playwright.config.ts");
|
|
39
|
+
writeFileSync(playwrightConfigPath, readFileSync(playwrightConfigPath, "utf-8").replaceAll("__APP_BASE_URL__", appBaseUrl));
|
|
35
40
|
console.log(`Scaffolded ${pkgName}/`);
|
|
36
41
|
console.log("");
|
|
37
42
|
console.log(` cd ${relative(process.cwd(), targetDir) || pkgName}`);
|
|
@@ -17,13 +17,10 @@ export type EffectBlock<In extends Checkpoint<string>, Out extends Checkpoint<st
|
|
|
17
17
|
modVerifyAll(patches: Record<string, Trait["check"] | Trait>): EffectBlock<In, Out>;
|
|
18
18
|
stubBefore(stub: import("../../highlights.js").HighlightStubPhase): EffectBlock<In, Out>;
|
|
19
19
|
stubBefore(stub: import("../../highlights.js").StubLifecycleFn<Out>): EffectBlock<In, Out>;
|
|
20
|
-
stubBefore(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): EffectBlock<In, Out>;
|
|
21
20
|
stubAfter(stub: import("../../highlights.js").HighlightStubPhase): EffectBlock<In, Out>;
|
|
22
21
|
stubAfter(stub: import("../../highlights.js").StubLifecycleFn<Out>): EffectBlock<In, Out>;
|
|
23
|
-
stubAfter(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): EffectBlock<In, Out>;
|
|
24
22
|
stubOnError(stub: import("../../highlights.js").HighlightStubPhase): EffectBlock<In, Out>;
|
|
25
23
|
stubOnError(stub: import("../../highlights.js").StubLifecycleFn<Out>): EffectBlock<In, Out>;
|
|
26
|
-
stubOnError(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): EffectBlock<In, Out>;
|
|
27
24
|
};
|
|
28
25
|
/** @deprecated Prefer {@link EffectBlock} - same type; Mem* was an early name. */
|
|
29
26
|
export type MemEffectBlock<In extends Checkpoint<string>, Out extends Checkpoint<string>> = EffectBlock<In, Out>;
|
|
@@ -17,13 +17,10 @@ export type MethodBlock<In extends Checkpoint<string>, Out extends Checkpoint<st
|
|
|
17
17
|
modVerifyAll(patches: Record<string, Trait["check"] | Trait>): MethodBlock<In, Out>;
|
|
18
18
|
stubBefore(stub: import("../../highlights.js").HighlightStubPhase): MethodBlock<In, Out>;
|
|
19
19
|
stubBefore(stub: import("../../highlights.js").StubLifecycleFn<Out>): MethodBlock<In, Out>;
|
|
20
|
-
stubBefore(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): MethodBlock<In, Out>;
|
|
21
20
|
stubAfter(stub: import("../../highlights.js").HighlightStubPhase): MethodBlock<In, Out>;
|
|
22
21
|
stubAfter(stub: import("../../highlights.js").StubLifecycleFn<Out>): MethodBlock<In, Out>;
|
|
23
|
-
stubAfter(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): MethodBlock<In, Out>;
|
|
24
22
|
stubOnError(stub: import("../../highlights.js").HighlightStubPhase): MethodBlock<In, Out>;
|
|
25
23
|
stubOnError(stub: import("../../highlights.js").StubLifecycleFn<Out>): MethodBlock<In, Out>;
|
|
26
|
-
stubOnError(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): MethodBlock<In, Out>;
|
|
27
24
|
};
|
|
28
25
|
/** @deprecated Prefer {@link MethodBlock} - same type; Action was the 0.7 name. */
|
|
29
26
|
export type ActionBlock<In extends Checkpoint<string>, Out extends Checkpoint<string>> = MethodBlock<In, Out>;
|
|
@@ -80,11 +77,8 @@ export type AssertBlock<Out extends Checkpoint<string>> = Omit<DefinedBlock<Out,
|
|
|
80
77
|
modVerifyAll(patches: Record<string, Trait["check"] | Trait>): AssertBlock<Out>;
|
|
81
78
|
stubBefore(stub: import("../../highlights.js").HighlightStubPhase): AssertBlock<Out>;
|
|
82
79
|
stubBefore(stub: import("../../highlights.js").StubLifecycleFn<Out>): AssertBlock<Out>;
|
|
83
|
-
stubBefore(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): AssertBlock<Out>;
|
|
84
80
|
stubAfter(stub: import("../../highlights.js").HighlightStubPhase): AssertBlock<Out>;
|
|
85
81
|
stubAfter(stub: import("../../highlights.js").StubLifecycleFn<Out>): AssertBlock<Out>;
|
|
86
|
-
stubAfter(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): AssertBlock<Out>;
|
|
87
82
|
stubOnError(stub: import("../../highlights.js").HighlightStubPhase): AssertBlock<Out>;
|
|
88
83
|
stubOnError(stub: import("../../highlights.js").StubLifecycleFn<Out>): AssertBlock<Out>;
|
|
89
|
-
stubOnError(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): AssertBlock<Out>;
|
|
90
84
|
};
|
|
@@ -22,13 +22,10 @@ export type NavBlock<Out extends Checkpoint<string>> = Omit<DefinedBlock<Checkpo
|
|
|
22
22
|
modVerifyAll(patches: Record<string, Trait["check"] | Trait>): NavBlock<Out>;
|
|
23
23
|
stubBefore(stub: import("../../highlights.js").HighlightStubPhase): NavBlock<Out>;
|
|
24
24
|
stubBefore(stub: import("../../highlights.js").StubLifecycleFn<Out>): NavBlock<Out>;
|
|
25
|
-
stubBefore(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): NavBlock<Out>;
|
|
26
25
|
stubAfter(stub: import("../../highlights.js").HighlightStubPhase): NavBlock<Out>;
|
|
27
26
|
stubAfter(stub: import("../../highlights.js").StubLifecycleFn<Out>): NavBlock<Out>;
|
|
28
|
-
stubAfter(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): NavBlock<Out>;
|
|
29
27
|
stubOnError(stub: import("../../highlights.js").HighlightStubPhase): NavBlock<Out>;
|
|
30
28
|
stubOnError(stub: import("../../highlights.js").StubLifecycleFn<Out>): NavBlock<Out>;
|
|
31
|
-
stubOnError(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): NavBlock<Out>;
|
|
32
29
|
};
|
|
33
30
|
/**
|
|
34
31
|
* `defineNavBlock`'s own options - exactly one of `url`/`click` required,
|
|
@@ -47,13 +47,10 @@ export type PageBlock<Out extends Checkpoint<string>> = Omit<DefinedBlock<Checkp
|
|
|
47
47
|
modVerifyAll(patches: Record<string, Trait["check"] | Trait>): PageBlock<Out>;
|
|
48
48
|
stubBefore(stub: import("../../highlights.js").HighlightStubPhase): PageBlock<Out>;
|
|
49
49
|
stubBefore(stub: import("../../highlights.js").StubLifecycleFn<Out>): PageBlock<Out>;
|
|
50
|
-
stubBefore(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): PageBlock<Out>;
|
|
51
50
|
stubAfter(stub: import("../../highlights.js").HighlightStubPhase): PageBlock<Out>;
|
|
52
51
|
stubAfter(stub: import("../../highlights.js").StubLifecycleFn<Out>): PageBlock<Out>;
|
|
53
|
-
stubAfter(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): PageBlock<Out>;
|
|
54
52
|
stubOnError(stub: import("../../highlights.js").HighlightStubPhase): PageBlock<Out>;
|
|
55
53
|
stubOnError(stub: import("../../highlights.js").StubLifecycleFn<Out>): PageBlock<Out>;
|
|
56
|
-
stubOnError(stub: (out: Out) => import("../../highlights.js").HighlightStubPhase): PageBlock<Out>;
|
|
57
54
|
};
|
|
58
55
|
/** @see {@link PageBlockOptions} */
|
|
59
56
|
export declare function definePageBlock<Out extends Checkpoint<string>>(options: PageBlockOptions<Out>): PageBlock<Out>;
|
package/dist/core/flow.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Split out of the former 2,900-line engine.ts (see src/ARCHITECTURE.md). Behavior unchanged.
|
|
2
2
|
import { connect } from "../types.js";
|
|
3
|
+
import { chromiumExecutablePath } from "../browser-path.js";
|
|
3
4
|
import { WaygraphError, MSG_CHAINFLOW_BLOCK_NOT_FOUND_BY_INDEX, MSG_CHAINFLOW_BLOCK_NOT_FOUND_BY_NAME, MSG_CHAINFLOW_EMPTY, } from "../errors.js";
|
|
4
5
|
import { preflight, runGraph } from "./run-graph.js";
|
|
5
6
|
import { resolveLauncher } from "./config.js";
|
|
@@ -33,11 +34,7 @@ export function buildFlow(middle, engineConfig) {
|
|
|
33
34
|
preflight(mem, chain);
|
|
34
35
|
const browserName = config.browserName ?? "chromium";
|
|
35
36
|
const launch = resolveLauncher(browserName, config);
|
|
36
|
-
|
|
37
|
-
// or Flatpak Chromium), launch that instead of Playwright's own bundled
|
|
38
|
-
// binary - only for chromium (the env var names a Chromium build, not a
|
|
39
|
-
// Firefox/WebKit one), and a no-op default anywhere that env var isn't set.
|
|
40
|
-
const executablePath = browserName === "chromium" ? process.env.CHROME_PATH || process.env.CHROMIUM_PATH : undefined;
|
|
37
|
+
const executablePath = browserName === "chromium" ? chromiumExecutablePath() : undefined;
|
|
41
38
|
const browser = await launch.launch({
|
|
42
39
|
headless: config.headless ?? true,
|
|
43
40
|
...(config.slowMo !== undefined ? { slowMo: config.slowMo } : {}),
|
|
@@ -324,7 +321,7 @@ export function chainFlow(...flows) {
|
|
|
324
321
|
// session reset, silently making withSessionReset a no-op).
|
|
325
322
|
const browserName = config?.browserName ?? "chromium";
|
|
326
323
|
const launch = resolveLauncher(browserName, config);
|
|
327
|
-
const executablePath = browserName === "chromium" ?
|
|
324
|
+
const executablePath = browserName === "chromium" ? chromiumExecutablePath() : undefined;
|
|
328
325
|
const browser = await launch.launch({
|
|
329
326
|
headless: config?.headless ?? true,
|
|
330
327
|
...(config?.slowMo !== undefined ? { slowMo: config.slowMo } : {}),
|
|
@@ -464,9 +464,10 @@ export type StubLifecycleFn<Out extends Checkpoint<string>> = (ctx: StubCtx<Out>
|
|
|
464
464
|
* Block stub authoring:
|
|
465
465
|
* - **preferred:** open lifecycle `stubBefore(ctx) { ctx.todos(...); ctx.ring(...) }`
|
|
466
466
|
* - **shorthand:** static slot map `{ email: { selector, label } }`
|
|
467
|
-
*
|
|
467
|
+
*
|
|
468
|
+
* Exactly one function member, so an inline `stubAfter(ctx) {}` gets `ctx` typed.
|
|
468
469
|
*/
|
|
469
|
-
export type HighlightStubPhaseOrFn<Out extends Checkpoint<string>> = HighlightStubPhase | StubLifecycleFn<Out
|
|
470
|
+
export type HighlightStubPhaseOrFn<Out extends Checkpoint<string>> = HighlightStubPhase | StubLifecycleFn<Out>;
|
|
470
471
|
/** Result of running a stub phase (rings + episode fixtures). */
|
|
471
472
|
export type StubPhaseResult = {
|
|
472
473
|
highlights: ResolvedHighlight[];
|
package/dist/index.d.ts
CHANGED
|
@@ -31,3 +31,6 @@ export { pilotStart } from "./session/pilot.js";
|
|
|
31
31
|
export type { PilotStartResult } from "./session/pilot.js";
|
|
32
32
|
export { defineConfig, resolveBaseUrl } from "./config.js";
|
|
33
33
|
export type { WaygraphConfig } from "./config.js";
|
|
34
|
+
export { withWebServer } from "./webserver.js";
|
|
35
|
+
export { chromiumExecutablePath } from "./browser-path.js";
|
|
36
|
+
export type { WebServerConfig } from "./webserver.js";
|
package/dist/index.js
CHANGED
|
@@ -15,3 +15,5 @@ export { WG_UI_SEL, WG_READY_PANEL_SEL, WG_READY_AUTO_SEL, WG_READY_BANNER_SEL,
|
|
|
15
15
|
export { AutoSession, stubFilePath } from "./auto-session.js";
|
|
16
16
|
export { pilotStart } from "./session/pilot.js";
|
|
17
17
|
export { defineConfig, resolveBaseUrl } from "./config.js";
|
|
18
|
+
export { withWebServer } from "./webserver.js";
|
|
19
|
+
export { chromiumExecutablePath } from "./browser-path.js";
|
|
@@ -101,28 +101,36 @@ export function installBanner({ title, favicon, bannerPos, todoPos, envAutoplay,
|
|
|
101
101
|
);
|
|
102
102
|
};
|
|
103
103
|
const home = b.dataset.home || b.dataset.pos || "left";
|
|
104
|
+
// Called every animation frame while a ring is followed - only log when the outcome changes.
|
|
105
|
+
const log = (state, line) => {
|
|
106
|
+
if (b.dataset.lastLog === state) return;
|
|
107
|
+
b.dataset.lastLog = state;
|
|
108
|
+
if (line) (window.__wgBannerLog = window.__wgBannerLog || []).push(line);
|
|
109
|
+
};
|
|
104
110
|
b.dataset.pos = home;
|
|
105
111
|
if (!hits()) {
|
|
106
112
|
delete b.dataset.moved;
|
|
113
|
+
log("clear");
|
|
107
114
|
return;
|
|
108
115
|
}
|
|
109
116
|
for (const cand of POSITIONS.filter((p) => p !== home)) {
|
|
110
117
|
b.dataset.pos = cand;
|
|
111
118
|
if (!hits()) {
|
|
112
119
|
b.dataset.moved = home + ">" + cand;
|
|
113
|
-
(
|
|
120
|
+
log("moved:" + cand, "moved " + home + " -> " + cand + " (ring overlap)");
|
|
114
121
|
return;
|
|
115
122
|
}
|
|
116
123
|
}
|
|
117
124
|
b.dataset.pos = home;
|
|
118
125
|
b.dataset.moved = "none-free";
|
|
119
|
-
(
|
|
126
|
+
log("none-free", "overlap at every position (kept " + home + ")");
|
|
120
127
|
};
|
|
121
128
|
window.__wgBannerRestore = () => {
|
|
122
129
|
const b = __wgById("wg-banner");
|
|
123
130
|
if (!b) return;
|
|
124
131
|
if (b.dataset.home) b.dataset.pos = b.dataset.home;
|
|
125
132
|
delete b.dataset.moved;
|
|
133
|
+
delete b.dataset.lastLog;
|
|
126
134
|
};
|
|
127
135
|
// Dim the banner while a ring caption is the focus - same "auto opacity" effect the todo
|
|
128
136
|
// dock already has via __wgTodosSetBehind, extended to the banner so both floating chrome
|
package/dist/runner/main.js
CHANGED
|
@@ -9,8 +9,10 @@ import { runStepMode } from "./step-mode.js";
|
|
|
9
9
|
import { connect } from "../types.js";
|
|
10
10
|
import { MemPage } from "../mem-page.js";
|
|
11
11
|
import { Engine, start, end, chainFlow, isFastForwardBlock, branchRoutes, runBranchRegression } from "../core.js";
|
|
12
|
+
import { withWebServer } from "../webserver.js";
|
|
13
|
+
import { chromiumExecutablePath } from "../browser-path.js";
|
|
12
14
|
|
|
13
|
-
async function
|
|
15
|
+
async function runMain() {
|
|
14
16
|
const projectDir = process.argv[2];
|
|
15
17
|
const spec = process.argv[3];
|
|
16
18
|
const mem = new MemPage();
|
|
@@ -285,11 +287,7 @@ async function main() {
|
|
|
285
287
|
// launched at Chromium's own default size/position, which stayed put
|
|
286
288
|
// where it was for a previous, larger monitor and looked chopped off on
|
|
287
289
|
// a smaller one. Maximizing fills whatever screen it's actually on.
|
|
288
|
-
|
|
289
|
-
// system/Flatpak Chromium when set, otherwise Playwright's bundled build.
|
|
290
|
-
// Without this, STEP mode always launched a different-looking browser than
|
|
291
|
-
// headed Engine runs / waygraph-demo.mjs (which already resolve Flatpak).
|
|
292
|
-
const executablePath = process.env.CHROME_PATH || process.env.CHROMIUM_PATH || undefined;
|
|
290
|
+
const executablePath = chromiumExecutablePath();
|
|
293
291
|
// Maximized for interactive step, and for fixed video viewport so the
|
|
294
292
|
// locked record size can actually fit (otherwise .webm gets grey pad).
|
|
295
293
|
const browser = await chromium.launch({
|
|
@@ -446,6 +444,12 @@ async function runAllBranchesMode(chainFlows, mem, baseURL, headed, engine) {
|
|
|
446
444
|
void engine;
|
|
447
445
|
}
|
|
448
446
|
|
|
447
|
+
// Here, not in the host CLI: importing playwright.config loads the project's own @playwright/test,
|
|
448
|
+
// which would collide with the CLI's copy.
|
|
449
|
+
async function main() {
|
|
450
|
+
await withWebServer(process.argv[2], runMain);
|
|
451
|
+
}
|
|
452
|
+
|
|
449
453
|
export function startRunner() {
|
|
450
454
|
main().catch((err) => {
|
|
451
455
|
console.error(err && err.stack ? err.stack : String(err));
|
|
@@ -6,6 +6,8 @@ import { MemPage } from "../mem-page.js";
|
|
|
6
6
|
import { buildExploreContext, buildExploreMenu, } from "./auto-explore.js";
|
|
7
7
|
import { installDemoChrome, instrumentInteractionHighlighting } from "./step-overlay.js";
|
|
8
8
|
import { resolveBaseUrl } from "../config.js";
|
|
9
|
+
import { withWebServer } from "../webserver.js";
|
|
10
|
+
import { chromiumExecutablePath } from "../browser-path.js";
|
|
9
11
|
/** See `../config.js`'s own `resolveBaseUrl` - re-exported so existing importers of this module
|
|
10
12
|
* don't need to change their import path. */
|
|
11
13
|
export { resolveBaseUrl };
|
|
@@ -540,7 +542,13 @@ function printCliMenu(menu, library) {
|
|
|
540
542
|
}
|
|
541
543
|
async function cliPick(menu, rl) {
|
|
542
544
|
while (true) {
|
|
543
|
-
|
|
545
|
+
let ans;
|
|
546
|
+
try {
|
|
547
|
+
ans = (await rl.question("Choose: ")).trim().toLowerCase();
|
|
548
|
+
}
|
|
549
|
+
catch {
|
|
550
|
+
return { type: "quit" }; // stdin ended (piped / Ctrl-D) - same as q
|
|
551
|
+
}
|
|
544
552
|
if (ans === "q" || ans === "quit")
|
|
545
553
|
return { type: "quit" };
|
|
546
554
|
const n = Number(ans);
|
|
@@ -554,6 +562,9 @@ async function cliPick(menu, rl) {
|
|
|
554
562
|
* Interactive waygraph auto: locate current Checkpoint, list runnable Blocks, pick one, repeat.
|
|
555
563
|
*/
|
|
556
564
|
export async function runAutoExplore(projectDir, options = {}) {
|
|
565
|
+
await withWebServer(projectDir, () => runAutoExploreCore(projectDir, options));
|
|
566
|
+
}
|
|
567
|
+
async function runAutoExploreCore(projectDir, options = {}) {
|
|
557
568
|
lastRunNote = null;
|
|
558
569
|
const cli = options.cli === true;
|
|
559
570
|
const baseURL = options.baseURL ?? (await resolveBaseUrl(projectDir)) ?? process.env.WAYGRAPH_BASE_URL;
|
|
@@ -567,7 +578,7 @@ export async function runAutoExplore(projectDir, options = {}) {
|
|
|
567
578
|
seedDefaultMem(library.byName, mem);
|
|
568
579
|
const engine = cli ? new Engine({ headless: true }) : new Engine({ headless: false, slowMo: 250 });
|
|
569
580
|
const { chromium } = await import("@playwright/test");
|
|
570
|
-
const executablePath =
|
|
581
|
+
const executablePath = chromiumExecutablePath();
|
|
571
582
|
const launchOpts = {
|
|
572
583
|
headless: cli,
|
|
573
584
|
args: cli ? [] : ["--start-maximized"],
|
package/dist/traverse/run.js
CHANGED
|
@@ -5,6 +5,7 @@ import { defaultMemValueForKey } from "../session/auto-explore-run.js";
|
|
|
5
5
|
import { resolveBaseUrl } from "../config.js";
|
|
6
6
|
import { EdgeLeaseCoordinator } from "./lease.js";
|
|
7
7
|
import { buildCoverageReport, collectGraphEdgeKeys, defaultCoverageOutPath, formatCoverageLine, writeCoverageReport, } from "./coverage.js";
|
|
8
|
+
import { chromiumExecutablePath } from "../browser-path.js";
|
|
8
9
|
function seedMem(library, mem, dataJson) {
|
|
9
10
|
const raw = dataJson ?? process.env.WAYGRAPH_DATA ?? process.env.WAYGRAPH_AUTO_MEM;
|
|
10
11
|
let envParsed = {};
|
|
@@ -253,7 +254,7 @@ export async function runTraverse(projectDir, options = {}) {
|
|
|
253
254
|
const leases = new EdgeLeaseCoordinator({ projectDir, persist: parallel > 1 });
|
|
254
255
|
const engine = new Engine({ headless: !headed, slowMo: headed ? 100 : 0 });
|
|
255
256
|
const { chromium } = await import("@playwright/test");
|
|
256
|
-
const executablePath =
|
|
257
|
+
const executablePath = chromiumExecutablePath();
|
|
257
258
|
const launchOpts = {
|
|
258
259
|
headless: !headed,
|
|
259
260
|
};
|
package/dist/types.d.ts
CHANGED
|
@@ -284,15 +284,12 @@ export type DefinedBlock<In extends Checkpoint<string>, Out extends Checkpoint<s
|
|
|
284
284
|
*/
|
|
285
285
|
stubBefore(stub: import("./highlights.js").HighlightStubPhase): DefinedBlock<In, Out>;
|
|
286
286
|
stubBefore(stub: import("./highlights.js").StubLifecycleFn<Out>): DefinedBlock<In, Out>;
|
|
287
|
-
stubBefore(stub: (out: Out) => import("./highlights.js").HighlightStubPhase): DefinedBlock<In, Out>;
|
|
288
287
|
/** Demo narration after resolve. Prefer ctx callbacks over slot-map objects. */
|
|
289
288
|
stubAfter(stub: import("./highlights.js").HighlightStubPhase): DefinedBlock<In, Out>;
|
|
290
289
|
stubAfter(stub: import("./highlights.js").StubLifecycleFn<Out>): DefinedBlock<In, Out>;
|
|
291
|
-
stubAfter(stub: (out: Out) => import("./highlights.js").HighlightStubPhase): DefinedBlock<In, Out>;
|
|
292
290
|
/** Demo narration when the step fails / expected-failure path. */
|
|
293
291
|
stubOnError(stub: import("./highlights.js").HighlightStubPhase): DefinedBlock<In, Out>;
|
|
294
292
|
stubOnError(stub: import("./highlights.js").StubLifecycleFn<Out>): DefinedBlock<In, Out>;
|
|
295
|
-
stubOnError(stub: (out: Out) => import("./highlights.js").HighlightStubPhase): DefinedBlock<In, Out>;
|
|
296
293
|
};
|
|
297
294
|
/**
|
|
298
295
|
* Structural (not imported) twin of `engine.ts`'s `Layout` - `types.ts` sits
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** The subset of Playwright's `TestConfigWebServer` this drives - same field names. */
|
|
2
|
+
export interface WebServerConfig {
|
|
3
|
+
command: string;
|
|
4
|
+
cwd?: string;
|
|
5
|
+
env?: Record<string, string>;
|
|
6
|
+
port?: number;
|
|
7
|
+
url?: string;
|
|
8
|
+
reuseExistingServer?: boolean;
|
|
9
|
+
timeout?: number;
|
|
10
|
+
stdout?: "pipe" | "ignore";
|
|
11
|
+
stderr?: "pipe" | "ignore";
|
|
12
|
+
}
|
|
13
|
+
/** Runs `fn` with the project's `webServer` (if any) up; only servers this call started get stopped. */
|
|
14
|
+
export declare function withWebServer<T>(projectDir: string, fn: () => Promise<T>): Promise<T>;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// Starts/stops a project's own playwright.config `webServer` around `waygraph run`/`demo`/`auto`,
|
|
2
|
+
// the same block `waygraph test` already honors.
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { pathToFileURL } from "node:url";
|
|
6
|
+
import { spawn } from "node:child_process";
|
|
7
|
+
const CONFIG_FILES = [
|
|
8
|
+
"playwright.config.ts",
|
|
9
|
+
"playwright.config.mts",
|
|
10
|
+
"playwright.config.mjs",
|
|
11
|
+
"playwright.config.js",
|
|
12
|
+
"playwright.config.cjs",
|
|
13
|
+
];
|
|
14
|
+
async function loadWebServerConfigs(projectDir) {
|
|
15
|
+
for (const name of CONFIG_FILES) {
|
|
16
|
+
const p = join(projectDir, name);
|
|
17
|
+
if (!existsSync(p))
|
|
18
|
+
continue;
|
|
19
|
+
let mod;
|
|
20
|
+
try {
|
|
21
|
+
mod = (await import(pathToFileURL(p).href));
|
|
22
|
+
}
|
|
23
|
+
catch (err) {
|
|
24
|
+
throw new Error(`waygraph: failed to load ${name}: ${err instanceof Error ? err.message : String(err)}`);
|
|
25
|
+
}
|
|
26
|
+
const webServer = mod.default?.webServer;
|
|
27
|
+
if (!webServer)
|
|
28
|
+
return [];
|
|
29
|
+
return Array.isArray(webServer) ? webServer : [webServer];
|
|
30
|
+
}
|
|
31
|
+
return [];
|
|
32
|
+
}
|
|
33
|
+
async function isUp(target) {
|
|
34
|
+
try {
|
|
35
|
+
return (await fetch(target)).status < 500;
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async function waitUntilUp(target, timeoutMs) {
|
|
42
|
+
const start = Date.now();
|
|
43
|
+
while (Date.now() - start < timeoutMs) {
|
|
44
|
+
if (await isUp(target))
|
|
45
|
+
return;
|
|
46
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
47
|
+
}
|
|
48
|
+
throw new Error(`waygraph: webServer "${target}" not ready after ${timeoutMs}ms`);
|
|
49
|
+
}
|
|
50
|
+
async function startWebServers(configs, projectDir) {
|
|
51
|
+
const started = [];
|
|
52
|
+
for (const cfg of configs) {
|
|
53
|
+
const target = cfg.url ?? (cfg.port ? `http://localhost:${cfg.port}` : undefined);
|
|
54
|
+
if (!target)
|
|
55
|
+
throw new Error(`waygraph: webServer needs "url" or "port"`);
|
|
56
|
+
if (cfg.reuseExistingServer !== false && (await isUp(target)))
|
|
57
|
+
continue;
|
|
58
|
+
// detached = own process group, so stop() kills the shell AND whatever it exec'd.
|
|
59
|
+
const child = spawn(cfg.command, {
|
|
60
|
+
shell: true,
|
|
61
|
+
detached: true,
|
|
62
|
+
cwd: cfg.cwd ? join(projectDir, cfg.cwd) : projectDir,
|
|
63
|
+
env: { ...process.env, ...cfg.env },
|
|
64
|
+
stdio: ["ignore", cfg.stdout === "pipe" ? "inherit" : "ignore", cfg.stderr === "ignore" ? "ignore" : "inherit"],
|
|
65
|
+
});
|
|
66
|
+
started.push(child);
|
|
67
|
+
await waitUntilUp(target, cfg.timeout ?? 60_000);
|
|
68
|
+
}
|
|
69
|
+
return started;
|
|
70
|
+
}
|
|
71
|
+
function stopWebServers(started) {
|
|
72
|
+
for (const child of started) {
|
|
73
|
+
try {
|
|
74
|
+
if (typeof child.pid === "number")
|
|
75
|
+
process.kill(-child.pid, "SIGTERM");
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
/* already exited */
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/** Runs `fn` with the project's `webServer` (if any) up; only servers this call started get stopped. */
|
|
83
|
+
export async function withWebServer(projectDir, fn) {
|
|
84
|
+
const started = await startWebServers(await loadWebServerConfigs(projectDir), projectDir);
|
|
85
|
+
try {
|
|
86
|
+
return await fn();
|
|
87
|
+
}
|
|
88
|
+
finally {
|
|
89
|
+
stopWebServers(started);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
"description": "Waygraph Map folder convention proof - (group)/<page>/page.block.ts + nav.block.ts + methods/*.block.ts, offline fixture, zero new engine code.",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"typecheck": "tsc --noEmit",
|
|
9
|
-
"test": "
|
|
9
|
+
"test": "playwright test",
|
|
10
10
|
"fixture": "node scripts/fixture-server.mjs",
|
|
11
|
-
"fixture:test": "node scripts/with-fixture.mjs npx playwright test",
|
|
12
11
|
"graph": "waygraph graph",
|
|
13
|
-
"
|
|
12
|
+
"map": "waygraph map",
|
|
13
|
+
"auto:cli": "waygraph auto --cli"
|
|
14
14
|
},
|
|
15
15
|
"waygraph": {
|
|
16
16
|
"baseUrl": "http://127.0.0.1:4277"
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { defineConfig } from "@playwright/test";
|
|
2
|
-
|
|
3
|
-
const PORT = process.env.WAYGRAPH_FIXTURE_PORT || "4277";
|
|
4
|
-
const HOST = process.env.WAYGRAPH_FIXTURE_HOST || "127.0.0.1";
|
|
2
|
+
import { chromiumExecutablePath } from "waygraph";
|
|
5
3
|
|
|
6
4
|
export default defineConfig({
|
|
7
5
|
testDir: "./tests",
|
|
@@ -9,13 +7,15 @@ export default defineConfig({
|
|
|
9
7
|
workers: 1,
|
|
10
8
|
timeout: 30_000,
|
|
11
9
|
reporter: [["list"], ["html", { open: "never" }]],
|
|
10
|
+
webServer: {
|
|
11
|
+
command: "node scripts/fixture-server.mjs",
|
|
12
|
+
url: "http://127.0.0.1:4277/dashboard",
|
|
13
|
+
reuseExistingServer: !process.env.CI,
|
|
14
|
+
},
|
|
12
15
|
use: {
|
|
13
16
|
headless: true,
|
|
14
|
-
baseURL:
|
|
17
|
+
baseURL: "http://127.0.0.1:4277",
|
|
15
18
|
trace: "retain-on-failure",
|
|
16
|
-
launchOptions: {
|
|
17
|
-
executablePath: process.env.CHROME_PATH || process.env.CHROMIUM_PATH,
|
|
18
|
-
args: ["--no-sandbox", "--disable-dev-shm-usage"],
|
|
19
|
-
},
|
|
19
|
+
launchOptions: { executablePath: chromiumExecutablePath() },
|
|
20
20
|
},
|
|
21
21
|
});
|
|
@@ -1,37 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
* Tiny static server for this example's offline fixture pages.
|
|
4
|
-
* Mirrors templates/scaffold's own scripts/fixture-server.mjs exactly.
|
|
5
|
-
*/
|
|
1
|
+
// Stands in for this example's real app: serves src/pages/<name>.html at clean URLs (/dashboard, /docs).
|
|
2
|
+
// Started and stopped by playwright.config.ts's webServer - waygraph run/demo/auto/test all honor it.
|
|
6
3
|
import { createServer } from "node:http";
|
|
7
4
|
import { readFileSync, existsSync } from "node:fs";
|
|
8
|
-
import { join
|
|
9
|
-
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { join } from "node:path";
|
|
10
6
|
|
|
11
|
-
const
|
|
12
|
-
const PORT = Number(process.env.WAYGRAPH_FIXTURE_PORT || 4277);
|
|
13
|
-
const HOST = process.env.WAYGRAPH_FIXTURE_HOST || "127.0.0.1";
|
|
7
|
+
const PAGES = join(import.meta.dirname, "../src/pages");
|
|
14
8
|
|
|
15
|
-
|
|
16
|
-
".
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const rel = raw === "/" ? "dashboard.html" : raw.replace(/^\//, "");
|
|
22
|
-
const full = normalize(join(ROOT, rel));
|
|
23
|
-
if (!full.startsWith(ROOT) || !existsSync(full)) {
|
|
24
|
-
res.writeHead(404, { "content-type": "text/plain" });
|
|
25
|
-
res.end("not found");
|
|
9
|
+
createServer((req, res) => {
|
|
10
|
+
const path = (req.url || "/").split("?")[0];
|
|
11
|
+
const name = path === "/" ? "dashboard" : path.slice(1);
|
|
12
|
+
const file = join(PAGES, `${name}.html`);
|
|
13
|
+
if (!/^[a-z-]+$/.test(name) || !existsSync(file)) {
|
|
14
|
+
res.writeHead(404).end("not found");
|
|
26
15
|
return;
|
|
27
16
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
res.end(readFileSync(full));
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
server.listen(PORT, HOST, () => {
|
|
34
|
-
if (process.env.WAYGRAPH_FIXTURE_QUIET !== "1") {
|
|
35
|
-
console.error(`waygraph fixture: http://${HOST}:${PORT}/dashboard.html`);
|
|
36
|
-
}
|
|
37
|
-
});
|
|
17
|
+
res.writeHead(200, { "content-type": "text/html; charset=utf-8" }).end(readFileSync(file));
|
|
18
|
+
}).listen(4277, "127.0.0.1");
|