@shivaedev/effect-test 0.1.1 → 0.1.2

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,6 +1,15 @@
1
1
  # Changelog
2
2
 
3
- ## Unreleased
3
+ ## 0.1.2 - 2026-09-26
4
+
5
+ ### Fixed
6
+
7
+ - Make `eventually` retry only typed failures under TestClock, matching the live
8
+ clock. Defects and interruption propagate without retrying.
9
+
10
+ ### Changed
11
+
12
+ - Document the live worker-Layer clock and the scope of per-test clock overrides.
4
13
 
5
14
  ## 0.1.1 - 2026-09-04
6
15
 
package/README.md CHANGED
@@ -58,10 +58,20 @@ effectApp("talks to a real timer", function* () {
58
58
  }, { clock: "live" })
59
59
  ```
60
60
 
61
+ The worker Layer is acquired and released outside the per-test environment,
62
+ using the live clock unless the Layer supplies its own. Fibers started during
63
+ Layer acquisition keep that environment; advancing a test's TestClock does not
64
+ advance their timers. The selected per-test clock applies to `around`,
65
+ `makeHarness`, and the test body.
66
+
61
67
  ## `eventually`
62
68
 
63
- Retries until the effect succeeds. Under TestClock it advances time with
64
- `TestClock.adjust`. Under `clock: "live"` it uses `Schedule.spaced`.
69
+ Retries typed failures until the effect succeeds. Under TestClock it advances
70
+ time with `TestClock.adjust`. Under `clock: "live"` it uses `Schedule.spaced`.
71
+ `times` counts retries after the initial attempt; omitting it retries without a
72
+ limit. Defects (including thrown assertions) and interruption propagate without
73
+ retrying under either clock. Use `Effect.try(() => expect(...))` when an
74
+ assertion failure is intentionally a retryable condition.
65
75
 
66
76
  ```ts
67
77
  import { eventually } from "@shivaedev/effect-test"
