@shivaedev/test-story 0.7.0 → 0.7.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.7.1 - 2026-10-18
4
+
5
+ ### Fixed
6
+
7
+ - Publish against `@shivaedev/effect-test` 0.6.0 so framework consumers share the current test runner.
8
+
3
9
  ## 0.7.0 - 2026-10-18
4
10
 
5
11
  ### Added
package/README.md CHANGED
@@ -8,11 +8,13 @@ When agents write most of the code, test files grow into hundreds of lines nobod
8
8
 
9
9
  ```ts
10
10
  bakery.it("steps until the condition holds", [ovenIsLit(), hasDough(3)], function* ({ oven }) {
11
- expect(yield* oven.bakesEverything()).toEqual({ loaves: 3, minutes: 3 });
11
+ yield* oven.bakesEverything();
12
+ expect(oven.loaves()).toBe(3);
13
+ expect(oven.minutes()).toBe(3);
12
14
  });
13
15
  ```
14
16
 
15
- That is a whole test. `bakery.it` comes from the bakery's story kit. The list holds its traits, `ovenIsLit()` and `hasDough(3)`, which are written once and shared by every spec. `oven.bakesEverything()` is a verb that runs the bakery's real code until the dough is gone. Every story runs the whole engine, so each test also checks the parts its author never thought to mock, and because a spec reads as English, a sloppy test stands out in review.
17
+ That is a whole test. `bakery.it` comes from the bakery's story kit. The list holds its traits, `ovenIsLit()` and `hasDough(3)`, which are written once and shared by every spec. `oven.bakesEverything()` performs the baking action until the dough is gone; `oven.loaves()` and `oven.minutes()` read separate observations. The spec states both expectations. Every story runs the whole engine, so each test also checks the parts its author never thought to mock, and because a spec reads as English, a sloppy test stands out in review.
16
18
 
17
19
  When a story fails, it prints itself. One of this package's own failing stories expects 2 loaves from one ball of dough, and the test fails with this message:
18
20
 
@@ -28,7 +30,7 @@ loaves: expected 1 to be 2 // Object.is equality
28
30
  given the baker has 1 balls of dough
29
31
  1m a loaf comes out of the oven
30
32
  ✗ the test failed after the line above
31
- at src/test-support/failingStories.ts:10:59
33
+ at src/test-support/failingStories.ts:12:34
32
34
 
33
35
  The bakery when the test failed:
34
36
  {"bowls":1,"capacity":3,"dough":0,"flour":0,"loaves":1,"minute":1,"orders":[],"ovenLit":true,"overfired":false,
@@ -57,6 +59,22 @@ The work splits into three layers, and each is written by a different hand at a
57
59
  2. **Once per feature**, traits and verbs in the kit name that feature in domain words.
58
60
  3. **In every test**, a spec tells a story with the kit's `it` and checks what a user would see.
59
61
 
62
+ ### The verb shape every kit follows
63
+
64
+ A verb performs one action on the real engine or reads one observation. An action may return its real response, such as an HTTP response; it does not orchestrate a scenario and package the measurements for the spec. A readout reports what happened without deciding whether it was correct. The spec shows each action in order and states every expectation.
65
+
66
+ Acquire real services in `create` or a trait inside the story's per-test Scope, with dependencies provided by `layer`. Keep those services on the engine so verbs use the same running instance; scoped cleanup releases them after the story. Do not build and tear down services inside each verb. When closing a service is the action under test, expose that action separately from acquisition and observation.
67
+
68
+ | Shape to avoid | What to do instead |
69
+ | --- | --- |
70
+ | A verb runs a whole scenario and returns the measurements the spec asserts. | Give each action and observation its own verb; let the spec compose them and compare the observations. |
71
+ | A verb hard-codes the expected outcome or hides assertions. | Return the real response or observation, and put expected values and all assertions in the spec. |
72
+ | A verb does two jobs and returns both results. | Split the jobs into two verbs and show both calls in the spec. |
73
+ | A verb silently does nothing when its target is missing, such as `button?.click()`. | Fail with a message naming the missing target, then perform the action only once the target exists. |
74
+ | An engine default hides what the story declares, such as a lit oven, signed-in user or authorization header. | Start with a neutral engine and name the precondition in a trait or pass the input explicitly in the action. |
75
+
76
+ The bakery below starts with a cold oven and no dough. Its traits declare heat and dough, its baking action returns no report, and its readouts expose loaves and elapsed minutes separately. `runUntil` waits for that one engine action to complete; it does not replace a spec's sequence of actions.
77
+
60
78
  ### 1. Once per engine: the story kit
61
79
 
62
80
  `storyKit(definition)` from `@shivaedev/test-story/storyKit.ts` turns one definition into the kit. Every type, the engine's, the stages', the verbs' and the services', is inferred from it.
@@ -97,8 +115,10 @@ export const bakery = storyKit({
97
115
  },
98
116
  },
99
117
  oven: {
100
- bakesEverything: (maxSteps?: number): Effect.Effect<BakeReport, BurntLoaf> =>
101
- story.runUntil((current) => current.dough === 0, { maxSteps }).pipe(Effect.map(() => ({ loaves: state.loaves, minutes: state.minute }))),
118
+ bakesEverything: (maxSteps?: number): Effect.Effect<void, BurntLoaf> =>
119
+ story.runUntil((current) => current.dough === 0, { maxSteps }),
120
+ loaves: () => state.loaves,
121
+ minutes: () => state.minute,
102
122
  },
103
123
  }),
