@shivaedev/test-story 0.7.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +42 -29
  3. package/dist/server/domEnvironment.config.js +1 -1
  4. package/dist/server/domEnvironment.config.js.map +1 -1
  5. package/dist/server/internal/installOutbound.d.ts +2 -0
  6. package/dist/server/internal/installOutbound.d.ts.map +1 -0
  7. package/dist/server/internal/{routeOutbound.js → installOutbound.js} +1 -5
  8. package/dist/server/internal/installOutbound.js.map +1 -0
  9. package/dist/server/internal/screenElements.d.ts +9 -0
  10. package/dist/server/internal/screenElements.d.ts.map +1 -0
  11. package/dist/server/internal/screenElements.js +61 -0
  12. package/dist/server/internal/screenElements.js.map +1 -0
  13. package/dist/server/internal/start.d.ts.map +1 -1
  14. package/dist/server/internal/start.js +4 -1
  15. package/dist/server/internal/start.js.map +1 -1
  16. package/dist/server/internal/storyIt.d.ts.map +1 -1
  17. package/dist/server/internal/storyIt.js +1 -1
  18. package/dist/server/internal/storyIt.js.map +1 -1
  19. package/dist/server/{internal/routeOutbound.d.ts → routeOutbound.d.ts} +0 -1
  20. package/dist/server/routeOutbound.d.ts.map +1 -0
  21. package/dist/server/routeOutbound.js +6 -0
  22. package/dist/server/routeOutbound.js.map +1 -0
  23. package/dist/server/screenDriver.d.ts +24 -0
  24. package/dist/server/screenDriver.d.ts.map +1 -0
  25. package/dist/server/screenDriver.js +60 -0
  26. package/dist/server/screenDriver.js.map +1 -0
  27. package/dist/server/storyKit.d.ts +3 -3
  28. package/dist/server/storyKit.d.ts.map +1 -1
  29. package/package.json +5 -6
  30. package/src/server/domEnvironment.config.ts +1 -1
  31. package/src/server/internal/{routeOutbound.ts → installOutbound.ts} +0 -8
  32. package/src/server/internal/screenElements.ts +62 -0
  33. package/src/server/internal/start.ts +9 -1
  34. package/src/server/internal/storyIt.ts +1 -1
  35. package/src/server/routeOutbound.ts +9 -0
  36. package/src/server/screenDriver.ts +75 -0
  37. package/src/server/storyKit.ts +5 -5
  38. package/dist/server/internal/routeOutbound.d.ts.map +0 -1
  39. package/dist/server/internal/routeOutbound.js.map +0 -1
  40. package/docs/north-star.md +0 -35
  41. package/docs/roadmap.md +0 -26
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.8.0 - 2026-10-18
4
+
5
+ ### Added
6
+
7
+ - `screenDriver(options).accessible(selector)` returns and narrates an element's computed accessible name and role, including label references that take precedence over `aria-label`.
8
+ - Export `screenDriver(options)`, `ScreenDriverOptions` and `ScreenDriver` from `screenDriver.ts`: narrated DOM clicks, text entry, form submission and screen readouts, with settlement driven by the app's pending signal and an optional renderer `act` adapter. Screens use the existing DOM transport to reach fake HTTP services, including identity providers.
9
+ - Screen drivers accept a root getter for document navigation and a per-call `settle({ timeoutMs })` limit.
10
+ - Export `routeOutbound(routes)` from `routeOutbound.ts` to scope outbound routing alongside a story's fake HTTP service.
11
+ - Screen actions and readouts reject hidden targets and targets inside hidden ancestors; form submission also refuses inert ancestors.
12
+ - Accept `stages: []` in `storyKit` definitions for engines initialized entirely in `create`, preserving inferred engine and verb types with no available trait stages.
13
+
3
14
  ## 0.7.1 - 2026-10-18
4
15
 
5
16
  ### Fixed
