summaryrefslogtreecommitdiffhomepage
path: root/packages/core/test/lib/effect.ts
diff options
context:
space:
mode:
authorDax <[email protected]>2026-04-25 10:59:17 -0400
committerGitHub <[email protected]>2026-04-25 10:59:17 -0400
commit62ef2a220723a6d6cb050e523fcdfaa974dafdda (patch)
tree214b03d016e18e4d8fe1bfc7209c1edd86547bbd /packages/core/test/lib/effect.ts
parent37aa8442dc023fad250f2573c8235a544789900c (diff)
downloadopencode-62ef2a220723a6d6cb050e523fcdfaa974dafdda.tar.gz
opencode-62ef2a220723a6d6cb050e523fcdfaa974dafdda.zip
refactor: rename shared package to core (#24309)
Diffstat (limited to 'packages/core/test/lib/effect.ts')
-rw-r--r--packages/core/test/lib/effect.ts53
1 files changed, 53 insertions, 0 deletions
diff --git a/packages/core/test/lib/effect.ts b/packages/core/test/lib/effect.ts
new file mode 100644
index 000000000..131ec5cc6
--- /dev/null
+++ b/packages/core/test/lib/effect.ts
@@ -0,0 +1,53 @@
+import { test, type TestOptions } from "bun:test"
+import { Cause, Effect, Exit, Layer } from "effect"
+import type * as Scope from "effect/Scope"
+import * as TestClock from "effect/testing/TestClock"
+import * as TestConsole from "effect/testing/TestConsole"
+
+type Body<A, E, R> = Effect.Effect<A, E, R> | (() => Effect.Effect<A, E, R>)
+
+const body = <A, E, R>(value: Body<A, E, R>) => Effect.suspend(() => (typeof value === "function" ? value() : value))
+
+const run = <A, E, R, E2>(value: Body<A, E, R | Scope.Scope>, layer: Layer.Layer<R, E2>) =>
+ Effect.gen(function* () {
+ const exit = yield* body(value).pipe(Effect.scoped, Effect.provide(layer), Effect.exit)
+ if (Exit.isFailure(exit)) {
+ for (const err of Cause.prettyErrors(exit.cause)) {
+ yield* Effect.logError(err)
+ }
+ }
+ return yield* exit
+ }).pipe(Effect.runPromise)
+
+const make = <R, E>(testLayer: Layer.Layer<R, E>, liveLayer: Layer.Layer<R, E>) => {
+ const effect = <A, E2>(name: string, value: Body<A, E2, R | Scope.Scope>, opts?: number | TestOptions) =>
+ test(name, () => run(value, testLayer), opts)
+
+ effect.only = <A, E2>(name: string, value: Body<A, E2, R | Scope.Scope>, opts?: number | TestOptions) =>
+ test.only(name, () => run(value, testLayer), opts)
+
+ effect.skip = <A, E2>(name: string, value: Body<A, E2, R | Scope.Scope>, opts?: number | TestOptions) =>
+ test.skip(name, () => run(value, testLayer), opts)
+
+ const live = <A, E2>(name: string, value: Body<A, E2, R | Scope.Scope>, opts?: number | TestOptions) =>
+ test(name, () => run(value, liveLayer), opts)
+
+ live.only = <A, E2>(name: string, value: Body<A, E2, R | Scope.Scope>, opts?: number | TestOptions) =>
+ test.only(name, () => run(value, liveLayer), opts)
+
+ live.skip = <A, E2>(name: string, value: Body<A, E2, R | Scope.Scope>, opts?: number | TestOptions) =>
+ test.skip(name, () => run(value, liveLayer), opts)
+
+ return { effect, live }
+}
+
+// Test environment with TestClock and TestConsole
+const testEnv = Layer.mergeAll(TestConsole.layer, TestClock.layer())
+
+// Live environment - uses real clock, but keeps TestConsole for output capture
+const liveEnv = TestConsole.layer
+
+export const it = make(testEnv, liveEnv)
+
+export const testEffect = <R, E>(layer: Layer.Layer<R, E>) =>
+ make(Layer.provideMerge(layer, testEnv), Layer.provideMerge(layer, liveEnv))