104
124
  });
@@ -118,7 +138,7 @@ This is the bakery kit this package tests itself with. `emptyBakery`, `stillWait
118
138
  | `after` | Optional. A hook per stage that runs once that stage's traits are applied, even when no trait names the stage, so a value it derives is ready before a later stage reads it. Its typed failure fails the test. |
119
139
  | `run` | Optional. What `story.runUntil` needs: `step(engine, tell)` advances the engine once and tells what happened, `maxSteps` caps one run, `failed(engine)` returns a sentence when the engine is in a state it cannot recover from, and `diagnose(engine)` says why it has not finished. |
120
140
  | `inspect` | Optional. The part of the engine a failure prints. Without it, the failure prints the whole engine. |
121
- | `verbs(engine, story)` | The entry points a test acts through. A verb that runs the engine returns the Effect from `story.runUntil`. |
141
+ | `verbs(engine, story)` | One action or one observation per verb. A verb that waits for a stepped engine returns the Effect from `story.runUntil`; the spec reads observations and asserts separately. |
122
142
 
123
143
  Every test of the kit is named `Bakery Story: <its name>`, so `vitest run -t "Bakery Story: "` runs only the bakery's stories with no setup. A project that splits runs by Vitest tags can also tag them:
124
144
 
@@ -154,7 +174,7 @@ Start an in-process host in `create` or a stage's `after` hook, such as `after:
154
174
 
155
175
  This lets an application's story assert that a request starts its own trace: a request without trace headers starts a root trace, and a request with `traceparent` continues that trace. Host startup and cleanup do not join the story's trace.
156
176
 
157
- A kit can collect spans with a native in-memory tracer, or start a fake OTLP receiver and point the application's exporter at it. Keep collection and any exporter flush or bounded wait in the kit's verbs. Assert only after the request span has ended. This small in-memory kit uses Effect's Web Request handler as its host:
177
+ A kit can collect spans with a native in-memory tracer, or start a fake OTLP receiver and point the application's exporter at it. Expose collection, exporter flush and any bounded wait as separate verbs. Assert only after the request span has ended. This small in-memory kit uses Effect's Web Request handler as its host:
158
178
 