package/README.md CHANGED
@@ -166,7 +166,9 @@ const app = storyKit({
166
166
 
167
167
  `appDefinition` holds the application's kit hooks, and `fakeUrl` is the listening fake server's HTTP or HTTPS origin, such as `http://127.0.0.1:4321`. The map matches exact URL hostnames, across ports. It replaces the destination origin while keeping the request's path, query, method, headers and body. For example, a POST to `https://github.com/login/oauth/access_token` reaches the fake's `/login/oauth/access_token`. In Node stories, other hostnames pass through the previous dispatcher unchanged. In the DOM environment, only loopback hosts (`localhost`, IPv4 loopback addresses and `[::1]`) may pass through without a route; every other hostname must have an `outbound` fake. A refused request fails the story and names its hostname, even when application code catches the fetch error.
168
168
 
169
- Routing uses the global dispatcher that Node's built-in `fetch` already uses. It is installed before `around`, creation, traits and the body, stays active during scoped cleanup, and restores the previous dispatcher after each story, including a failing story. Stories within one worker must run one at a time because that dispatcher is shared; parallelism belongs between workers or inside one story. The DOM environment uses the same routing for host-side Node fetch and document requests, including redirect destinations. It refuses external hosts even when the kit omits `outbound`.
169
+ `routeOutbound(routes)` from `@shivaedev/test-story/routeOutbound.ts` installs the same routing in the current Effect Scope. Acquire a `fakeHttpService` in `create`, then yield `routeOutbound({ "api.example.com": api.url })` so the fake listener and its routing belong to that story. The starter's social sign-in story exercises this path through both document navigation and host-side requests.
170
+
171
+ Routing uses the global dispatcher that Node's built-in `fetch` already uses. The kit's `outbound` option installs routing before `around`, creation, traits and the body, stays active during scoped cleanup, and restores the previous dispatcher after each story, including a failing story. Stories within one worker must run one at a time because that dispatcher is shared; parallelism belongs between workers or inside one story. The DOM environment uses the same routing for host-side Node fetch and document requests, including redirect destinations. It refuses external hosts even when the kit omits `outbound`.
170
172
 
171
173
  #### Asserting on application traces
172
174
 
@@ -229,7 +231,7 @@ app.it("a request continues its supplied trace", [], function* ({ request, reque
229
231
  });
230
232
  ```
231
233
 
232
- The package's [tracing kit](https://github.com/ShivaeDev/platform/blob/main/packages/test-story/src/test-support/tracingApp.ts) and [stories](https://github.com/ShivaeDev/platform/blob/main/packages/test-story/src/server/hostTracing.spec.ts) also assert that two requests have different trace IDs, request work stays under its request span, and traits and engine steps stay under the story span. The [after-hook stories](https://github.com/ShivaeDev/platform/blob/main/packages/test-story/src/server/afterHostTracing.spec.ts) boot a loopback HTTP host after deployment and check its startup, requests and cleanup against the story trace, while its request verb remains a child of the story span. Detachment only removes the incoming parent: spans that application startup explicitly creates still follow native Effect semantics.
234
+ Detachment only removes the incoming parent: spans that application startup explicitly creates still follow native Effect semantics.
233
235
 
234
236
  #### Reading OTLP exports
235
237
 
@@ -282,8 +284,6 @@ const user = yield* Fiber.join(pending);
282
284
 
283
285
  A `pages` route accepts a one-based `?page=` query and returns `{ items, next }`, with `next: null` on the last page. No query means page 1; a page past the end returns an empty list; a non-positive or non-integer page gets 400. `api.requests` reads a snapshot of the request log, including rejected and held requests, with `method`, `path` (including query), raw `body` Buffer, `headers`, `params` and `query`.
284
286
 
285
- The [fake HTTP stories](https://github.com/ShivaeDev/platform/blob/main/packages/test-story/src/server/outboundApi.spec.ts) use Node fetch to check params, credentials, pages, one-shot failure, hold/release ordering, request logs, narration and listener cleanup.
286
-
287
287
  ### 2. Once per feature: traits and verbs
288
288
 
289
289
  A trait is a line and a change, tagged with a stage:
@@ -398,7 +398,7 @@ A library package has an engine too: its own services or Layer under test. Keep
398
398
 
399
399
  The [`backfill` kit](https://github.com/ShivaeDev/platform/blob/main/packages/effect-test-sql/src/test-support/migrationStory.ts) in `effect-test-sql` is a library example. Its `create` returns the package's `migrationSteps(migrations)` API, its worker Layer provides PostgreSQL, and `around: withIsolatedDatabase` isolates each story. The `oldSchema` and `existingContacts` traits put contacts with email addresses into the old schema; the `backfill` verb calls `steps.migrateToLatest`. Its [story](https://github.com/ShivaeDev/platform/blob/main/packages/effect-test-sql/src/server/migrationStory.spec.ts) proves that those existing addresses survive the migration into a new table. It runs only when `PLATFORM_EFFECT_TEST_SQL_TEST_DATABASE_URL` is configured; a skipped story proves nothing.
400
400
 
401
- A fake belongs only at a true external boundary, wired in `create`; keep the package's own engine real. The [resume kit](https://github.com/ShivaeDev/platform/blob/main/packages/effect-contract/src/test-support/resumeStory.ts), for example, creates synthetic browser and native event sources while running the package's real `resumeSignal` API. Its [stories](https://github.com/ShivaeDev/platform/blob/main/packages/effect-contract/src/resume.dom.test.ts) exercise refresh on those events and listener cleanup. Those synthetic sources prove the package's response to events, not a physical browser or native application's event delivery.
401
+ A fake belongs only at a true external boundary, wired in `create`; keep the package's own engine real. The [resume kit](https://github.com/ShivaeDev/platform/blob/main/packages/effect-contract/src/test-support/resumeStory.ts), for example, creates synthetic browser and native event sources while running the package's real `resumeSignal` API.
402
402
 
403
403
  ### Whole-stack application kits
404
404
 
@@ -406,7 +406,7 @@ Keep one kit in the application’s `test-support/`. `effect-test` owns Vitest r
406
406
 
407
407
  Set `runIf: hasPostgres` in the kit definition to gate all its stories once, where `hasPostgres` is a boolean such as `process.env.PLATFORM_EFFECT_SQL_TEST_DATABASE_URL !== undefined`. When false, `it`, `it.fails`, `it.only`, `it.skip`, `it.runIf` and `it.skipIf` all register skipped stories without acquiring the worker Layer or running `around`, creation, traits or bodies. A skipped `it.only` does not focus the file. When true or omitted, each variant keeps its usual Vitest behavior, including explicit skips and `fails` inverting a failure. Per-story conditions can skip more stories; they cannot enable a disabled kit. The engine, traits, verbs and services remain inferred from the definition.
408
408
 
409
- The [order feature kit](https://github.com/ShivaeDev/platform/tree/main/packages/effect-react/src/test-support/order-example) runs the existing feature’s services, repository, contracts, JSON serialization and authentication middleware over a loopback HTTP listener. Its [stories](https://github.com/ShivaeDev/platform/blob/main/packages/effect-react/src/orderStory.dom.spec.tsx) test visible commits through a separate PostgreSQL pool, rollback of a rejected write without publication, cross-owner rejection, a native React action refreshing a list, and an editor retaining rejected input before a corrected save.
409
+ The [order feature kit](https://github.com/ShivaeDev/platform/tree/main/packages/effect-react/src/test-support/order-example) is an example: it runs the feature’s services, repository, contracts, JSON serialization and authentication middleware over a loopback HTTP listener with bearer tokens.
410
410
 
411
411
  For full-app stories, use `around: withIsolatedDatabase` from `@shivaedev/effect-test-sql/withIsolatedDatabase.ts` with a PostgreSQL test layer prepared from the application's migrations. Each story gets a database cloned from that template, and HTTP and worker pools commit into the same clone. The clone is dropped after scoped hosts and pools close. The starter's [application kit](https://github.com/ShivaeDev/platform/blob/main/examples/starter/src/test-support/application.ts) uses this isolation path.
412
412
 
@@ -414,7 +414,7 @@ For repository-level tests on a migrated template, `withTestTransaction` from `@
414
414
 
415
415
  React screen traits acquire roots in Scope and use a fresh native atom registry for each screen. Cleanup unmounts roots before disposing registries and servers. Screen verbs dispatch DOM events and use bounded observations of rendered output. Select a live clock once on an HTTP/DOM kit; keep TestClock for deterministic local stories. `runUntil` is for engines with a meaningful step hook, not HTTP or DOM polling. Creation forms can use the same pattern with the existing `useCreate` path.
416
416
 
417
- The order example proves DOM and loopback HTTP behavior with bearer tokens. For cookie sessions, use the DOM host setup below. These fixtures do not prove browser networking, SSR, mobile or a deployed proxy. Native `RpcTest` can exercise handlers in faster local stories, but omits serialization and transport. Failure inspection is synchronous: keep redacted observed values in the engine instead of trying to query PostgreSQL inside `inspect`.
417
+ For cookie sessions, use the DOM host setup below. Native `RpcTest` can exercise handlers in faster local stories, but omits serialization and transport. Failure inspection is synchronous: keep redacted observed values in the engine instead of trying to query PostgreSQL inside `inspect`.
418
418
 
419
419
  ### DOM stories with cookie sessions
420
420
 
@@ -463,37 +463,48 @@ const cookieApp = storyKit({
463
463
 
464
464
  Happy-dom's detached window records a location change without loading the next document. `domNavigate(url = window.location.href)` from `@shivaedev/test-story/domNavigate.ts` performs that load: it follows HTTP redirects through the document transport, keeps cookies for each destination, sets the final location, writes the returned HTML and returns the happy-dom response. Call it after the sign-in client has set the provider location, and before checking the returned page. An unrouted external redirect fails with its hostname.
465
465
 
466
- The starter's [social application kit](https://github.com/ShivaeDev/platform/blob/main/examples/starter/src/test-support/socialApp.ts) runs a fixture Better Auth host on real PostgreSQL, with a rendered sign-in button and a fake GitHub provider. Its `outbound` map routes both `github.com` and `api.github.com` to the fake's loopback origin. The fake's authorize endpoint returns the application's callback URL with the received state and a test code. The real callback exchanges that code and fetches the user against the fake, creates the account and session in PostgreSQL, and redirects to the signed-in page.
466
+ The starter's [social application kit](https://github.com/ShivaeDev/platform/blob/main/examples/starter/src/test-support/socialApp.ts) runs a fixture Better Auth host on real PostgreSQL, with a rendered sign-in button and a fake GitHub provider. Its `create` hook acquires the provider and uses scoped `routeOutbound` routing for both `github.com` and `api.github.com`. The fake's authorize endpoint returns the application's callback URL with the received state and a test code. The real callback exchanges that code and fetches the user against the fake, creates the account and session in PostgreSQL, and redirects to the signed-in page.
467
467
 
468
- ```ts
469
- import { domNavigate } from "@shivaedev/test-story/domNavigate.ts";
468
+ The kit renders a Better Auth client whose `customFetchImpl` is `domFetch(baseUrl)`. The story calls `clickGitHubSignIn`, `settle` and `followRedirect` separately, then reads the heading, cookie and session. The screen driver settles on the screen's request state and reads the heading from the current document after navigation. The provider uses `fakeHttpService`. The authorize, token and user requests at the fake and a later session response provide evidence across the provider and application boundaries. The kit does not copy cookies into request headers.
470
469
 
471
- const socialApp = storyKit({
472
- ...socialDefinition,
473
- outbound: { "github.com": fakeUrl, "api.github.com": fakeUrl },
474
- verbs: (engine, story) => ({
475
- clickGitHubSignIn: () => Effect.promise(async () => {
476
- story.tell("Alice clicks Sign in with GitHub");
477
- await engine.screen.click();
478
- }),
479
- followRedirect: () => Effect.promise(() => domNavigate()),
480
- heading: () => document.querySelector("h1")?.textContent,
481
- session: () => Effect.promise(async () => (await engine.fetch("/api/auth/get-session")).json()),
482
- }),
483
- });
484
-
485
- socialApp.it("a social sign-in returns with a cookie session", [], function* ({ clickGitHubSignIn, followRedirect, heading, session }) {
470
+ ```ts
471
+ socialApp.it("a social sign-in returns with a cookie session", [], function* ({ clickGitHubSignIn, settle, followRedirect, heading, cookie, session }) {
486
472
  yield* clickGitHubSignIn();
487
- yield* followRedirect();
473
+ yield* settle();
474
+ const response = yield* followRedirect();
475
+ expect(response.status).toBe(200);
488
476
  expect(heading()).toBe("Signed in as alice@social.test");
477
+ expect(cookie()).not.toContain("session_token");
489
478
  expect(yield* session()).toMatchObject({ user: { email: "alice@social.test" } });
490
479
  });
491
480
  ```
492
481
 
493
- `socialDefinition` starts the host and renders the screen with a Better Auth client whose `customFetchImpl` is `domFetch(baseUrl)`. The authorize, token and user requests at the fake and a later session response provide evidence across the provider and application boundaries. It does not copy cookies into request headers.
494
-
495
482
  `domFetch` uses the current window and its cookie jar; it does not isolate multiple users. Run stories using that window serially, and let the application's cleanup end its sessions, restore the page location and close its host. Cookies follow hostnames, not listener ports, so a different loopback port alone does not isolate accounts.
496
483
 
484
+ ### Driving a screen
485
+
486
+ `screenDriver(options)` supplies DOM verbs and readouts for a kit's `verbs` hook. Give it the mounted `root` (or a getter for a root that navigation replaces), the story's `tell`, and a `pending()` function that reads the application's own request or atom state. `settle()` waits until that signal is false; repeated identical renders never count as completion. The application must keep the signal true until its resulting screen work is ready to render.
487
+
488
+ ```ts
489
+ import { screenDriver } from "@shivaedev/test-story/screenDriver.ts";
490
+
491
+ verbs: ({ view, requests }, story) => screenDriver({
492
+ root: view.container,
493
+ pending: () => requests.pending,
494
+ tell: story.tell,
495
+ })
496
+ ```
497
+
498
+ `click(selector)`, `enter(selector, value)` and `submit(selector = "form")` return Effects. Selectors identify exactly one descendant of the root; missing or ambiguous controls fail. Hidden targets and targets inside hidden ancestors refuse actions and readouts. Text entry focuses an input or textarea and dispatches input and change events. Disabled controls refuse clicks and entry, inert ancestors also prevent form submission, and read-only fields refuse entry. Actions do not wait for settlement, so a story can release a held request before calling `settle()`.
499
+
500
+ `text(selector?)` returns rendered text from the selected element or the whole root. `value(selector)` returns the current input or textarea value. Both narrate what they read through `tell` and leave assertions to the spec. Entry narration omits the supplied value.
501
+
502
+ `accessible(selector)` returns `{ name, role }` computed by `dom-accessibility-api`, including native roles and label references that take precedence over `aria-label`. It narrates the readout and uses the same single rendered target checks as other readouts. Assert on this result when checking a control's accessible name; reading its raw attributes does not compute that name. This DOM computation does not inspect a browser's accessibility tree or prove speech from a screen reader.
503
+
504
+ For React, pass `act: async (action) => { await act(action); }` using React's `act`. The adapter wraps each action and flushes renderer work before checking the pending signal, including while waiting for an asynchronous response. The [React driver stories](https://github.com/ShivaeDev/platform/blob/main/packages/effect-react/src/screenDriver.dom.spec.tsx) cover a native pending atom, a rendered response and a controlled field without React warnings. The driver itself has no renderer dependency.
505
+
506
+ Settlement has a live-time limit of 3 seconds, configurable with the driver's `timeoutMs` or per call with `settle({ timeoutMs })`, and fails with the current screen text and advice when that limit expires. Use the existing DOM environment and scoped `routeOutbound` routing to reach `fakeHttpService`; the driver does not install another transport. The [screen stories](src/server/screenSignals.dom.spec.ts) hold a real HTTP response across repeated renders and sign in by filling and submitting a form against a fake identity provider. These fixtures prove DOM interactions and loopback HTTP, not a browser or a production authentication system.
507
+
497
508
  ### API by module
498
509
 
499
510
  Import each module with the prefix `@shivaedev/test-story/`; there is no root entry.
@@ -502,6 +513,8 @@ Import each module with the prefix `@shivaedev/test-story/`; there is no root en
502
513
  | --- | --- |
503
514
  | `storyKit.ts` | `storyKit`, `Trait`, `RunUntilOptions`, `Story`, `RunHooks`, `StoryKitDefinition`, `Told`, `StoryBody`, `StoryTest`, `StoryIt`, `StoryKit` |
504
515
  | `domFetch.ts` | `domFetch(baseUrl)` |
516
+ | `routeOutbound.ts` | `routeOutbound(routes)` |
517
+ | `screenDriver.ts` | `screenDriver(options)`, `ScreenDriverOptions`, `ScreenDriver` |
505
518
  | `domNavigate.ts` | `domNavigate(url?)` |
506
519
  | `genreTags.ts` | `genreTags(...kitNames)`, `GenreTag` |
507
520
  | `domEnvironment.config.ts` | Default Vitest environment preserving Node host globals and happy-dom document transport |
@@ -517,7 +530,7 @@ pnpm add --save-dev @shivaedev/test-story @effect/vitest@4.0.4 effect@4.0.4 vite
517
530
  `@effect/vitest`, `effect` and `vitest` are peers, so the application's own versions run the stories.
518
531
 
519
532
  - The package runs inside Vitest. The story reaches the failure by rewriting the first error's message in Vitest's `onTestFailed` hook.
520
- - Layer acquisition and engine creation failures precede that hook and carry no story appendix. A printed rerun command still needs a Vitest configuration that collects its file; the intentional `failingStories.ts` examples use the package's explicit fixture runner.
533
+ - Layer acquisition and engine creation failures precede that hook and carry no story appendix. A printed rerun command still needs a Vitest configuration that collects its file.
521
534
  - A kit's `it` is created when the kit is defined, so a kit lives in a module that only Vitest test files import.
522
535
  - `inspect` runs after the test has failed, so it reads the engine synchronously.
523
536
  - The spec line under the `✗` is found by matching the spec's path in the failure's stack, or else in the call site of the last line the story told or the last `runUntil`. A failure raised inside an Effect that the spec does not call directly may have none.
@@ -7,7 +7,7 @@ const domEnvironment = {
7
7
  // Vitest loads environments outside the project's source resolution conditions.
8
8
  const load = createRequire(import.meta.url);
9
9
  const { documentTransport } = load("#internal/documentTransport.ts");
10
- const { installOutbound } = load("#internal/routeOutbound.ts");
10
+ const { installOutbound } = load("#internal/installOutbound.ts");
11
11
  const native = Object.fromEntries(["fetch", "AbortController", "AbortSignal", "Headers", "Request", "Response"].map((name) => [name, Reflect.get(global, name)]));
12
12
  const restoreOutbound = await installOutbound({}, true);
13
13
  const win = new GlobalWindow({
@@ -1 +1 @@
1
- {"version":3,"file":"domEnvironment.config.js","sourceRoot":"","sources":["../../src/server/domEnvironment.config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"domEnvironment.config.js","sourceRoot":"","sources":["../../src/server/domEnvironment.config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function installOutbound(routes: Readonly<Record<string, string>>, strict?: boolean): Promise<() => void>;
2
+ //# sourceMappingURL=installOutbound.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installOutbound.d.ts","sourceRoot":"","sources":["../../../src/server/internal/installOutbound.ts"],"names":[],"mappings":"AAeA,wBAAsB,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,UAAQ,uBAgD7F"}
@@ -1,5 +1,4 @@
1
1
  import { isIP } from "node:net";
2
- import { Effect } from "effect";
3
2
  import { unrouted } from "#internal/errors.ts";
4
3
  function isDispatcher(value) {
5
4
  return typeof value === "object" && value !== null && "dispatch" in value && typeof value.dispatch === "function";
@@ -52,7 +51,4 @@ export async function installOutbound(routes, strict = false) {
52
51
  }
53
52
  };
54
53
  }
55
- export function routeOutbound(routes) {
56
- return Effect.acquireRelease(Effect.promise(() => installOutbound(routes, Reflect.get(globalThis, Symbol.for("test-story.dom")) === true)), (restore) => Effect.sync(restore)).pipe(Effect.asVoid);
57
- }
58
- //# sourceMappingURL=routeOutbound.js.map
54
+ //# sourceMappingURL=installOutbound.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installOutbound.js","sourceRoot":"","sources":["../../../src/server/internal/installOutbound.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export declare function screenElements(root: () => HTMLElement): {
2
+ element: (selector: string) => HTMLElement;
3
+ enabled: (found: HTMLElement, selector: string) => void;
4
+ enter: (selector: string, value: string) => void;
5
+ form: (selector: string) => HTMLFormElement;
6
+ input: (selector: string) => HTMLInputElement | HTMLTextAreaElement;
7
+ rendered: (found: HTMLElement, selector: string) => HTMLElement;
8
+ };
9
+ //# sourceMappingURL=screenElements.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"screenElements.d.ts","sourceRoot":"","sources":["../../../src/server/internal/screenElements.ts"],"names":[],"mappings":"AAAA,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,WAAW;wBAa1B,MAAM;qBAiBT,WAAW,YAAY,MAAM;sBAQlC,MAAM,SAAS,MAAM;qBAYtB,MAAM;sBA3BC,MAAM;sBAtBN,WAAW,YAAY,MAAM;EA4DtD"}
@@ -0,0 +1,61 @@
1
+ export function screenElements(root) {
2
+ function rendered(found, selector) {
3
+ const visibility = getComputedStyle(found).visibility;
4
+ let hidden = visibility === "hidden" || visibility === "collapse";
5
+ for (let ancestor = found; ancestor; ancestor = ancestor.parentElement) {
6
+ const style = getComputedStyle(ancestor);
7
+ hidden ||= Boolean(ancestor.hidden) || style.display === "none" || style.contentVisibility === "hidden";
8
+ }
9
+ if (hidden) {
10
+ throw new Error(`The screen's ${selector} is not rendered.\nhelp: Reveal the target and its ancestors before acting on or reading it.`);
11
+ }
12
+ return found;
13
+ }
14
+ function element(selector) {
15
+ const matches = root().querySelectorAll(selector);
16
+ const found = matches[0];
17
+ if (matches.length !== 1 || found === undefined) {
18
+ throw new Error(`The screen has ${matches.length} matches for ${JSON.stringify(selector)}.\nhelp: Use a selector for exactly one rendered control or readout.`);
19
+ }
20
+ return rendered(found, selector);
21
+ }
22
+ function input(selector) {
23
+ const found = element(selector);
24
+ if (!(found instanceof HTMLInputElement || found instanceof HTMLTextAreaElement)) {
25
+ throw new Error(`The screen's ${selector} is not a text field.\nhelp: Select a rendered input or textarea to enter or read a value.`);
26
+ }
27
+ return found;
28
+ }
29
+ function enabled(found, selector) {
30
+ if (found.matches(":disabled") || found.closest("[inert]")) {
31
+ throw new Error(`The screen's ${selector} is disabled.\nhelp: Wait for the app to enable the control before acting on it.`);
32
+ }
33
+ }
34
+ return {
35
+ element,
36
+ enabled,
37
+ enter: (selector, value) => {
38
+ const field = input(selector);
39
+ enabled(field, selector);
40
+ if (field.readOnly) {
41
+ throw new Error(`The screen's ${selector} is read-only.\nhelp: Select an editable input or textarea.`);
42
+ }
43
+ field.focus();
44
+ const prototype = field instanceof HTMLInputElement ? HTMLInputElement.prototype : HTMLTextAreaElement.prototype;
45
+ Object.getOwnPropertyDescriptor(prototype, "value")?.set?.call(field, value);
46
+ field.dispatchEvent(new Event("input", { bubbles: true }));
47
+ field.dispatchEvent(new Event("change", { bubbles: true }));
48
+ },
49
+ form: (selector) => {
50
+ const found = element(selector);
51
+ if (!(found instanceof HTMLFormElement)) {
52
+ throw new Error(`The screen's ${selector} is not a form.\nhelp: Select a rendered form to submit.`);
53
+ }
54
+ enabled(found, selector);
55
+ return found;
56
+ },
57
+ input,
58
+ rendered,
59
+ };
60
+ }
61
+ //# sourceMappingURL=screenElements.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"screenElements.js","sourceRoot":"","sources":["../../../src/server/internal/screenElements.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,cAAc,CAAC,IAAuB;IACrD,SAAS,QAAQ,CAAC,KAAkB,EAAE,QAAgB;QACrD,MAAM,UAAU,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC;QACtD,IAAI,MAAM,GAAG,UAAU,KAAK,QAAQ,IAAI,UAAU,KAAK,UAAU,CAAC;QAClE,KAAK,IAAI,QAAQ,GAAuB,KAAK,EAAE,QAAQ,EAAE,QAAQ,GAAG,QAAQ,CAAC,aAAa,EAAE,CAAC;YAC5F,MAAM,KAAK,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;YACzC,MAAM,KAAK,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,OAAO,KAAK,MAAM,IAAI,KAAK,CAAC,iBAAiB,KAAK,QAAQ,CAAC;QACzG,CAAC;QACD,IAAI,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,gBAAgB,QAAQ,8FAA8F,CAAC,CAAC;QACzI,CAAC;QACD,OAAO,KAAK,CAAC;IACd,CAAC;IACD,SAAS,OAAO,CAAC,QAAgB;QAChC,MAAM,OAAO,GAAG,IAAI,EAAE,CAAC,gBAAgB,CAAc,QAAQ,CAAC,CAAC;QAC/D,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACzB,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACjD,MAAM,IAAI,KAAK,CACd,kBAAkB,OAAO,CAAC,MAAM,gBAAgB,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,sEAAsE,CAC9I,CAAC;QACH,CAAC;QACD,OAAO,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAClC,CAAC;IACD,SAAS,KAAK,CAAC,QAAgB;QAC9B,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;QAChC,IAAI,CAAC,CAAC,KAAK,YAAY,gBAAgB,IAAI,KAAK,YAAY,mBAAmB,CAAC,EAAE,CAAC;YAClF,MAAM,IAAI,KAAK,CAAC,gBAAgB,QAAQ,4FAA4F,CAAC,CAAC;QACvI,CAAC;QACD,OAAO,KAAK,CAAC;IACd,CAAC;IACD,SAAS,OAAO,CAAC,KAAkB,EAAE,QAAgB;QACpD,IAAI,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;YAC5D,MAAM,IAAI,KAAK,CAAC,gBAAgB,QAAQ,kFAAkF,CAAC,CAAC;QAC7H,CAAC;IACF,CAAC;IACD,OAAO;QACN,OAAO;QACP,OAAO;QACP,KAAK,EAAE,CAAC,QAAgB,EAAE,KAAa,EAAE,EAAE;YAC1C,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;YAC9B,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;YACzB,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACpB,MAAM,IAAI,KAAK,CAAC,gBAAgB,QAAQ,6DAA6D,CAAC,CAAC;YACxG,CAAC;YACD,KAAK,CAAC,KAAK,EAAE,CAAC;YACd,MAAM,SAAS,GAAG,KAAK,YAAY,gBAAgB,CAAC,CAAC,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC,mBAAmB,CAAC,SAAS,CAAC;YACjH,MAAM,CAAC,wBAAwB,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YAC7E,KAAK,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YAC3D,KAAK,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAC7D,CAAC;QACD,IAAI,EAAE,CAAC,QAAgB,EAAE,EAAE;YAC1B,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;YAChC,IAAI,CAAC,CAAC,KAAK,YAAY,eAAe,CAAC,EAAE,CAAC;gBACzC,MAAM,IAAI,KAAK,CAAC,gBAAgB,QAAQ,0DAA0D,CAAC,CAAC;YACrG,CAAC;YACD,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;YACzB,OAAO,KAAK,CAAC;QACd,CAAC;QACD,KAAK;QACL,QAAQ;KACR,CAAC;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../../src/server/internal/start.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,MAAM,EAAU,MAAM,QAAQ,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAK1C,OAAO,EAAE,KAAK,eAAe,EAAmB,KAAK,UAAU,EAAQ,MAAM,mBAAmB,CAAC;AAEjG,eAAO,MAAM,KAAK,iGAIJ,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,6CAkB/D,CAAC"}
1
+ {"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../../src/server/internal/start.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,MAAM,EAAU,MAAM,QAAQ,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAK1C,OAAO,EAAE,KAAK,eAAe,EAAmB,KAAK,UAAU,EAAQ,MAAM,mBAAmB,CAAC;AAEjG,eAAO,MAAM,KAAK,iGAIJ,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,6CA0B/D,CAAC"}
@@ -19,7 +19,10 @@ export const start = Effect.fnUntraced(function* (definition, given, context, bo
19
19
  },
20
20
  tell: narration.tell,
21
21
  };
22
- return yield* body({ ...definition.verbs(engine, story), story });
22
+ return yield* body(Object.defineProperties({}, {
23
+ ...Object.getOwnPropertyDescriptors(definition.verbs(engine, story)),
24
+ story: { enumerable: true, value: story },
25
+ }));
23
26
  }).pipe(Effect.tapCause((cause) => Effect.sync(() => captureFailure(Cause.prettyErrors(cause)[0]?.stack))));