@@ -0,0 +1,3 @@
1
+ import type { Layer } from "effect";
2
+ export type AnyTestLayer = Layer.Layer<any, any, never>;
3
+ //# sourceMappingURL=any-test-layer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"any-test-layer.d.ts","sourceRoot":"","sources":["../src/any-test-layer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAEpC,MAAM,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=any-test-layer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"any-test-layer.js","sourceRoot":"","sources":["../src/any-test-layer.ts"],"names":[],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"eventually.d.ts","sourceRoot":"","sources":["../src/eventually.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,QAAQ,EAAE,MAAM,EAAkB,MAAM,QAAQ,CAAC;AAGtE,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC;IACnC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACxB;AAOD,eAAO,MAAM,UAAU,GAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EACjC,QAAQ,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC9B,UAAU,iBAAiB,KACzB,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CA4BrB,CAAC"}
1
+ {"version":3,"file":"eventually.d.ts","sourceRoot":"","sources":["../src/eventually.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,QAAQ,EAAE,MAAM,EAAoB,MAAM,QAAQ,CAAC;AAGxE,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC;IACnC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACxB;AAgCD,eAAO,MAAM,UAAU,GAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,QAAQ,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,iBAAiB,KAAG,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAMpH,CAAC"}
@@ -1,26 +1,22 @@
1
- import { Clock, Effect, Exit, Schedule } from "effect";
1
+ import { Clock, Effect, Result, Schedule } from "effect";
2
2
  import * as TestClock from "effect/testing/TestClock";
3
3
  const defaultInterval = "10 millis";
4
4
  const isTestClock = (clock) => "adjust" in clock;
5
- export const eventually = (effect, options) => Effect.gen(function* () {
6
- const interval = options?.interval ?? defaultInterval;
7
- const clock = yield* Clock.Clock;
8
- if (!isTestClock(clock)) {
9
- return yield* options?.times === undefined
10
- ? Effect.retry(effect, Schedule.spaced(interval))
11
- : Effect.retry(effect, {
12
- schedule: Schedule.spaced(interval),
13
- times: options.times,
14
- });
15
- }
16
- let retriesLeft = options?.times;
5
+ const retryOnLiveClock = (effect, interval, times) => times === undefined
6
+ ? Effect.retry(effect, Schedule.spaced(interval))
7
+ : Effect.retry(effect, {
8
+ schedule: Schedule.spaced(interval),
9
+ times,
10
+ });
11
+ const retryOnTestClock = (effect, interval, times) => Effect.gen(function* () {
12
+ let retriesLeft = times;
17
13
  for (;;) {
18
- const exit = yield* Effect.exit(effect);
19
- if (Exit.isSuccess(exit)) {
20
- return exit.value;
14
+ const result = yield* Effect.result(effect);
15
+ if (Result.isSuccess(result)) {
16
+ return result.success;
21
17
  }
22
18
  if (retriesLeft === 0) {
23
- return yield* exit;
19
+ return yield* Effect.fail(result.failure);
24
20
  }
25
21
  if (retriesLeft !== undefined) {
26
22
  retriesLeft -= 1;
@@ -28,4 +24,10 @@ export const eventually = (effect, options) => Effect.gen(function* () {
28
24
  yield* TestClock.adjust(interval);
29
25
  }
30
26
  });
27
+ export const eventually = (effect, options) => Effect.gen(function* () {
28
+ const interval = options?.interval ?? defaultInterval;
29
+ const clock = yield* Clock.Clock;
30
+ const retry = isTestClock(clock) ? retryOnTestClock : retryOnLiveClock;
31
+ return yield* retry(effect, interval, options?.times);
32
+ });
31
33
  //# sourceMappingURL=eventually.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"eventually.js","sourceRoot":"","sources":["../src/eventually.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAiB,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACtE,OAAO,KAAK,SAAS,MAAM,0BAA0B,CAAC;AAOtD,MAAM,eAAe,GAAG,WAAW,CAAC;AAEpC,MAAM,WAAW,GAAG,CAAC,KAAkB,EAAgC,EAAE,CACxE,QAAQ,IAAI,KAAK,CAAC;AAEnB,MAAM,CAAC,MAAM,UAAU,GAAG,CACzB,MAA8B,EAC9B,OAA2B,EACF,EAAE,CAC3B,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IACnB,MAAM,QAAQ,GAAG,OAAO,EAAE,QAAQ,IAAI,eAAe,CAAC;IACtD,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC;IAEjC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,CAAC,OAAO,EAAE,KAAK,KAAK,SAAS;YACzC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YACjD,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE;gBACrB,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC;gBACnC,KAAK,EAAE,OAAO,CAAC,KAAK;aACpB,CAAC,CAAC;IACN,CAAC;IAED,IAAI,WAAW,GAAG,OAAO,EAAE,KAAK,CAAC;IACjC,SAAS,CAAC;QACT,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxC,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1B,OAAO,IAAI,CAAC,KAAK,CAAC;QACnB,CAAC;QACD,IAAI,WAAW,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,KAAK,CAAC,CAAC,IAAI,CAAC;QACpB,CAAC;QACD,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC/B,WAAW,IAAI,CAAC,CAAC;QAClB,CAAC;QACD,KAAK,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC;AACF,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"eventually.js","sourceRoot":"","sources":["../src/eventually.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAiB,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACxE,OAAO,KAAK,SAAS,MAAM,0BAA0B,CAAC;AAOtD,MAAM,eAAe,GAAG,WAAW,CAAC;AAEpC,MAAM,WAAW,GAAG,CAAC,KAAkB,EAAgC,EAAE,CAAC,QAAQ,IAAI,KAAK,CAAC;AAE5F,MAAM,gBAAgB,GAAG,CAAU,MAA8B,EAAE,QAAwB,EAAE,KAAyB,EAA0B,EAAE,CACjJ,KAAK,KAAK,SAAS;IAClB,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACjD,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE;QACrB,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC;QACnC,KAAK;KACL,CAAC,CAAC;AAEN,MAAM,gBAAgB,GAAG,CAAU,MAA8B,EAAE,QAAwB,EAAE,KAAyB,EAA0B,EAAE,CACjJ,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IACnB,IAAI,WAAW,GAAG,KAAK,CAAC;IACxB,SAAS,CAAC;QACT,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5C,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;YAC9B,OAAO,MAAM,CAAC,OAAO,CAAC;QACvB,CAAC;QACD,IAAI,WAAW,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC3C,CAAC;QACD,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC/B,WAAW,IAAI,CAAC,CAAC;QAClB,CAAC;QACD,KAAK,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC;AACF,CAAC,CAAC,CAAC;AAEJ,MAAM,CAAC,MAAM,UAAU,GAAG,CAAU,MAA8B,EAAE,OAA2B,EAA0B,EAAE,CAC1H,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IACnB,MAAM,QAAQ,GAAG,OAAO,EAAE,QAAQ,IAAI,eAAe,CAAC;IACtD,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC;IACjC,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,gBAAgB,CAAC;IACvE,OAAO,KAAK,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;AACvD,CAAC,CAAC,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { type EventuallyOptions, eventually } from "./eventually.js";
2
- export type { EffectClock, EffectTest, EffectTester, EffectTestOptions, MakeEffectItOptions, MakeEffectItResult, } from "./types.js";
3
- export { makeEffectIt } from "./vitest.js";
1
+ export { type EventuallyOptions, eventually } from "./eventually.ts";
2
+ export type { EffectClock, EffectTest, EffectTester, EffectTestOptions, MakeEffectItOptions, MakeEffectItResult, } from "./types.ts";
3
+ export { makeEffectIt } from "./vitest.ts";
4
4
  //# sourceMappingURL=index.d.ts.map
package/dist/types.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { TestContext, TestOptions } from "@effect/vitest";
2
2
  import type { Effect, Layer } from "effect";
3
+ import type { AnyTestLayer } from "./any-test-layer.ts";
3
4
  export type EffectClock = "test" | "live";
4
5
  export type EffectTestOptions = TestOptions & {
5
6
  readonly clock?: EffectClock;
@@ -13,11 +14,11 @@ export interface EffectTester<Harness, Provided> extends EffectTest<Harness, Pro
13
14
  readonly each: <Item>(cases: ReadonlyArray<Item>) => <A, Eff extends Effect.Effect<unknown, unknown, Provided>>(name: string, body: (item: Item, harness: Harness, context: TestContext) => Generator<Eff, A, never>, options?: number | EffectTestOptions) => void;
14
15
  readonly fails: EffectTest<Harness, Provided>;
15
16
  }
16
- export interface MakeEffectItOptions<Harness, TestLayer extends Layer.Layer<any, any, never>> {
17
+ export interface MakeEffectItOptions<Harness, TestLayer extends AnyTestLayer> {
17
18
  readonly layer: TestLayer;
18
- readonly around?: <A, E>(effect: Effect.Effect<A, E, Layer.Success<TestLayer>>) => Effect.Effect<A, unknown, Layer.Success<TestLayer>>;
19
+ readonly around?: (<A, E>(effect: Effect.Effect<A, E, Layer.Success<TestLayer>>) => Effect.Effect<A, unknown, Layer.Success<TestLayer>>) | undefined;
19
20
  readonly makeHarness: (context: TestContext) => Effect.Effect<Harness, unknown, Layer.Success<TestLayer>>;
20
- readonly clock?: EffectClock;
21
+ readonly clock?: EffectClock | undefined;
21
22
  }
22
23
  export interface MakeEffectItResult<Harness, Provided> {
23
24
  readonly effectApp: EffectTester<Harness, Provided>;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC/D,OAAO,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAE5C,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,CAAC;AAE1C,MAAM,MAAM,iBAAiB,GAAG,WAAW,GAAG;IAC7C,QAAQ,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,UAAU,CAAC,OAAO,EAAE,QAAQ,IAAI,CAC3C,CAAC,EACD,GAAG,SAAS,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,EAErD,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,KAAK,SAAS,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,CAAC,EAC1E,OAAO,CAAC,EAAE,MAAM,GAAG,iBAAiB,KAChC,IAAI,CAAC;AAEV,MAAM,WAAW,YAAY,CAAC,OAAO,EAAE,QAAQ,CAC9C,SAAQ,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC;IACrC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC7C,QAAQ,CAAC,MAAM,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACvE,QAAQ,CAAC,KAAK,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACtE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC7C,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EACnB,KAAK,EAAE,aAAa,CAAC,IAAI,CAAC,KACtB,CAAC,CAAC,EAAE,GAAG,SAAS,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,EAC7D,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,CACL,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,WAAW,KAChB,SAAS,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,CAAC,EAC7B,OAAO,CAAC,EAAE,MAAM,GAAG,iBAAiB,KAChC,IAAI,CAAC;IACV,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;CAC9C;AAED,MAAM,WAAW,mBAAmB,CACnC,OAAO,EAEP,SAAS,SAAS,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC;IAE9C,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EACtB,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,KACjD,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;IACzD,QAAQ,CAAC,WAAW,EAAE,CACrB,OAAO,EAAE,WAAW,KAChB,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;IAC/D,QAAQ,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC;CAC7B;AAED,MAAM,WAAW,kBAAkB,CAAC,OAAO,EAAE,QAAQ;IACpD,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;CACpD"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/vitest.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { Layer } from "effect";
2
- import type { MakeEffectItOptions, MakeEffectItResult } from "./types.js";
3
- export declare const makeEffectIt: <Harness, TestLayer extends Layer.Layer<any, any, never>>(options: MakeEffectItOptions<Harness, TestLayer>) => MakeEffectItResult<Harness, Layer.Success<TestLayer>>;
2
+ import type { AnyTestLayer } from "./any-test-layer.ts";
3
+ import type { MakeEffectItOptions, MakeEffectItResult } from "./types.ts";
4
+ export declare const makeEffectIt: <Harness, TestLayer extends AnyTestLayer>(options: MakeEffectItOptions<Harness, TestLayer>) => MakeEffectItResult<Harness, Layer.Success<TestLayer>>;
4
5
  //# sourceMappingURL=vitest.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"vitest.d.ts","sourceRoot":"","sources":["../src/vitest.ts"],"names":[],"mappings":"AAKA,OAAO,EAAqC,KAAK,EAAS,MAAM,QAAQ,CAAC;AAGzE,OAAO,KAAK,EAKX,mBAAmB,EACnB,kBAAkB,EAClB,MAAM,YAAY,CAAC;AAyGpB,eAAO,MAAM,YAAY,GACxB,OAAO,EAEP,SAAS,SAAS,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,EAE9C,SAAS,mBAAmB,CAAC,OAAO,EAAE,SAAS,CAAC,KAC9C,kBAAkB,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAuHtD,CAAC"}
1
+ {"version":3,"file":"vitest.d.ts","sourceRoot":"","sources":["../src/vitest.ts"],"names":[],"mappings":"AACA,OAAO,EAAqC,KAAK,EAAS,MAAM,QAAQ,CAAC;AAGzE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAA4D,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAkEpI,eAAO,MAAM,YAAY,GAAI,OAAO,EAAE,SAAS,SAAS,YAAY,EACnE,SAAS,mBAAmB,CAAC,OAAO,EAAE,SAAS,CAAC,KAC9C,kBAAkB,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAyEtD,CAAC"}
package/dist/vitest.js CHANGED
@@ -1,16 +1,15 @@
1
- import { it as effectIt, } from "@effect/vitest";
1
+ import { it as effectIt } from "@effect/vitest";
2
2
  import { Cause, Effect, Exit, Layer, Scope } from "effect";
3
3
  import * as TestClock from "effect/testing/TestClock";
4
4
  import * as TestConsole from "effect/testing/TestConsole";
5
5
  const fixtureName = "__effectTestContext";
6
6
  const TestClockEnvironment = Layer.mergeAll(TestConsole.layer, TestClock.layer());
7
7
  const LiveClockEnvironment = TestConsole.layer;
8
- const environmentFor = (clock) => clock === "live" ? LiveClockEnvironment : TestClockEnvironment;
8
+ const environmentFor = (clock) => (clock === "live" ? LiveClockEnvironment : TestClockEnvironment);
9
9
  const restoreContext = (fixture, context) => ({
10
10
  ...context,
11
11
  [fixtureName]: fixture,
12
12
  });
13
- const contextFrom = (context) => context[fixtureName];
14
13
  const runEffectTest = (effect, context, clock) => Effect.runPromise(Effect.gen(function* () {
15
14
  const exit = yield* Effect.exit(effect);
16
15
  if (Exit.isFailure(exit)) {
@@ -30,9 +29,7 @@ const splitOptions = (options) => {
30
29
  const { clock, ...vitest } = options;
31
30
  return { clock, vitest };
32
31
  };
33
- const makeFixtureIt = (layer) => effectIt.extend(fixtureName, { scope: "worker" },
34
- // biome-ignore lint/correctness/noEmptyPattern: Vitest fixtures require a destructured context parameter.
35
- async ({}, { onCleanup }) => {
32
+ const makeFixtureIt = (layer) => effectIt.extend(fixtureName, { scope: "worker" }, async ({}, { onCleanup }) => {
36
33
  const scope = Effect.runSync(Scope.make());
37
34
  onCleanup(() => Effect.runPromise(Scope.close(scope, Exit.void)));
38
35
  try {
@@ -47,20 +44,17 @@ export const makeEffectIt = (options) => {
47
44
  const fixtureIt = makeFixtureIt(options.layer);
48
45
  const defaultClock = options.clock ?? "test";
49
46
  const run = (body, context) => {
50
- const program = Effect.gen(function* () {
47
+ const ready = Effect.gen(function* () {
51
48
  const harness = yield* options.makeHarness(context);
52
49
  return yield* Effect.gen(() => body(harness, context));
53
50
  });
54
- // The body constraint proves every yielded service is part of Provided.
55
- // TypeScript cannot reduce that generic generator requirement here.
56
- const ready = program;
57
51
  const wrapped = options.around?.(ready) ?? ready;
58
- return wrapped.pipe(Effect.provide(contextFrom(context)));
52
+ return wrapped.pipe(Effect.provide(context[fixtureName]));
59
53
  };
60
54
  const register = (current) => (name, body, testOptions) => {
61
55
  const split = splitOptions(testOptions);
62
56
  const clock = split.clock ?? defaultClock;
63
- current(name, split.vitest, ({ __effectTestContext, task, signal, onTestFailed, onTestFinished, skip, annotate, expect, _local, }) => {
57
+ current(name, split.vitest, ({ __effectTestContext, task, signal, onTestFailed, onTestFinished, skip, annotate, expect, _local }) => {
64
58
  const context = restoreContext(__effectTestContext, {
65
59
  annotate,
66
60
  expect,
@@ -82,7 +76,7 @@ export const makeEffectIt = (options) => {
82
76
  each: (cases) => (name, body, testOptions) => {
83
77
  const split = splitOptions(testOptions);
84
78
  const clock = split.clock ?? defaultClock;
85
- fixtureIt.for(cases)(name, split.vitest, (item, { __effectTestContext, task, signal, onTestFailed, onTestFinished, skip, annotate, expect, _local, }) => {
79
+ fixtureIt.for(cases)(name, split.vitest, (item, { __effectTestContext, task, signal, onTestFailed, onTestFinished, skip, annotate, expect, _local }) => {
86
80
  const context = restoreContext(__effectTestContext, {
87
81
  annotate,
88
82
  expect,
@@ -93,7 +87,7 @@ export const makeEffectIt = (options) => {
93
87
  task,
94
88
  _local,
95
89
  });
96
- return runEffectTest(run((harness, testContext) => body(item, harness, testContext), context), context, clock);
90
+ return runEffectTest(Effect.asVoid(run((harness, testContext) => body(item, harness, testContext), context)), context, clock);
97
91
  });
98
92
  },
99
93
  fails: register(fixtureIt.fails),
@@ -1 +1 @@
1
- {"version":3,"file":"vitest.js","sourceRoot":"","sources":["../src/vitest.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"vitest.js","sourceRoot":"","sources":["../src/vitest.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shivaedev/effect-test",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Generic Effect Vitest runner with worker-scoped Layers and TestClock",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -0,0 +1,3 @@
1
+ import type { Layer } from "effect";
2
+
3
+ export type AnyTestLayer = Layer.Layer<any, any, never>;
package/src/eventually.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Clock, type Duration, Effect, Exit, Schedule } from "effect";
1
+ import { Clock, type Duration, Effect, Result, Schedule } from "effect";
2
2
  import * as TestClock from "effect/testing/TestClock";
3
3
 
4
4
  export interface EventuallyOptions {
@@ -8,34 +8,26 @@ export interface EventuallyOptions {
8
8
 
9
9
  const defaultInterval = "10 millis";
10
10
 
11
- const isTestClock = (clock: Clock.Clock): clock is TestClock.TestClock =>
12
- "adjust" in clock;
11
+ const isTestClock = (clock: Clock.Clock): clock is TestClock.TestClock => "adjust" in clock;
13
12
 
14
- export const eventually = <A, E, R>(
15
- effect: Effect.Effect<A, E, R>,
16
- options?: EventuallyOptions,
17
- ): Effect.Effect<A, E, R> =>
18
- Effect.gen(function* () {
19
- const interval = options?.interval ?? defaultInterval;
20
- const clock = yield* Clock.Clock;
13
+ const retryOnLiveClock = <A, E, R>(effect: Effect.Effect<A, E, R>, interval: Duration.Input, times: number | undefined): Effect.Effect<A, E, R> =>
14
+ times === undefined
15
+ ? Effect.retry(effect, Schedule.spaced(interval))
16
+ : Effect.retry(effect, {
17
+ schedule: Schedule.spaced(interval),
18
+ times,
19
+ });
21
20
 
22
- if (!isTestClock(clock)) {
23
- return yield* options?.times === undefined
24
- ? Effect.retry(effect, Schedule.spaced(interval))
25
- : Effect.retry(effect, {
26
- schedule: Schedule.spaced(interval),
27
- times: options.times,
28
- });
29
- }
30
-
31
- let retriesLeft = options?.times;
21
+ const retryOnTestClock = <A, E, R>(effect: Effect.Effect<A, E, R>, interval: Duration.Input, times: number | undefined): Effect.Effect<A, E, R> =>
22
+ Effect.gen(function* () {
23
+ let retriesLeft = times;
32
24
  for (;;) {
33
- const exit = yield* Effect.exit(effect);
34
- if (Exit.isSuccess(exit)) {
35
- return exit.value;
25
+ const result = yield* Effect.result(effect);
26
+ if (Result.isSuccess(result)) {
27
+ return result.success;
36
28
  }
37
29
  if (retriesLeft === 0) {
38
- return yield* exit;
30
+ return yield* Effect.fail(result.failure);
39
31
  }
40
32
  if (retriesLeft !== undefined) {
41
33
  retriesLeft -= 1;
@@ -43,3 +35,11 @@ export const eventually = <A, E, R>(
43
35
  yield* TestClock.adjust(interval);
44
36
  }
45
37
  });
38
+
39
+ export const eventually = <A, E, R>(effect: Effect.Effect<A, E, R>, options?: EventuallyOptions): Effect.Effect<A, E, R> =>
40
+ Effect.gen(function* () {
41
+ const interval = options?.interval ?? defaultInterval;
42
+ const clock = yield* Clock.Clock;
43
+ const retry = isTestClock(clock) ? retryOnTestClock : retryOnLiveClock;
44
+ return yield* retry(effect, interval, options?.times);
45
+ });
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { type EventuallyOptions, eventually } from "./eventually.js";
1
+ export { type EventuallyOptions, eventually } from "./eventually.ts";
2
2
  export type {
3
3
  EffectClock,
4
4
  EffectTest,
@@ -6,5 +6,5 @@ export type {
6
6
  EffectTestOptions,
7
7
  MakeEffectItOptions,
8
8
  MakeEffectItResult,
9
- } from "./types.js";
10
- export { makeEffectIt } from "./vitest.js";
9
+ } from "./types.ts";
10
+ export { makeEffectIt } from "./vitest.ts";
package/src/types.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { TestContext, TestOptions } from "@effect/vitest";
2
2
  import type { Effect, Layer } from "effect";
3
+ import type { AnyTestLayer } from "./any-test-layer.ts";
3
4
 
4
5
  export type EffectClock = "test" | "live";
5
6
 
@@ -7,17 +8,13 @@ export type EffectTestOptions = TestOptions & {
7
8
  readonly clock?: EffectClock;
8
9
  };
9
10
 
10
- export type EffectTest<Harness, Provided> = <
11
- A,
12
- Eff extends Effect.Effect<unknown, unknown, Provided>,
13
- >(
11
+ export type EffectTest<Harness, Provided> = <A, Eff extends Effect.Effect<unknown, unknown, Provided>>(
14
12
  name: string,
15
13
  body: (harness: Harness, context: TestContext) => Generator<Eff, A, never>,
16
14
  options?: number | EffectTestOptions,
17
15
  ) => void;
18
16
 
19
- export interface EffectTester<Harness, Provided>
20
- extends EffectTest<Harness, Provided> {
17
+ export interface EffectTester<Harness, Provided> extends EffectTest<Harness, Provided> {
21
18
  readonly skip: EffectTest<Harness, Provided>;
22
19
  readonly skipIf: (condition: unknown) => EffectTest<Harness, Provided>;
23
20
  readonly runIf: (condition: unknown) => EffectTest<Harness, Provided>;
@@ -26,29 +23,19 @@ export interface EffectTester<Harness, Provided>
26
23
  cases: ReadonlyArray<Item>,
27
24
  ) => <A, Eff extends Effect.Effect<unknown, unknown, Provided>>(
28
25
  name: string,
29
- body: (
30
- item: Item,
31
- harness: Harness,
32
- context: TestContext,
33
- ) => Generator<Eff, A, never>,
26
+ body: (item: Item, harness: Harness, context: TestContext) => Generator<Eff, A, never>,
34
27
  options?: number | EffectTestOptions,
35
28
  ) => void;
36
29
  readonly fails: EffectTest<Harness, Provided>;
37
30
  }
38
31
 
39
- export interface MakeEffectItOptions<
40
- Harness,
41
- // biome-ignore lint/suspicious/noExplicitAny: Layer output and error are recovered with Layer utility types
42
- TestLayer extends Layer.Layer<any, any, never>,
43
- > {
32
+ export interface MakeEffectItOptions<Harness, TestLayer extends AnyTestLayer> {
44
33
  readonly layer: TestLayer;
45
- readonly around?: <A, E>(
46
- effect: Effect.Effect<A, E, Layer.Success<TestLayer>>,
47
- ) => Effect.Effect<A, unknown, Layer.Success<TestLayer>>;
48
- readonly makeHarness: (
49
- context: TestContext,
50
- ) => Effect.Effect<Harness, unknown, Layer.Success<TestLayer>>;
51
- readonly clock?: EffectClock;
34
+ readonly around?:
35
+ | (<A, E>(effect: Effect.Effect<A, E, Layer.Success<TestLayer>>) => Effect.Effect<A, unknown, Layer.Success<TestLayer>>)
36
+ | undefined;
37
+ readonly makeHarness: (context: TestContext) => Effect.Effect<Harness, unknown, Layer.Success<TestLayer>>;
38
+ readonly clock?: EffectClock | undefined;
52
39
  }
53
40
 
54
41
  export interface MakeEffectItResult<Harness, Provided> {
package/src/vitest.ts CHANGED
@@ -1,19 +1,9 @@
1
- import {
2
- it as effectIt,
3
- type TestContext,
4
- type TestOptions,
5
- } from "@effect/vitest";
1
+ import { it as effectIt, type TestContext, type TestOptions } from "@effect/vitest";
6
2
  import { Cause, type Context, Effect, Exit, Layer, Scope } from "effect";
7
3
  import * as TestClock from "effect/testing/TestClock";
8
4
  import * as TestConsole from "effect/testing/TestConsole";
9
- import type {
10
- EffectClock,
11
- EffectTest,
12
- EffectTester,
13
- EffectTestOptions,
14
- MakeEffectItOptions,
15
- MakeEffectItResult,
16
- } from "./types.js";
5
+ import type { AnyTestLayer } from "./any-test-layer.ts";
6
+ import type { EffectClock, EffectTest, EffectTester, EffectTestOptions, MakeEffectItOptions, MakeEffectItResult } from "./types.ts";
17
7
 
18
8
  const fixtureName = "__effectTestContext";
19
9
 
@@ -21,54 +11,22 @@ type EffectFixture<Provided> = TestContext & {
21
11
  readonly [fixtureName]: Context.Context<Provided>;
22
12
  };
23
13
 
24
- interface FixtureTestApi<Provided> {
25
- (
26
- name: string,
27
- options: TestOptions,
28
- body: (context: EffectFixture<Provided>) => Promise<unknown>,
29
- ): void;
30
- readonly skip: FixtureTestApi<Provided>;
31
- readonly skipIf: (condition: unknown) => FixtureTestApi<Provided>;
32
- readonly runIf: (condition: unknown) => FixtureTestApi<Provided>;
33
- readonly only: FixtureTestApi<Provided>;
34
- readonly fails: FixtureTestApi<Provided>;
35
- readonly for: <Item>(
36
- cases: ReadonlyArray<Item>,
37
- ) => (
38
- name: string,
39
- options: TestOptions,
40
- body: (item: Item, context: EffectFixture<Provided>) => Promise<unknown>,
41
- ) => void;
42
- }
14
+ type FixtureTest<Provided> = (name: string, options: TestOptions, body: (context: EffectFixture<Provided>) => Promise<unknown>) => void;
43
15
 
44
- const TestClockEnvironment = Layer.mergeAll(
45
- TestConsole.layer,
46
- TestClock.layer(),
47
- );
16
+ const TestClockEnvironment = Layer.mergeAll(TestConsole.layer, TestClock.layer());
48
17
  const LiveClockEnvironment = TestConsole.layer;
49
18
 
50
- const environmentFor = (clock: EffectClock) =>
51
- clock === "live" ? LiveClockEnvironment : TestClockEnvironment;
19
+ const environmentFor = (clock: EffectClock) => (clock === "live" ? LiveClockEnvironment : TestClockEnvironment);
52
20
 
53
21
  const restoreContext = <Provided>(
54
22
  fixture: Context.Context<Provided>,
55
23
  context: Omit<EffectFixture<Provided>, typeof fixtureName>,
56
- ): EffectFixture<Provided> =>
57
- ({
58
- ...context,
59
- [fixtureName]: fixture,
60
- }) as EffectFixture<Provided>;
24
+ ): EffectFixture<Provided> => ({
25
+ ...context,
26
+ [fixtureName]: fixture,
27
+ });
61
28
 
62
- const contextFrom = <Provided>(
63
- context: TestContext,
64
- ): Context.Context<Provided> =>
65
- (context as EffectFixture<Provided>)[fixtureName];
66
-
67
- const runEffectTest = <A, E>(
68
- effect: Effect.Effect<A, E, Scope.Scope>,
69
- context: TestContext,
70
- clock: EffectClock,
71
- ): Promise<A> =>
29
+ const runEffectTest = <A, E>(effect: Effect.Effect<A, E, Scope.Scope>, context: TestContext, clock: EffectClock): Promise<A> =>
72
30
  Effect.runPromise(
73
31
  Effect.gen(function* () {
74
32
  const exit = yield* Effect.exit(effect);
@@ -98,149 +56,92 @@ const splitOptions = (
98
56
  return { clock, vitest };
99
57
  };
100
58
 
101
- const makeFixtureIt = <Provided, LayerError>(
102
- layer: Layer.Layer<Provided, LayerError>,
103
- ): FixtureTestApi<Provided> =>
104
- effectIt.extend(
105
- fixtureName,
106
- { scope: "worker" },
107
- // biome-ignore lint/correctness/noEmptyPattern: Vitest fixtures require a destructured context parameter.
108
- async ({}, { onCleanup }) => {
109
- const scope = Effect.runSync(Scope.make());
110
- onCleanup(() => Effect.runPromise(Scope.close(scope, Exit.void)));
59
+ const makeFixtureIt = <Provided, LayerError>(layer: Layer.Layer<Provided, LayerError>) =>
60
+ effectIt.extend(fixtureName, { scope: "worker" }, async ({}, { onCleanup }) => {
61
+ const scope = Effect.runSync(Scope.make());
62
+ onCleanup(() => Effect.runPromise(Scope.close(scope, Exit.void)));
111
63
 
112
- try {
113
- return await Effect.runPromise(Layer.buildWithScope(layer, scope));
114
- } catch (error) {
115
- await Effect.runPromise(Scope.close(scope, Exit.void));
116
- throw error;
117
- }
118
- },
119
- ) as unknown as FixtureTestApi<Provided>;
64
+ try {
65
+ return await Effect.runPromise(Layer.buildWithScope(layer, scope));
66
+ } catch (error) {
67
+ await Effect.runPromise(Scope.close(scope, Exit.void));
68
+ throw error;
69
+ }
70
+ });
120
71
 
121
- export const makeEffectIt = <
122
- Harness,
123
- // biome-ignore lint/suspicious/noExplicitAny: Layer output and error are recovered with Layer utility types
124
- TestLayer extends Layer.Layer<any, any, never>,
125
- >(
72
+ export const makeEffectIt = <Harness, TestLayer extends AnyTestLayer>(
126
73
  options: MakeEffectItOptions<Harness, TestLayer>,
127
74
  ): MakeEffectItResult<Harness, Layer.Success<TestLayer>> => {
128
75
  type Provided = Layer.Success<TestLayer>;
129
76
  const fixtureIt = makeFixtureIt(options.layer);
130
77
  const defaultClock = options.clock ?? "test";
131
78
 
132
- const run = <A, Eff extends Effect.Effect<unknown, unknown, Provided>>(
133
- body: (harness: Harness, context: TestContext) => Generator<Eff, A, never>,
134
- context: TestContext,
79
+ const run = <A>(
80
+ body: (harness: Harness, context: TestContext) => Generator<Effect.Effect<unknown, unknown, Provided>, A, never>,
81
+ context: EffectFixture<Provided>,
135
82
  ): Effect.Effect<A, unknown, Scope.Scope> => {
136
- const program = Effect.gen(function* () {
83
+ const ready: Effect.Effect<A, unknown, Provided> = Effect.gen(function* () {
137
84
  const harness = yield* options.makeHarness(context);
138
85
  return yield* Effect.gen(() => body(harness, context));
139
86
  });
140
- // The body constraint proves every yielded service is part of Provided.
141
- // TypeScript cannot reduce that generic generator requirement here.
142
- const ready = program as Effect.Effect<A, unknown, Provided>;
143
87
  const wrapped = options.around?.(ready) ?? ready;
144
- return wrapped.pipe(
145
- Effect.provide(contextFrom<Provided>(context)),
146
- ) as Effect.Effect<A, unknown, Scope.Scope>;
88
+ return wrapped.pipe(Effect.provide(context[fixtureName]));
147
89
  };
148
90
 
149
91
  const register =
150
- (current: FixtureTestApi<Provided>): EffectTest<Harness, Provided> =>
92
+ (current: FixtureTest<Provided>): EffectTest<Harness, Provided> =>
151
93
  (name, body, testOptions) => {
152
94
  const split = splitOptions(testOptions);
153
95
  const clock = split.clock ?? defaultClock;
154
- current(
155
- name,
156
- split.vitest,
157
- ({
158
- __effectTestContext,
159
- task,
160
- signal,
96
+ current(name, split.vitest, ({ __effectTestContext, task, signal, onTestFailed, onTestFinished, skip, annotate, expect, _local }) => {
97
+ const context = restoreContext(__effectTestContext, {
98
+ annotate,
99
+ expect,
161
100
  onTestFailed,
162
101
  onTestFinished,
102
+ signal,
163
103
  skip,
164
- annotate,
165
- expect,
104
+ task,
166
105
  _local,
167
- }) => {
168
- const context = restoreContext(__effectTestContext, {
169
- annotate,
170
- expect,
171
- onTestFailed,
172
- onTestFinished,
173
- signal,
174
- skip,
175
- task,
176
- _local,
177
- });
178
- return runEffectTest(run(body, context), context, clock);
179
- },
180
- );
106
+ });
107
+ return runEffectTest(run(body, context), context, clock);
108
+ });
181
109
  };
182
110
 
183
- const effectApp: EffectTester<Harness, Provided> = Object.assign(
184
- register(fixtureIt),
185
- {
186
- skip: register(fixtureIt.skip),
187
- skipIf: (condition: unknown) => register(fixtureIt.skipIf(condition)),
188
- runIf: (condition: unknown) => register(fixtureIt.runIf(condition)),
189
- only: register(fixtureIt.only),
190
- each:
191
- <Item>(cases: ReadonlyArray<Item>) =>
192
- <A, Eff extends Effect.Effect<unknown, unknown, Provided>>(
193
- name: string,
194
- body: (
195
- item: Item,
196
- harness: Harness,
197
- context: TestContext,
198
- ) => Generator<Eff, A, never>,
199
- testOptions?: number | EffectTestOptions,
200
- ) => {
201
- const split = splitOptions(testOptions);
202
- const clock = split.clock ?? defaultClock;
203
- fixtureIt.for(cases)(
204
- name,
205
- split.vitest,
206
- (
207
- item,
208
- {
209
- __effectTestContext,
210
- task,
211
- signal,
212
- onTestFailed,
213
- onTestFinished,
214
- skip,
215
- annotate,
216
- expect,
217
- _local,
218
- },
219
- ) => {
220
- const context = restoreContext(__effectTestContext, {
221
- annotate,
222
- expect,
223
- onTestFailed,
224
- onTestFinished,
225
- signal,
226
- skip,
227
- task,
228
- _local,
229
- });
230
- return runEffectTest(
231
- run(
232
- (harness, testContext) => body(item, harness, testContext),
233
- context,
234
- ),
235
- context,
236
- clock,
237
- );
238
- },
239
- );
240
- },
241
- fails: register(fixtureIt.fails),
242
- },
243
- );
111
+ const effectApp: EffectTester<Harness, Provided> = Object.assign(register(fixtureIt), {
112
+ skip: register(fixtureIt.skip),
113
+ skipIf: (condition: unknown) => register(fixtureIt.skipIf(condition)),
114
+ runIf: (condition: unknown) => register(fixtureIt.runIf(condition)),
115
+ only: register(fixtureIt.only),
116
+ each:
117
+ <Item>(cases: ReadonlyArray<Item>) =>
118
+ <A, Eff extends Effect.Effect<unknown, unknown, Provided>>(
119
+ name: string,
120
+ body: (item: Item, harness: Harness, context: TestContext) => Generator<Eff, A, never>,
121
+ testOptions?: number | EffectTestOptions,
122
+ ) => {
123
+ const split = splitOptions(testOptions);
124
+ const clock = split.clock ?? defaultClock;
125
+ fixtureIt.for(cases)(
126
+ name,
127
+ split.vitest,
128
+ (item, { __effectTestContext, task, signal, onTestFailed, onTestFinished, skip, annotate, expect, _local }) => {
129
+ const context = restoreContext(__effectTestContext, {
130
+ annotate,
131
+ expect,
132
+ onTestFailed,
133
+ onTestFinished,
134
+ signal,
135
+ skip,
136
+ task,
137
+ _local,
138
+ });
139
+ return runEffectTest(Effect.asVoid(run((harness, testContext) => body(item, harness, testContext), context)), context, clock);
140
+ },
141
+ );
142
+ },
143
+ fails: register(fixtureIt.fails),
144
+ });
244
145
 
245
146
  return { effectApp };
246
147
  };