159
179
  ```ts
160
180
  import { Effect, Tracer } from "effect";
@@ -162,44 +182,48 @@ import { HttpEffect, HttpServerResponse } from "effect/http";
162
182
  import { expect } from "vitest";
163
183
  import { storyKit } from "@shivaedev/test-story/storyKit.ts";
164
184
 
165
- const spans: Tracer.NativeSpan[] = [];
166
- const tracer = Tracer.make({
167
- span: (options) => {
168
- const span = new Tracer.NativeSpan(options);
169
- spans.push(span);
170
- return span;
171
- },
172
- });
173
-
174
185
  const app = storyKit({
175
- around: (effect) => effect.pipe(Effect.withSpan("story"), Effect.withTracer(tracer)),
186
+ around: (effect) => effect.pipe(Effect.withSpan("story")),
176
187
  *create() {
177
- const context = yield* Effect.context<never>();
178
- return HttpEffect.toWebHandlerWith(context)(Effect.succeed(HttpServerResponse.text("ok")));
188
+ const spans: Tracer.NativeSpan[] = [];
189
+ const tracer = Tracer.make({
190
+ span: (options) => {
191
+ const span = new Tracer.NativeSpan(options);
192
+ spans.push(span);
193
+ return span;
194
+ },
195
+ });
196
+ const context = yield* Effect.context<never>().pipe(Effect.withTracer(tracer));
197
+ const handler = HttpEffect.toWebHandlerWith(context)(Effect.succeed(HttpServerResponse.text("ok")));
198
+ return { handler, spans };
179
199
  },
180
200
  name: "traced application",
181
201
  stages: ["ready"],
182
- verbs: (handler) => ({
202
+ verbs: ({ handler, spans }) => ({
183
203
  request: (headers: HeadersInit = {}) => Effect.promise(async () => {
184
204
  const response = await handler(new Request("http://app.test/", { headers }));
185
- await response.text();
205
+ return response.text();
206
+ }),
207
+ requestSpan: () => {
186
208
  const span = spans.filter((span) => span.kind === "server").at(-1);
187
209
  if (span === undefined) throw new Error("The request exported no server span");
188
210
  return span;
189
- }),
211
+ },
190
212
  }),
191
213
  });
192
214
 
193
- app.it("a request is its own root trace", [], function* ({ request }) {
215
+ app.it("a request is its own root trace", [], function* ({ request, requestSpan }) {
194
216
  const storySpan = yield* Effect.currentSpan;
195
- const span = yield* request();
217
+ expect(yield* request()).toBe("ok");
218
+ const span = requestSpan();
196
219
  expect(span.parent._tag).toBe("None");
197
220
  expect(span.traceId).not.toBe(storySpan.traceId);
198
221
  expect(span.status._tag).toBe("Ended");
199
222
  });
200
223
 
201
- app.it("a request continues its supplied trace", [], function* ({ request }) {
202
- const span = yield* request({ traceparent: "00-1234567890abcdef1234567890abcdef-1234567890abcdef-01" });
224
+ app.it("a request continues its supplied trace", [], function* ({ request, requestSpan }) {
225
+ yield* request({ traceparent: "00-1234567890abcdef1234567890abcdef-1234567890abcdef-01" });
226
+ const span = requestSpan();
203
227
  expect(span.traceId).toBe("1234567890abcdef1234567890abcdef");
204
228
  expect(span.parent).toMatchObject({ value: { spanId: "1234567890abcdef" } });
205
229
  });
@@ -212,15 +236,15 @@ The package's [tracing kit](https://github.com/ShivaeDev/platform/blob/main/pack
212
236
  Use `otlpReceiver` from `@shivaedev/test-story/otlpReceiver.ts` in a kit's scoped `create` hook. It listens on an allocated loopback port and closes with the story scope. Point the application's real exporter at `${receiver.url}/v1/traces`, then flush the exporter before reading:
213
237
 
214
238
  ```ts