24
27
  });
25
28
  //# sourceMappingURL=start.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"start.js","sourceRoot":"","sources":["../../../src/server/internal/start.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAExD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAA0D,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEjG,MAAM,CAAC,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EAC/C,UAA2B,EAC3B,KAA4B,EAC5B,OAAoB,EACpB,IAAgE;IAEhE,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAC5G,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,CAAC,OAAO,EAAE,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC;IACvH,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QACjC,KAAK,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;QAClD,MAAM,KAAK,GAAe;YACzB,MAAM;YACN,KAAK,EAAE,SAAS,CAAC,KAAK;YACtB,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;gBAC5B,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;gBACxB,SAAS,CAAC,EAAE,GAAG,IAAI,CAAC;gBACpB,OAAO,QAAQ,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,GAAG,EAAE,UAAU,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;YACvI,CAAC;YACD,IAAI,EAAE,SAAS,CAAC,IAAI;SACpB,CAAC;QACF,OAAO,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7G,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"start.js","sourceRoot":"","sources":["../../../src/server/internal/start.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAExD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAA0D,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEjG,MAAM,CAAC,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EAC/C,UAA2B,EAC3B,KAA4B,EAC5B,OAAoB,EACpB,IAAgE;IAEhE,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAC5G,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,CAAC,OAAO,EAAE,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC;IACvH,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QACjC,KAAK,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;QAClD,MAAM,KAAK,GAAe;YACzB,MAAM;YACN,KAAK,EAAE,SAAS,CAAC,KAAK;YACtB,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;gBAC5B,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;gBACxB,SAAS,CAAC,EAAE,GAAG,IAAI,CAAC;gBACpB,OAAO,QAAQ,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,GAAG,EAAE,UAAU,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;YACvI,CAAC;YACD,IAAI,EAAE,SAAS,CAAC,IAAI;SACpB,CAAC;QACF,OAAO,KAAK,CAAC,CAAC,IAAI,CACjB,MAAM,CAAC,gBAAgB,CACtB,EAAE,EACF;YACC,GAAG,MAAM,CAAC,yBAAyB,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YACpE,KAAK,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE;SACzC,CACD,CACD,CAAC;IACH,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7G,CAAC,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"storyIt.d.ts","sourceRoot":"","sources":["../../../src/server/internal/storyIt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,OAAO,KAAK,EAAc,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAGrF,OAAO,EAAE,KAAK,SAAS,EAAU,MAAM,qBAAqB,CAAC;AAE7D,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAGrE,KAAK,SAAS,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,KAAK,SAAS,CAAC,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,GAAG,SAAS,CAAC;AAE1G,KAAK,SAAS,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,UAAU,EAAE,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,iBAAiB,KAAK,IAAI,CAAC;AAE9H,MAAM,WAAW,OAAQ,SAAQ,SAAS;IACzC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,SAAS,CAAC;IAClD,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,SAAS,CAAC;CACnD;AAgCD,wBAAgB,OAAO,CAAC,UAAU,EAAE,eAAe,GAAG,OAAO,CA0B5D"}
