/** * @since 4.0.0 */ import type * as Duration from "effect/Duration" import type * as Effect from "effect/Effect" import type * as Layer from "effect/Layer" import type * as Schema from "effect/Schema" import type * as Scope from "effect/Scope" import type * as FC from "effect/testing/FastCheck" import * as V from "vitest" import * as internal from "./internal/internal.ts" /** * @since 4.0.0 */ export * from "vitest" /** * @since 4.0.0 */ export type API = V.TestAPI<{}> /** * @since 4.0.0 */ export namespace Vitest { /** * @since 4.0.0 */ export interface TestFunction> { (...args: TestArgs): Effect.Effect } /** * @since 4.0.0 */ export interface Test { ( name: string, self: TestFunction, timeout?: number | V.TestOptions ): void } /** * @since 4.0.0 */ export type Arbitraries = | Array | FC.Arbitrary> | { [K in string]: Schema.Schema | FC.Arbitrary } /** * @since 4.0.0 */ export interface Tester extends Vitest.Test { skip: Vitest.Test skipIf: (condition: unknown) => Vitest.Test runIf: (condition: unknown) => Vitest.Test only: Vitest.Test each: ( cases: ReadonlyArray ) => (name: string, self: TestFunction>, timeout?: number | V.TestOptions) => void fails: Vitest.Test /** * @since 4.0.0 */ prop: ( name: string, arbitraries: Arbs, self: TestFunction< A, E, R, [ { [K in keyof Arbs]: Arbs[K] extends FC.Arbitrary ? T : Arbs[K] extends Schema.Schema ? T : never }, V.TestContext ] >, timeout?: | number | V.TestOptions & { fastCheck?: FC.Parameters< { [K in keyof Arbs]: Arbs[K] extends FC.Arbitrary ? T : Arbs[K] extends Schema.Schema ? T : never } > } ) => void } /** * @since 4.0.0 */ export interface MethodsNonLive extends API { readonly effect: Vitest.Tester readonly flakyTest: ( self: Effect.Effect, timeout?: Duration.Input ) => Effect.Effect readonly layer: (layer: Layer.Layer, options?: { readonly timeout?: Duration.Input }) => { (f: (it: Vitest.MethodsNonLive) => void): void ( name: string, f: (it: Vitest.MethodsNonLive) => void ): void } /** * @since 4.0.0 */ readonly prop: ( name: string, arbitraries: Arbs, self: ( properties: { [K in keyof Arbs]: Arbs[K] extends FC.Arbitrary ? T : Arbs[K] extends Schema.Schema ? T : never }, ctx: V.TestContext ) => void, timeout?: | number | V.TestOptions & { fastCheck?: FC.Parameters< { [K in keyof Arbs]: Arbs[K] extends FC.Arbitrary ? T : Arbs[K] extends Schema.Schema ? T : never } > } ) => void } /** * @since 4.0.0 */ export interface Methods extends MethodsNonLive { readonly live: Vitest.Tester readonly layer: (layer: Layer.Layer, options?: { readonly memoMap?: Layer.MemoMap readonly timeout?: Duration.Input readonly excludeTestServices?: boolean }) => { (f: (it: Vitest.MethodsNonLive) => void): void ( name: string, f: (it: Vitest.MethodsNonLive) => void ): void } } } /** * @since 4.0.0 */ export const addEqualityTesters: () => void = internal.addEqualityTesters /** * @since 4.0.0 */ export const effect: Vitest.Tester = internal.effect /** * @since 4.0.0 */ export const live: Vitest.Tester = internal.live /** * Share a `Layer` between multiple tests, optionally wrapping * the tests in a `describe` block if a name is provided. * * @since 4.0.0 * * ```ts * import { expect, layer } from "@effect/vitest" * import { Effect, Layer, Context } from "effect" * * class Foo extends Context.Service("Foo")() { * static Live = Layer.succeed(Foo, "foo") * } * * class Bar extends Context.Service("Bar")() { * static Live = Layer.effect( * Bar, * Effect.map(Foo, () => "bar" as const) * ) * } * * layer(Foo.Live)("layer", (it) => { * it.effect("adds context", () => * Effect.gen(function*() { * const foo = yield* Foo * expect(foo).toEqual("foo") * })) * * it.layer(Bar.Live)("nested", (it) => { * it.effect("adds context", () => * Effect.gen(function*() { * const foo = yield* Foo * const bar = yield* Bar * expect(foo).toEqual("foo") * expect(bar).toEqual("bar") * })) * }) * }) * ``` */ export const layer: ( layer_: Layer.Layer, options?: { readonly memoMap?: Layer.MemoMap readonly timeout?: Duration.Input readonly excludeTestServices?: boolean } ) => { (f: (it: Vitest.MethodsNonLive) => void): void (name: string, f: (it: Vitest.MethodsNonLive) => void): void } = internal.layer /** * @since 4.0.0 */ export const flakyTest: ( self: Effect.Effect, timeout?: Duration.Input ) => Effect.Effect = internal.flakyTest /** * @since 4.0.0 */ export const prop: Vitest.Methods["prop"] = internal.prop /** * @since 4.0.0 */ /** * @since 4.0.0 */ export const it: Vitest.Methods = internal.makeMethods(V.it) /** * @since 4.0.0 */ export const makeMethods: (it: V.TestAPI) => Vitest.Methods = internal.makeMethods /** * @since 4.0.0 */ export const describeWrapped: (name: string, f: (it: Vitest.Methods) => void) => V.SuiteCollector = internal.describeWrapped