215
- import { otlpReceiver } from "@shivaedev/test-story/otlpReceiver.ts";
216
-
217
- const receiver = yield* otlpReceiver();
218
- yield* exportWork(`${receiver.url}/v1/traces`);
219
- expect(receiver.spans).toContainEqual(expect.objectContaining({ name: "CountWords" }));
220
- expect(receiver.requests.some(({ body }) => body.includes(Buffer.from("planted-secret")))).toBe(true);
239
+ app.it("exports the work span", [], function* ({ runWork, disposeRuntime, spans, requests }) {
240
+ yield* runWork();
241
+ yield* disposeRuntime();
242
+ expect(spans()).toContainEqual(expect.objectContaining({ name: "CountWords" }));
243
+ expect(requests().some(({ body }) => body.includes(Buffer.from("planted-secret")))).toBe(true);
244
+ });
221
245
  ```
222
246
 
223
- `exportWork` is the kit's verb that runs application work and flushes its exporter. The receiver accepts OTLP/HTTP JSON and protobuf. `spans` flattens all exports into decoded trace and span IDs, parent span IDs, names, numeric OTLP kinds and status codes, attributes, events and links. Attributes retain OTLP key/value objects, including lossless decimal strings for integers; each span also has `resourceAttributes`. `requests` retains every request's unmodified `body` Buffer, parsed `headers`, original `rawHeaders` pairs and `path`. Search all body bytes when checking that a secret was not exported. Optional `path`, `status` (a number or attempt callback) and `answer` configure collector responses for failure stories.
247
+ Here `app` is the application's kit. Its `create` acquires the receiver and the real exporter pointed at that receiver, `runWork` performs the traced operation, `disposeRuntime` disposes the exporter's runtime and flushes pending spans, and `spans` and `requests` read the receiver's observations. Each action is visible in the spec. The receiver accepts OTLP/HTTP JSON and protobuf. `spans` flattens all exports into decoded trace and span IDs, parent span IDs, names, numeric OTLP kinds and status codes, attributes, events and links. Attributes retain OTLP key/value objects, including lossless decimal strings for integers; each span also has `resourceAttributes`. `requests` retains every request's unmodified `body` Buffer, parsed `headers`, original `rawHeaders` pairs and `path`. Search all body bytes when checking that a secret was not exported. Optional `path`, `status` (a number or attempt callback) and `answer` configure collector responses for failure stories.
224
248
 
225
249
  For timeout stories, return `undefined` from the `status` callback to accept an export without sending response headers. Set `answer: null` to send headers without completing the response body.
226
250
 
@@ -303,7 +327,7 @@ help: a trait throws when the bakery it asks for cannot exist. Give the test tra
303
327
 
304
328
  given the oven is lit
305
329
  ✗ given the baker has 4 balls of dough
306
- refused at src/test-support/failingStories.ts:13:57
330
+ refused at src/test-support/failingStories.ts:15:57
307
331
  given the bakery has 1 bowls
308
332
 
309
333
  The bakery when the test failed:
@@ -370,7 +394,7 @@ The package wraps between words or JSON fields toward 120 columns and prints the
370
394
 
371
395
  ### Library package kits
372
396
 
373
- A library package has an engine too: its own services or Layer under test. Keep its kit in `src/test-support/`, acquire the real services in `create` with their dependencies supplied by the kit's `layer`, and use real PostgreSQL wherever the package touches it. Traits seed that engine in domain words; verbs call the package's public API. The same division applies as for an application: the kit owns setup and wiring, and a spec names traits, calls verbs and checks results. Following the [root test guidance](https://github.com/ShivaeDev/platform/blob/main/AGENTS.md), reserve plain Vitest tests for pure functions with no engine behind them.
397
+ A library package has an engine too: its own services or Layer under test. Keep its kit in `src/test-support/`, acquire the real services in `create` or a trait inside the story's per-test Scope, with their dependencies supplied by the kit's `layer`, and use real PostgreSQL wherever the package touches it. Traits seed that engine in domain words; each verb calls one action on the package's public API or reads one observation from that same engine. Verbs never create a fresh service just to run a scenario and return its measurements. The same division applies as for an application: the kit owns setup and wiring, and a spec names traits, shows every action through verbs and states each expectation. Following the [root test guidance](https://github.com/ShivaeDev/platform/blob/main/AGENTS.md), reserve plain Vitest tests for pure functions with no engine behind them.
374
398
 
375
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.
376
400
 
@@ -448,24 +472,21 @@ const socialApp = storyKit({
448
472
  ...socialDefinition,
449
473
  outbound: { "github.com": fakeUrl, "api.github.com": fakeUrl },
450
474
  verbs: (engine, story) => ({
451
- signInWithGitHub: () => Effect.promise(async () => {
475
+ clickGitHubSignIn: () => Effect.promise(async () => {
452
476
  story.tell("Alice clicks Sign in with GitHub");
453
477
  await engine.screen.click();
454
- await domNavigate();
455
478
  }),
456
- signedInPage: () => Effect.promise(async () => ({
457
- heading: document.querySelector("h1")?.textContent,
458
- session: await (await engine.fetch("/api/auth/get-session")).json(),
459
- })),
479
+ followRedirect: () => Effect.promise(() => domNavigate()),
480
+ heading: () => document.querySelector("h1")?.textContent,
481
+ session: () => Effect.promise(async () => (await engine.fetch("/api/auth/get-session")).json()),
460
482
  }),
461
483
  });
462
484
 
463
- socialApp.it("a social sign-in returns with a cookie session", [], function* ({ signInWithGitHub, signedInPage }) {
464
- yield* signInWithGitHub();
465
- expect(yield* signedInPage()).toMatchObject({
466
- heading: "Signed in as alice@social.test",
467
- session: { user: { email: "alice@social.test" } },
468
- });
485
+ socialApp.it("a social sign-in returns with a cookie session", [], function* ({ clickGitHubSignIn, followRedirect, heading, session }) {
486
+ yield* clickGitHubSignIn();
487
+ yield* followRedirect();
488
+ expect(heading()).toBe("Signed in as alice@social.test");
489
+ expect(yield* session()).toMatchObject({ user: { email: "alice@social.test" } });
469
490
  });
470
491
  ```
471
492
 