1
+ {"version":3,"file":"storyIt.d.ts","sourceRoot":"","sources":["../../../src/server/internal/storyIt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,OAAO,KAAK,EAAc,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAGrF,OAAO,EAAE,KAAK,SAAS,EAAU,MAAM,qBAAqB,CAAC;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAIrE,KAAK,SAAS,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,KAAK,SAAS,CAAC,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,GAAG,SAAS,CAAC;AAE1G,KAAK,SAAS,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,UAAU,EAAE,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,iBAAiB,KAAK,IAAI,CAAC;AAE9H,MAAM,WAAW,OAAQ,SAAQ,SAAS;IACzC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,SAAS,CAAC;IAClD,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,SAAS,CAAC;CACnD;AAgCD,wBAAgB,OAAO,CAAC,UAAU,EAAE,eAAe,GAAG,OAAO,CA0B5D"}
@@ -2,8 +2,8 @@ import { Effect, Layer } from "effect";
2
2
  import { makeEffectIt } from "@shivaedev/effect-test/vitest.ts";
3
3
  import { genreOf } from "#internal/genre.ts";
4
4
  import { hooked } from "#internal/hooked.ts";
5
- import { routeOutbound } from "#internal/routeOutbound.ts";
6
5
  import { start } from "#internal/start.ts";
6
+ import { routeOutbound } from "#routeOutbound.ts";
7
7
  function withTags(options, tags) {
8
8
  if (typeof options === "number") {
9
9
  return { tags: [...tags], timeout: options };
@@ -1 +1 @@
1
- {"version":3,"file":"storyIt.js","sourceRoot":"","sources":["../../../src/server/internal/storyIt.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"storyIt.js","sourceRoot":"","sources":["../../../src/server/internal/storyIt.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAEvC,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAChE,OAAO,EAAc,OAAO,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAkB,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7D,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAclD,SAAS,QAAQ,CAAC,OAA+C,EAAE,IAAuB;IACzF,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QACjC,OAAO,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;IAC9C,CAAC;IACD,MAAM,GAAG,GAAG,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC;IAChC,OAAO,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,CAAC,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;AACpF,CAAC;AAED,SAAS,OAAO,CAAC,UAA2B,EAAE,KAA4B,EAAE,IAA2B;IACtG,OAAO,QAAQ,CAAC,CAAC,KAAK,CAAC,QAAiB,EAAE,OAAoB;QAC7D,OAAO,KAAK,CAAC,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAChG,CAAC,CAAC;AACH,CAAC;AAED,wHAAwH;AACxH,SAAS,SAAS,CAAC,UAA2B,EAAE,KAAY,EAAE,OAAqC;IAClG,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;QACrC,MAAM,KAAK,GAAG,GAAG,KAAK,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;QACxC,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QAC/C,IAAI,CAAC;YACJ,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC5D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC;gBAChF,MAAM,KAAK,CAAC;YACb,CAAC;YACD,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;QAC9C,CAAC;IACF,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,UAA2B;IAClD,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IACvC,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACjH,MAAM,EAAE,SAAS,EAAE,GAAG,YAAY,CAAC;QAClC,MAAM,EACL,QAAQ,KAAK,SAAS;YACrB,CAAC,CAAC,UAAU,CAAC,MAAM;YACnB,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CACX,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;gBACnB,KAAK,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;gBAC/B,OAAO,KAAK,CAAC,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC;YACrD,CAAC,CAAC;QACN,KAAK,EAAE,UAAU,CAAC,KAAK;QACvB,KAAK,EAAE,UAAU,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK;QACtC,WAAW,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI;KAC9B,CAAC,CAAC;IACH,SAAS,QAAQ,CAAC,OAAqC;QACtD,OAAO,SAAS,CAAC,UAAU,EAAE,KAAK,EAAE,UAAU,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IAC5F,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE;QACzC,KAAK,EAAE,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC;QAChC,IAAI,EAAE,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC;QAC9B,KAAK,EAAE,CAAC,SAAkB,EAAE,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACnE,IAAI,EAAE,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC;QAC9B,MAAM,EAAE,CAAC,SAAkB,EAAE,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;KACrE,CAAC,CAAC;AACJ,CAAC"}
@@ -1,4 +1,3 @@
1
1
  import { Effect } from "effect";
2
- export declare function installOutbound(routes: Readonly<Record<string, string>>, strict?: boolean): Promise<() => void>;
3
2
  export declare function routeOutbound(routes: Readonly<Record<string, string>>): Effect.Effect<void, never, import("effect/Scope").Scope>;
4
3
  //# sourceMappingURL=routeOutbound.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routeOutbound.d.ts","sourceRoot":"","sources":["../../src/server/routeOutbound.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGhC,wBAAgB,aAAa,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,4DAKrE"}
@@ -0,0 +1,6 @@
1
+ import { Effect } from "effect";
2
+ import { installOutbound } from "#internal/installOutbound.ts";
3
+ export function routeOutbound(routes) {
4
+ return Effect.acquireRelease(Effect.promise(() => installOutbound(routes, Reflect.get(globalThis, Symbol.for("test-story.dom")) === true)), (restore) => Effect.sync(restore)).pipe(Effect.asVoid);
5
+ }
6
+ //# sourceMappingURL=routeOutbound.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routeOutbound.js","sourceRoot":"","sources":["../../src/server/routeOutbound.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAE/D,MAAM,UAAU,aAAa,CAAC,MAAwC;IACrE,OAAO,MAAM,CAAC,cAAc,CAC3B,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,EAC7G,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CACjC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AACvB,CAAC"}
@@ -0,0 +1,24 @@
1
+ import { Effect } from "effect";
2
+ export interface ScreenDriverOptions {
3
+ readonly act?: (action: () => Promise<void>) => PromiseLike<void>;
4
+ readonly pending: () => boolean;
5
+ readonly root: HTMLElement | (() => HTMLElement);
6
+ readonly tell: (line: string) => void;
7
+ readonly timeoutMs?: number;
8
+ }
9
+ export type ScreenDriver = ReturnType<typeof screenDriver>;
10
+ export declare function screenDriver({ root, pending, tell, act, timeoutMs }: ScreenDriverOptions): {
11
+ accessible: (selector: string) => {
12
+ name: string;
13
+ role: string | null;
14
+ };
15
+ click: (selector: string) => Effect.Effect<void, never, never>;
16
+ enter: (selector: string, value: string) => Effect.Effect<void, never, never>;
17
+ settle: (options?: {
18
+ readonly timeoutMs?: number;
19
+ }) => Effect.Effect<void, never, never>;
20
+ submit: (selector?: string) => Effect.Effect<void, never, never>;
21
+ text: (selector?: string) => string;
22
+ value: (selector: string) => string;
23
+ };
24
+ //# sourceMappingURL=screenDriver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"screenDriver.d.ts","sourceRoot":"","sources":["../../src/server/screenDriver.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIhC,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,WAAW,CAAC,IAAI,CAAC,CAAC;IAClE,QAAQ,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,CAAC,MAAM,WAAW,CAAC,CAAC;IACjD,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AAE3D,wBAAgB,YAAY,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,GAA0B,EAAE,SAAgB,EAAE,EAAE,mBAAmB;2BAgC9F,MAAM;;;;sBAMX,MAAM;sBAON,MAAM,SAAS,MAAM;uBApCf;QAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE;;sBAuCrC,MAAM;sBAKN,MAAM;EAMzB"}
@@ -0,0 +1,60 @@
1
+ import { computeAccessibleName, getRole } from "dom-accessibility-api";
2
+ import { Effect } from "effect";
3
+ import { withLive } from "@shivaedev/effect-test/withLive.ts";
4
+ import { screenElements } from "#internal/screenElements.ts";
5
+ export function screenDriver({ root, pending, tell, act = (action) => action(), timeoutMs = 3000 }) {
6
+ const currentRoot = typeof root === "function" ? root : () => root;
7
+ const elements = screenElements(currentRoot);
8
+ function perform(line, action) {
9
+ return Effect.promise(async () => {
10
+ tell(line);
11
+ await act(async () => action());
12
+ });
13
+ }
14
+ function settle(options = {}) {
15
+ const limit = options.timeoutMs ?? timeoutMs;
16
+ const wait = Effect.gen(function* () {
17
+ tell("wait for the screen's pending work");
18
+ do {
19
+ yield* Effect.promise(() => act(async () => undefined));
20
+ if (!pending()) {
21
+ tell("the screen has no pending work");
22
+ return;
23
+ }
24
+ yield* Effect.promise(() => act(() => new Promise((resolve) => setTimeout(resolve, 10))));
25
+ } while (true);
26
+ });
27
+ function timedOut() {
28
+ return Effect.die(new Error(`The screen did not settle within ${limit}ms.\nhelp: Release held requests and check the app's pending signal and renderer act adapter.\nScreen: ${currentRoot().textContent}`));
29
+ }
30
+ return withLive(wait.pipe(Effect.timeoutOrElse({ duration: limit, orElse: timedOut })));
31
+ }
32
+ return {
33
+ accessible: (selector) => {
34
+ const element = elements.element(selector);
35
+ const accessible = { name: computeAccessibleName(element), role: getRole(element) };
36
+ tell(`read the accessibility of ${selector}: ${JSON.stringify(accessible)}`);
37
+ return accessible;
38
+ },
39
+ click: (selector) => perform(`click ${selector}`, () => {
40
+ const element = elements.element(selector);
41
+ elements.enabled(element, selector);
42
+ element.focus();
43
+ element.click();
44
+ }),
45
+ enter: (selector, value) => perform(`enter a value in ${selector}`, () => elements.enter(selector, value)),
46
+ settle,
47
+ submit: (selector = "form") => perform(`submit ${selector}`, () => elements.form(selector).requestSubmit()),
48
+ text: (selector) => {
49
+ const text = (selector === undefined ? elements.rendered(currentRoot(), "root") : elements.element(selector)).innerText;
50
+ tell(`read ${selector ?? "the screen"}: ${JSON.stringify(text)}`);
51
+ return text;
52
+ },
53
+ value: (selector) => {
54
+ const value = elements.input(selector).value;
55
+ tell(`read the value in ${selector}: ${JSON.stringify(value)}`);
56
+ return value;
57
+ },
58
+ };
59
+ }
60
+ //# sourceMappingURL=screenDriver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"screenDriver.js","sourceRoot":"","sources":["../../src/server/screenDriver.ts"],"names":[],"mappings":"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"}
@@ -37,7 +37,7 @@ export interface StoryKitDefinition<TEngine, TStage extends string, TVerbs, TPro
37
37
  readonly outbound?: Readonly<Record<string, string>>;
38
38
  readonly run?: RunHooks<TEngine, TStep, TFailed, TDiagnose>;
39
39
  readonly runIf?: boolean;
40
- readonly stages: readonly [TStage, ...TStage[]];
40
+ readonly stages: readonly TStage[];
41
41
  readonly verbs: (engine: TEngine, story: Story<TEngine, TStep | TFailed | TDiagnose>) => TVerbs;
42
42
  }
43
43
  export type Told<TEngine, TVerbs, TRun extends AnyEffect> = TVerbs & {
@@ -60,8 +60,8 @@ export interface StoryKit<TEngine, TStage extends string, TVerbs, TRun extends A
60
60
  };
61
61
  readonly traits: <const TGiven extends readonly Trait<TEngine, TStage, unknown>[]>(...given: TGiven) => Trait<TEngine, TStage, TraitServices<TGiven[number]>>;
62
62
  }
63
- export declare function storyKit<TCreate extends () => unknown, const TStage extends string, TVerbs extends object, TProvided = never, TAfter extends AfterResults<TStage> = Record<never, never>, TStep extends AnyEffect = never, TFailed extends AnyEffect = never, TDiagnose extends AnyEffect = never>(definition: InferredDefinition<TCreate, TStage, TVerbs, TProvided, TAfter, TStep, TFailed, TDiagnose>): StoryKit<HookValue<ReturnType<TCreate>>, TStage, TVerbs, TStep | TFailed | TDiagnose, TProvided>;
64
- export declare function storyKit<TEngine, const TStage extends string, TVerbs extends object, TProvided = never, TCreate extends AnyEffect = never, TAfter extends {
63
+ export declare function storyKit<TCreate extends () => unknown, const TStage extends string = never, TVerbs extends object = object, TProvided = never, TAfter extends AfterResults<TStage> = Record<never, never>, TStep extends AnyEffect = never, TFailed extends AnyEffect = never, TDiagnose extends AnyEffect = never>(definition: InferredDefinition<TCreate, TStage, TVerbs, TProvided, TAfter, TStep, TFailed, TDiagnose>): StoryKit<HookValue<ReturnType<TCreate>>, TStage, TVerbs, TStep | TFailed | TDiagnose, TProvided>;
64
+ export declare function storyKit<TEngine, const TStage extends string = never, TVerbs extends object = object, TProvided = never, TCreate extends AnyEffect = never, TAfter extends {
65
65
  readonly [TKey in TStage]?: AnyEffect;
66
66
  } = Record<never, never>, TStep extends AnyEffect = never, TFailed extends AnyEffect = never, TDiagnose extends AnyEffect = never>(definition: LegacyDefinition<TEngine, TStage, TVerbs, TProvided, TCreate, TAfter, TStep, TFailed, TDiagnose>): StoryKit<TEngine, TStage, TVerbs, TStep | TFailed | TDiagnose, TProvided>;
67
67
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"storyKit.d.ts","sourceRoot":"","sources":["../../src/server/storyKit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACtF,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,UAAU,EAAE,KAAK,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,SAAS,EAAU,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACxI,OAAO,KAAK,EAAE,YAAY,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAGrG,OAAO,EAAE,KAAK,KAAK,EAAiB,MAAM,qBAAqB,CAAC;AAEhE,MAAM,MAAM,KAAK,CAAC,OAAO,EAAE,MAAM,SAAS,MAAM,EAAE,CAAC,GAAG,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;AAEnI,KAAK,aAAa,CAAC,MAAM,IAAI,MAAM,SAAS,KAAK,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,KAAK,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAEhI,KAAK,KAAK,CAAC,SAAS,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;AAEnE,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACvC;AAED,MAAM,WAAW,KAAK,CAAC,OAAO,EAAE,IAAI,SAAS,SAAS,GAAG,KAAK;IAC7D,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,SAAS,SAAS,GAAG,KAAK,EACnD,KAAK,EAAE,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAC/C,OAAO,CAAC,EAAE,eAAe,KACrB,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,EAAE,UAAU,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC;IAC5E,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,QAAQ,CAAC,OAAO,EAAE,KAAK,SAAS,SAAS,EAAE,OAAO,SAAS,SAAS,EAAE,SAAS,SAAS,SAAS;IACjH,QAAQ,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;IAC/D,QAAQ,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACvE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;CAClF;AAED,MAAM,WAAW,kBAAkB,CAClC,OAAO,EACP,MAAM,SAAS,MAAM,EACrB,MAAM,EACN,SAAS,EACT,OAAO,SAAS,SAAS,EACzB,MAAM,SAAS;IAAE,QAAQ,EAAE,IAAI,IAAI,MAAM,CAAC,CAAC,EAAE,SAAS;CAAE,EACxD,KAAK,SAAS,SAAS,EACvB,OAAO,SAAS,SAAS,EACzB,SAAS,SAAS,SAAS;IAE3B,QAAQ,CAAC,KAAK,CAAC,EAAE;QAAE,QAAQ,EAAE,IAAI,IAAI,MAAM,MAAM,GAAG,UAAU,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,SAAS,EAAE,IAAI,CAAC;KAAE,CAAC;IACpH,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IAC/H,QAAQ,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAClD,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC;IAChD,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;IACxD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACrD,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;IAC5D,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;IAChD,QAAQ,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,GAAG,OAAO,GAAG,SAAS,CAAC,KAAK,MAAM,CAAC;CAChG;AAED,MAAM,MAAM,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,SAAS,SAAS,IAAI,MAAM,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;CAAE,CAAC;AAE9G,MAAM,MAAM,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,SAAS,SAAS,EAAE,OAAO,SAAS,SAAS,IAAI,CAC3F,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EACjC,OAAO,EAAE,WAAW,KAChB,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,GAAG,SAAS,CAAC;AAEpD,MAAM,MAAM,SAAS,CAAC,OAAO,EAAE,MAAM,SAAS,MAAM,EAAE,MAAM,EAAE,IAAI,SAAS,SAAS,EAAE,SAAS,IAAI,CAClG,OAAO,SAAS,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,KAAK,EAEtD,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,SAAS,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,EACjE,IAAI,CAAC,EAAE,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,EAChD,OAAO,CAAC,EAAE,MAAM,GAAG,iBAAiB,KAChC,IAAI,CAAC;AAEV,MAAM,WAAW,OAAO,CAAC,OAAO,EAAE,MAAM,SAAS,MAAM,EAAE,MAAM,EAAE,IAAI,SAAS,SAAS,EAAE,SAAS,CACjG,SAAQ,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,CAAC;IAC3D,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IACpE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IACnE,QAAQ,CAAC,KAAK,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IAC5F,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IACnE,QAAQ,CAAC,MAAM,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;CAC7F;AAED,MAAM,WAAW,QAAQ,CAAC,OAAO,EAAE,MAAM,SAAS,MAAM,EAAE,MAAM,EAAE,IAAI,SAAS,SAAS,EAAE,SAAS;IAClG,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IAC/D,QAAQ,CAAC,KAAK,EAAE;QACf,CAAC,OAAO,SAAS,SAAS,GAAG,KAAK,EACjC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,GAC3C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;QAC/C,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;KACtH,CAAC;IACF,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,MAAM,SAAS,SAAS,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,EAChF,GAAG,KAAK,EAAE,MAAM,KACZ,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;CAC3D;AAED,wBAAgB,QAAQ,CACvB,OAAO,SAAS,MAAM,OAAO,EAC7B,KAAK,CAAC,MAAM,SAAS,MAAM,EAC3B,MAAM,SAAS,MAAM,EACrB,SAAS,GAAG,KAAK,EACjB,MAAM,SAAS,YAAY,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EAC1D,KAAK,SAAS,SAAS,GAAG,KAAK,EAC/B,OAAO,SAAS,SAAS,GAAG,KAAK,EACjC,SAAS,SAAS,SAAS,GAAG,KAAK,EAEnC,UAAU,EAAE,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,CAAC,GACnG,QAAQ,CAAC,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,GAAG,OAAO,GAAG,SAAS,EAAE,SAAS,CAAC,CAAC;AAEpG,wBAAgB,QAAQ,CACvB,OAAO,EACP,KAAK,CAAC,MAAM,SAAS,MAAM,EAC3B,MAAM,SAAS,MAAM,EACrB,SAAS,GAAG,KAAK,EACjB,OAAO,SAAS,SAAS,GAAG,KAAK,EACjC,MAAM,SAAS;IAAE,QAAQ,EAAE,IAAI,IAAI,MAAM,CAAC,CAAC,EAAE,SAAS;CAAE,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EAC/E,KAAK,SAAS,SAAS,GAAG,KAAK,EAC/B,OAAO,SAAS,SAAS,GAAG,KAAK,EACjC,SAAS,SAAS,SAAS,GAAG,KAAK,EAEnC,UAAU,EAAE,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,CAAC,GAC1G,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,GAAG,OAAO,GAAG,SAAS,EAAE,SAAS,CAAC,CAAC"}
1
+ {"version":3,"file":"storyKit.d.ts","sourceRoot":"","sources":["../../src/server/storyKit.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shivaedev/test-story",
3
- "version": "0.7.1",
3
+ "version": "0.8.0",
4
4
  "description": "Tests that read like stories over the real engine: a story kit per engine with its own it, traits per feature, and a failure that prints the story, where it stopped and the engine's state",
5
5
  "homepage": "https://github.com/ShivaeDev/platform/tree/main/packages/test-story#readme",
6
6
  "bugs": {
@@ -37,21 +37,20 @@
37
37
  "!src/**/*.test.ts",
38
38
  "!src/**/*.spec.ts",
39
39
  "!src/**/test-support",
40
- "docs",
41
40
  "CHANGELOG.md",
42
41
  "README.md"
43
42
  ],
44
43
  "dependencies": {
45
- "@shivaedev/effect-test": "0.6.0"
44
+ "@shivaedev/effect-test": "0.6.0",
45
+ "dom-accessibility-api": "0.7.1"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@effect/vitest": "4.0.4",
49
- "@shivaedev/quality": "0.25.0",
49
+ "@shivaedev/quality": "0.26.0",
50
50
  "@types/node": "24.19.2",
51
- "@typescript/native": "npm:typescript@7.0.2",
52
51
  "effect": "4.0.4",
53
52
  "happy-dom": "20.14.6",
54
- "typescript": "npm:@typescript/typescript6@6.0.2",
53
+ "typescript": "7.0.2",
55
54
  "vitest": "5.0.3"
56
55
  },
57
56
  "peerDependencies": {
@@ -8,7 +8,7 @@ const domEnvironment: Environment = {
8
8
  // Vitest loads environments outside the project's source resolution conditions.
9
9
  const load = createRequire(import.meta.url);
10
10
  const { documentTransport }: typeof import("#internal/documentTransport.ts") = load("#internal/documentTransport.ts");
11
- const { installOutbound }: typeof import("#internal/routeOutbound.ts") = load("#internal/routeOutbound.ts");
11
+ const { installOutbound }: typeof import("#internal/installOutbound.ts") = load("#internal/installOutbound.ts");
12
12
  const native = Object.fromEntries(
13
13
  ["fetch", "AbortController", "AbortSignal", "Headers", "Request", "Response"].map((name) => [name, Reflect.get(global, name)]),
14
14
  );
@@ -1,5 +1,4 @@
1
1
  import { isIP } from "node:net";
2
- import { Effect } from "effect";
3
2
  import { unrouted } from "#internal/errors.ts";
4
3
 
5
4
  interface DispatchOptions {
@@ -63,10 +62,3 @@ export async function installOutbound(routes: Readonly<Record<string, string>>,
63
62
  }
64
63
  };
65
64
  }
66
-
67
- export function routeOutbound(routes: Readonly<Record<string, string>>) {
68
- return Effect.acquireRelease(
69
- Effect.promise(() => installOutbound(routes, Reflect.get(globalThis, Symbol.for("test-story.dom")) === true)),
70
- (restore) => Effect.sync(restore),
71
- ).pipe(Effect.asVoid);
72
- }
@@ -0,0 +1,62 @@
1
+ export function screenElements(root: () => HTMLElement) {
2
+ function rendered(found: HTMLElement, selector: string) {
3
+ const visibility = getComputedStyle(found).visibility;
4
+ let hidden = visibility === "hidden" || visibility === "collapse";
5
+ for (let ancestor: HTMLElement | null = found; ancestor; ancestor = ancestor.parentElement) {
6
+ const style = getComputedStyle(ancestor);
7
+ hidden ||= Boolean(ancestor.hidden) || style.display === "none" || style.contentVisibility === "hidden";
8
+ }
9
+ if (hidden) {
10
+ throw new Error(`The screen's ${selector} is not rendered.\nhelp: Reveal the target and its ancestors before acting on or reading it.`);
11
+ }
12
+ return found;
13
+ }
14
+ function element(selector: string) {
15
+ const matches = root().querySelectorAll<HTMLElement>(selector);
16
+ const found = matches[0];
17
+ if (matches.length !== 1 || found === undefined) {
18
+ throw new Error(
19
+ `The screen has ${matches.length} matches for ${JSON.stringify(selector)}.\nhelp: Use a selector for exactly one rendered control or readout.`,
20
+ );
21
+ }
22
+ return rendered(found, selector);
23
+ }
24
+ function input(selector: string) {
25
+ const found = element(selector);
26
+ if (!(found instanceof HTMLInputElement || found instanceof HTMLTextAreaElement)) {
27
+ throw new Error(`The screen's ${selector} is not a text field.\nhelp: Select a rendered input or textarea to enter or read a value.`);
28
+ }
29
+ return found;
30
+ }
31
+ function enabled(found: HTMLElement, selector: string) {
32
+ if (found.matches(":disabled") || found.closest("[inert]")) {
33
+ throw new Error(`The screen's ${selector} is disabled.\nhelp: Wait for the app to enable the control before acting on it.`);
34
+ }
35
+ }
36
+ return {
37
+ element,
38
+ enabled,
39
+ enter: (selector: string, value: string) => {
40
+ const field = input(selector);
41
+ enabled(field, selector);
42
+ if (field.readOnly) {
43
+ throw new Error(`The screen's ${selector} is read-only.\nhelp: Select an editable input or textarea.`);
44
+ }
45
+ field.focus();
46
+ const prototype = field instanceof HTMLInputElement ? HTMLInputElement.prototype : HTMLTextAreaElement.prototype;
47
+ Object.getOwnPropertyDescriptor(prototype, "value")?.set?.call(field, value);
48
+ field.dispatchEvent(new Event("input", { bubbles: true }));
49
+ field.dispatchEvent(new Event("change", { bubbles: true }));
50
+ },
51
+ form: (selector: string) => {
52
+ const found = element(selector);
53
+ if (!(found instanceof HTMLFormElement)) {
54
+ throw new Error(`The screen's ${selector} is not a form.\nhelp: Select a rendered form to submit.`);
55
+ }
56
+ enabled(found, selector);
57
+ return found;
58
+ },
59
+ input,
60
+ rendered,
61
+ };
62
+ }
@@ -26,6 +26,14 @@ export const start = Effect.fnUntraced(function* (
26
26
  },
27
27
  tell: narration.tell,
28
28
  };
29
- return yield* body({ ...definition.verbs(engine, story), story });
29
+ return yield* body(
30
+ Object.defineProperties(
31
+ {},
32
+ {
33
+ ...Object.getOwnPropertyDescriptors(definition.verbs(engine, story)),
34
+ story: { enumerable: true, value: story },
35
+ },
36
+ ),
37
+ );
30
38
  }).pipe(Effect.tapCause((cause) => Effect.sync(() => captureFailure(Cause.prettyErrors(cause)[0]?.stack))));
31
39
  });
@@ -4,9 +4,9 @@ import type { EffectTest, EffectTestOptions } from "@shivaedev/effect-test/types
4
4
  import { makeEffectIt } from "@shivaedev/effect-test/vitest.ts";
5
5
  import { type Genre, genreOf } from "#internal/genre.ts";
6
6
  import { type AnyEffect, hooked } from "#internal/hooked.ts";
7
- import { routeOutbound } from "#internal/routeOutbound.ts";
8
7
  import type { LooseDefinition, LooseTrait } from "#internal/seed.ts";
9
8
  import { start } from "#internal/start.ts";
9
+ import { routeOutbound } from "#routeOutbound.ts";
10
10
 
11
11
  type LooseBody = (told: object, context: TestContext) => Generator<AnyEffect, unknown, never> | undefined;
12
12
 
@@ -0,0 +1,9 @@
1
+ import { Effect } from "effect";
2
+ import { installOutbound } from "#internal/installOutbound.ts";
3
+
4
+ export function routeOutbound(routes: Readonly<Record<string, string>>) {
5
+ return Effect.acquireRelease(
6
+ Effect.promise(() => installOutbound(routes, Reflect.get(globalThis, Symbol.for("test-story.dom")) === true)),
7
+ (restore) => Effect.sync(restore),
8
+ ).pipe(Effect.asVoid);
9
+ }
@@ -0,0 +1,75 @@
1
+ import { computeAccessibleName, getRole } from "dom-accessibility-api";
2
+ import { Effect } from "effect";
3
+ import { withLive } from "@shivaedev/effect-test/withLive.ts";
4
+ import { screenElements } from "#internal/screenElements.ts";
5
+
6
+ export interface ScreenDriverOptions {
7
+ readonly act?: (action: () => Promise<void>) => PromiseLike<void>;
8
+ readonly pending: () => boolean;
9
+ readonly root: HTMLElement | (() => HTMLElement);
10
+ readonly tell: (line: string) => void;
11
+ readonly timeoutMs?: number;
12
+ }
13
+
14
+ export type ScreenDriver = ReturnType<typeof screenDriver>;
15
+
16
+ export function screenDriver({ root, pending, tell, act = (action) => action(), timeoutMs = 3000 }: ScreenDriverOptions) {
17
+ const currentRoot = typeof root === "function" ? root : () => root;
18
+ const elements = screenElements(currentRoot);
19
+ function perform(line: string, action: () => void) {
20
+ return Effect.promise(async () => {
21
+ tell(line);
22
+ await act(async () => action());
23
+ });
24
+ }
25
+ function settle(options: { readonly timeoutMs?: number } = {}) {
26
+ const limit = options.timeoutMs ?? timeoutMs;
27
+ const wait = Effect.gen(function* () {
28
+ tell("wait for the screen's pending work");
29
+ do {
30
+ yield* Effect.promise(() => act(async () => undefined));
31
+ if (!pending()) {
32
+ tell("the screen has no pending work");
33
+ return;
34
+ }
35
+ yield* Effect.promise(() => act(() => new Promise<void>((resolve) => setTimeout(resolve, 10))));
36
+ } while (true);
37
+ });
38
+ function timedOut() {
39
+ return Effect.die(
40
+ new Error(
41
+ `The screen did not settle within ${limit}ms.\nhelp: Release held requests and check the app's pending signal and renderer act adapter.\nScreen: ${currentRoot().textContent}`,
42
+ ),
43
+ );
44
+ }
45
+ return withLive(wait.pipe(Effect.timeoutOrElse({ duration: limit, orElse: timedOut })));
46
+ }
47
+ return {
48
+ accessible: (selector: string) => {
49
+ const element = elements.element(selector);
50
+ const accessible = { name: computeAccessibleName(element), role: getRole(element) };
51
+ tell(`read the accessibility of ${selector}: ${JSON.stringify(accessible)}`);
52
+ return accessible;
53
+ },
54
+ click: (selector: string) =>
55
+ perform(`click ${selector}`, () => {
56
+ const element = elements.element(selector);
57
+ elements.enabled(element, selector);
58
+ element.focus();
59
+ element.click();
60
+ }),
61
+ enter: (selector: string, value: string) => perform(`enter a value in ${selector}`, () => elements.enter(selector, value)),
62
+ settle,
63
+ submit: (selector = "form") => perform(`submit ${selector}`, () => elements.form(selector).requestSubmit()),
64
+ text: (selector?: string) => {
65
+ const text = (selector === undefined ? elements.rendered(currentRoot(), "root") : elements.element(selector)).innerText;
66
+ tell(`read ${selector ?? "the screen"}: ${JSON.stringify(text)}`);
67
+ return text;
68
+ },
69
+ value: (selector: string) => {
70
+ const value = elements.input(selector).value;
71
+ tell(`read the value in ${selector}: ${JSON.stringify(value)}`);
72
+ return value;
73
+ },
74
+ };
75
+ }
@@ -55,7 +55,7 @@ export interface StoryKitDefinition<
55
55
  readonly outbound?: Readonly<Record<string, string>>;
56
56
  readonly run?: RunHooks<TEngine, TStep, TFailed, TDiagnose>;
57
57
  readonly runIf?: boolean;
58
- readonly stages: readonly [TStage, ...TStage[]];
58
+ readonly stages: readonly TStage[];
59
59
  readonly verbs: (engine: TEngine, story: Story<TEngine, TStep | TFailed | TDiagnose>) => TVerbs;
60
60
  }
61
61
 
@@ -101,8 +101,8 @@ export interface StoryKit<TEngine, TStage extends string, TVerbs, TRun extends A
101
101
 
102
102
  export function storyKit<
103
103
  TCreate extends () => unknown,
104
- const TStage extends string,
105
- TVerbs extends object,
104
+ const TStage extends string = never,
105
+ TVerbs extends object = object,
106
106
  TProvided = never,
107
107
  TAfter extends AfterResults<TStage> = Record<never, never>,
108
108
  TStep extends AnyEffect = never,
@@ -114,8 +114,8 @@ export function storyKit<
114
114
  // Keep explicit engine and effect type arguments accepted by existing kits.
115
115
  export function storyKit<
116
116
  TEngine,
117
- const TStage extends string,
118
- TVerbs extends object,
117
+ const TStage extends string = never,
118
+ TVerbs extends object = object,
119
119
  TProvided = never,
120
120
  TCreate extends AnyEffect = never,
121
121
  TAfter extends { readonly [TKey in TStage]?: AnyEffect } = Record<never, never>,
@@ -1 +0,0 @@
1
- {"version":3,"file":"routeOutbound.d.ts","sourceRoot":"","sources":["../../../src/server/internal/routeOutbound.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAehC,wBAAsB,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,UAAQ,uBAgD7F;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,4DAKrE"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"routeOutbound.js","sourceRoot":"","sources":["../../../src/server/internal/routeOutbound.ts"],"names":[],"mappings":"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"}
@@ -1,35 +0,0 @@
1
- # North star
2
-
3
- ## The problem
4
-
5
- Agents now write most of the code, tests included, and a test file an agent writes tends to be hundreds of lines long. Each test rebuilds its setup by hand, a little differently from the last, and where rebuilding a complex setup is too much work, it mocks the part that was hard to build. Nobody reads these files. A human could ask an agent what a suite actually tests, but nobody asks consistently enough for that to be a safety net, so we lose sight of what we test exactly when more code is written than ever.
6
-
7
- ## The ideal
8
-
9
- A test reads like a short English story: what exists, what someone does, and what is true afterwards. Its setup is a list of traits in the domain's words, such as `ovenIsLit()` and `hasDough(3)`, its actions go through the application's real verbs, and the real engine runs between them. Everything that is not specific to this one test lives elsewhere, written once:
10
-
11
- - once per engine, a story kit that knows how to create the engine, seed it stage by stage, step it and show its state;
12
- - once per feature, the traits and verbs that name that feature in domain words;
13
- - in each test, only the story.
14
-
15
- This changes the cost and benefit of a good test for both readers. For an agent, a story test is the cheaper one to write and to read on every later visit, because it is a handful of lines that reuse what already exists. Because every story runs the whole engine, each test also checks, almost by accident, the parts its author never thought about and would have mocked. For a human, a spec that reads as English leaves no excuse not to read it. With so little noise around the signal, an agent that writes a sloppy or pointless test produces something a reviewer sees at a glance.
16
-
17
- ## What good looks like
18
-
19
- - A spec is a few lines of domain words. If a spec needs a helper, a loop or hand-built state, a trait or verb is missing from the kit.
20
- - An impossible setup refuses loudly instead of seeding a state the application could never reach.
21
- - A failure is a console version of stopping in a debugger: the whole story, where it stopped and the spec line there, and the engine's state at that moment, written so an agent with no knowledge of this package can fix the test, and complete enough that a CI log alone is enough to reproduce it.
22
- - The kit author writes hooks and the package infers every type from them. There is one kit, built on Effect: a hook is a plain function, or a generator function when it needs a service or fails with a typed error, so no definition writes `Effect.gen` and a plain engine needs no Effect at all.
23
- - A spec writes only its story. The kit hands it an `it` that already knows the engine's services, so a spec never builds a test harness, and names every test after its genre, so a report shows which engine it ran and a run can pick one engine's stories.
24
-
25
- ## Trade-offs
26
-
27
- - **Real engine over speed.** A story is slower than a unit test with a mock. We accept that, and keep engines fast enough to step in a test instead of faking them.
28
- - **Hooks over freedom.** The kit fixes the shape of an engine: create, stages, after-stage hooks, a step, a state to inspect, verbs. An engine that does not fit should change its kit's hooks, not bypass the kit.
29
- - **Cheap locations over complete ones.** The failure shows one spec line, where the story stopped, found by matching the spec's path in the failure's stack or in the call site of the story's last line. A failure raised deep inside an Effect verb may have none; finding one would take machinery we do not want.
30
-
31
- ## What it will not do
32
-
33
- - Run without Vitest, or print a failure anywhere but the failing test's own error.
34
- - Own any application's traits, verbs or steps; they belong to the application's `test-support/`.
35
- - Mock the application's own code, or help a test reach into an engine's internals. A fake belongs only at a true external boundary, and the kit's `create` is where it is wired in.
package/docs/roadmap.md DELETED
@@ -1,26 +0,0 @@
1
- # Roadmap
2
-
3
- This file owns the story kit's implementation, next work and open questions. The [framework roadmap](https://github.com/ShivaeDev/platform/blob/main/docs/framework/roadmap.md) owns composed application features and host-level validation. Those roadmaps link to each other rather than repeating a completion checklist.
4
-
5
- ## Built
6
-
7
- - [x] `storyKit(definition)`: one Effect kit per engine, with every type and the services its layer provides inferred from its hooks. Plain engines plug in with plain functions.
8
- - [x] Traits seeded stage by stage, with a hook after each stage, and refusal of an impossible setup.
9
- - [x] The kit's own `it`, built on `@shivaedev/effect-test`, which hands the body the verbs and the story and names every test after the kit's genre. Vitest tags per genre are opt-in through `genreTags(...kitNames)` in the Vitest config.
10
- - [x] `story.runUntil(condition)`: steps the engine until the condition holds, stops on what `run.failed` reports, and stops after a step budget with a diagnosis, keeping every hook's typed failure in its error channel.
11
- - [x] A failed test prints a short guide, its story, where it stopped with the spec line there, and the engine's state, inline or in a file under `node_modules/.cache/test-story/`, broken at 120 columns.
12
- - [x] `domEnvironment` keeps Node fetch classes for an in-process host and happy-dom fetch for the client; `domFetch(baseUrl)` connects the window to that host, with a starter story proving Better Auth sign-up, sign-in, session reads and sign-out on PostgreSQL through cookies.
13
- - [x] `domNavigate` loads a routed document into happy-dom, updates its location and returns a response whose body remains readable. [Document transport stories](../src/server/documentTransport.dom.spec.ts) assert the rendered heading, location and response body.
14
- - [x] `outbound` routes exact hostnames to fake HTTP servers while preserving request paths, queries, methods, headers and bodies, and restores Node routing after successful and failed stories. [Outbound stories](../src/server/outbound.spec.ts) assert routing and restoration; [document transport stories](../src/server/documentTransport.dom.spec.ts) cover redirects, cookies and XMLHttpRequest; [DOM refusal tests](../src/server/domOutbound.spec.ts) assert that unrouted external fetches, document requests and redirects fail the story even when application code catches the error.
15
- - [x] In-process host creation separates request traces from the story span: requests without trace headers get distinct root traces, supplied trace headers continue their trace, request work stays under the request span, and traits and steps stay under the story span. [Host tracing stories](../src/server/hostTracing.spec.ts) assert span parents, trace IDs and completed request spans.
16
- - [x] Creation, traits and stage `after` hooks can return Effects directly, with services from the kit's Layer and resources released in the story's Scope, covered by [Effect hook stories](../src/server/effectHooks.spec.ts).
17
- - [x] Kit hooks and steps support a live clock and a per-story TestClock override. [Live-time stories](../src/server/liveTime.spec.ts) cover polling real workers with `withLive` without advancing virtual token expiry.
18
-
19
- ## Next
20
-
21
- - [ ] Move the Work Fleet engine's hand-written story DSL onto the kit and let what it needs decide the next hook.
22
-
23
- ## Open questions
24
-
25
- - A long story prints in full. Should a story of thousands of lines print its traits and its last lines, and write the rest to a file the way a large engine state is written?
26
- - `inspect` runs synchronously when the test has failed. An engine whose state lives behind an Effect service cannot be read then. Is that worth an Effect inspect, captured when the failure happens?