@@ -1,5 +1,5 @@
1
1
  import { Effect, type Scope } from "effect";
2
- import type { AnyTestLayer } from "@shivaedev/effect-test/any-test-layer.ts";
2
+ import type { AnyTestLayer } from "@shivaedev/effect-test/anyTestLayer.ts";
3
3
  import type { EffectClock } from "@shivaedev/effect-test/types.ts";
4
4
  import { type AnyEffect, type EffectHook, type Hook } from "#internal/hooked.ts";
5
5
  import { type Narration } from "#internal/narration.ts";
@@ -1 +1 @@
1
- {"version":3,"file":"seed.d.ts","sourceRoot":"","sources":["../../../src/server/internal/seed.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,MAAM,EAAE,KAAK,KAAK,EAAU,MAAM,QAAQ,CAAC;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0CAA0C,CAAC;AAC7E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAEnE,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,UAAU,EAAE,KAAK,IAAI,EAAU,MAAM,qBAAqB,CAAC;AACzF,OAAO,EAAE,KAAK,SAAS,EAAa,MAAM,wBAAwB,CAAC;AACnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,MAAM,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;AAEnG,MAAM,WAAW,UAAU;IAC1B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC5I,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACnG,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,KAAK,CAAC,KAAK,CAAC,CAAC;IAC1G,QAAQ,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IACpD,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC;IAChD,QAAQ,CAAC,KAAK,CAAC,EAAE,YAAY,CAAC;IAC9B,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,aAAa,CAAC,OAAO,CAAC,CAAC;IACtC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,KAAK,MAAM,CAAC;CAC/D;AAED,eAAO,MAAM,IAAI,6IAuBf,CAAC"}
1
+ {"version":3,"file":"seed.d.ts","sourceRoot":"","sources":["../../../src/server/internal/seed.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,MAAM,EAAE,KAAK,KAAK,EAAU,MAAM,QAAQ,CAAC;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wCAAwC,CAAC;AAC3E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAEnE,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,UAAU,EAAE,KAAK,IAAI,EAAU,MAAM,qBAAqB,CAAC;AACzF,OAAO,EAAE,KAAK,SAAS,EAAa,MAAM,wBAAwB,CAAC;AACnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,MAAM,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;AAEnG,MAAM,WAAW,UAAU;IAC1B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC5I,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACnG,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,KAAK,CAAC,KAAK,CAAC,CAAC;IAC1G,QAAQ,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IACpD,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC;IAChD,QAAQ,CAAC,KAAK,CAAC,EAAE,YAAY,CAAC;IAC9B,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,aAAa,CAAC,OAAO,CAAC,CAAC;IACtC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,KAAK,MAAM,CAAC;CAC/D;AAED,eAAO,MAAM,IAAI,6IAuBf,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shivaedev/test-story",
3
- "version": "0.7.0",
3
+ "version": "0.7.1",
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": {
@@ -24,9 +24,8 @@
24
24
  },
25
25
  "exports": {
26
26
  "./*.ts": {
27
- "types": "./dist/server/*.d.ts",
28
27
  "source": "./src/server/*.ts",
29
- "import": "./dist/server/*.js",
28
+ "types": "./dist/server/*.d.ts",
30
29
  "default": "./dist/server/*.js"
31
30
  },
32
31
  "./internal/*": null,
@@ -43,11 +42,11 @@
43
42
  "README.md"
44
43
  ],
45
44
  "dependencies": {
46
- "@shivaedev/effect-test": "0.5.0"
45
+ "@shivaedev/effect-test": "0.6.0"
47
46
  },
48
47
  "devDependencies": {
49
48
  "@effect/vitest": "4.0.4",
50
- "@shivaedev/quality": "0.24.0",
49
+ "@shivaedev/quality": "0.25.0",
51
50
  "@types/node": "24.19.2",
52
51
  "@typescript/native": "npm:typescript@7.0.2",
53
52
  "effect": "4.0.4",
@@ -1,5 +1,5 @@
1
1
  import { Cause, Context, Effect, type Scope, Tracer } from "effect";
2
- import type { AnyTestLayer } from "@shivaedev/effect-test/any-test-layer.ts";
2
+ import type { AnyTestLayer } from "@shivaedev/effect-test/anyTestLayer.ts";
3
3
  import type { EffectClock } from "@shivaedev/effect-test/types.ts";
4
4
  import { refusal } from "#internal/errors.ts";
5
5
  import { type AnyEffect, type EffectHook, type Hook, hooked } from "#internal/hooked.ts";