Skip to content

Commit

Permalink
Support native arbitraries in @effect/vitest (#4173)
Browse files Browse the repository at this point in the history
  • Loading branch information
thewilkybarkid authored Dec 22, 2024
1 parent a1ca621 commit 62f12d8
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 24 deletions.
5 changes: 5 additions & 0 deletions .changeset/shiny-timers-agree.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@effect/vitest": minor
---

Support native arbitraries in @effect/vitest
26 changes: 16 additions & 10 deletions packages/vitest/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/
import type * as Duration from "effect/Duration"
import type * as Effect from "effect/Effect"
import type * as FastCheck from "effect/FastCheck"
import type * as Layer from "effect/Layer"
import type * as Schema from "effect/Schema"
import type * as Scope from "effect/Scope"
Expand Down Expand Up @@ -40,7 +41,9 @@ export namespace Vitest {
/**
* @since 1.0.0
*/
export type SchemaObj = Array<Schema.Schema.Any> | { [K in string]: Schema.Schema.Any }
export type Arbitraries =
| Array<Schema.Schema.Any | FastCheck.Arbitrary<any>>
| { [K in string]: Schema.Schema.Any | FastCheck.Arbitrary<any> }

/**
* @since 1.0.0
Expand All @@ -57,14 +60,17 @@ export namespace Vitest {
/**
* @since 1.0.0
*/
prop: <const S extends SchemaObj, A, E>(
prop: <const Arbs extends Arbitraries, A, E>(
name: string,
schemas: S,
arbitraries: Arbs,
self: TestFunction<
A,
E,
R,
[{ [K in keyof S]: Schema.Schema.Type<S[K]> }, V.TaskContext<V.RunnerTestCase<{}>> & V.TestContext]
[
{ [K in keyof Arbs]: Arbs[K] extends FastCheck.Arbitrary<infer T> ? T : Schema.Schema.Type<Arbs[K]> },
V.TaskContext<V.RunnerTestCase<{}>> & V.TestContext
]
>,
timeout?: number | V.TestOptions
) => void
Expand Down Expand Up @@ -92,11 +98,11 @@ export namespace Vitest {
/**
* @since 1.0.0
*/
readonly prop: <const S extends SchemaObj>(
readonly prop: <const Arbs extends Arbitraries>(
name: string,
schemas: S,
arbitraries: Arbs,
self: (
schemas: { [K in keyof S]: Schema.Schema.Type<S[K]> },
properties: { [K in keyof Arbs]: K extends FastCheck.Arbitrary<infer T> ? T : Schema.Schema.Type<Arbs[K]> },
ctx: V.TaskContext<V.RunnerTestCase<{}>> & V.TestContext
) => void,
timeout?: number | V.TestOptions
Expand Down Expand Up @@ -188,11 +194,11 @@ export const flakyTest: <A, E, R>(
/**
* @since 1.0.0
*/
export const prop: <const S extends Vitest.SchemaObj>(
export const prop: <const Arbs extends Vitest.Arbitraries>(
name: string,
schemas: S,
arbitraries: Arbs,
self: (
schemas: { [K in keyof S]: Schema.Schema.Type<S[K]> },
properties: { [K in keyof Arbs]: K extends FastCheck.Arbitrary<infer T> ? T : Schema.Schema.Type<Arbs[K]> },
ctx: V.TaskContext<V.RunnerTestCase<{}>> & V.TestContext
) => void,
timeout?: number | V.TestOptions
Expand Down
21 changes: 11 additions & 10 deletions packages/vitest/src/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { flow, identity, pipe } from "effect/Function"
import * as Layer from "effect/Layer"
import * as Logger from "effect/Logger"
import * as Schedule from "effect/Schedule"
import * as Schema from "effect/Schema"
import * as Scope from "effect/Scope"
import * as TestEnvironment from "effect/TestContext"
import type * as TestServices from "effect/TestServices"
Expand Down Expand Up @@ -97,9 +98,9 @@ const makeTester = <R>(
(args, ctx) => run(ctx, [args], self) as any
)

const prop: Vitest.Vitest.Tester<R>["prop"] = (name, schemaObj, self, timeout) => {
if (Array.isArray(schemaObj)) {
const arbs = schemaObj.map((schema) => Arbitrary.make(schema))
const prop: Vitest.Vitest.Tester<R>["prop"] = (name, arbitraries, self, timeout) => {
if (Array.isArray(arbitraries)) {
const arbs = arbitraries.map((arbitrary) => Schema.isSchema(arbitrary) ? Arbitrary.make(arbitrary) : arbitrary)
return V.it(
name,
// @ts-ignore
Expand All @@ -109,8 +110,8 @@ const makeTester = <R>(
}

const arbs = fc.record(
Object.keys(schemaObj).reduce(function(result, key) {
result[key] = Arbitrary.make(schemaObj[key])
Object.keys(arbitraries).reduce(function(result, key) {
result[key] = Schema.isSchema(arbitraries[key]) ? Arbitrary.make(arbitraries[key]) : arbitraries[key]
return result
}, {} as Record<string, fc.Arbitrary<any>>)
)
Expand All @@ -126,9 +127,9 @@ const makeTester = <R>(
return Object.assign(f, { skip, skipIf, runIf, only, each, prop })
}

export const prop: Vitest.Vitest.Methods["prop"] = (name, schemaObj, self, timeout) => {
if (Array.isArray(schemaObj)) {
const arbs = schemaObj.map((schema) => Arbitrary.make(schema))
export const prop: Vitest.Vitest.Methods["prop"] = (name, arbitraries, self, timeout) => {
if (Array.isArray(arbitraries)) {
const arbs = arbitraries.map((arbitrary) => Schema.isSchema(arbitrary) ? Arbitrary.make(arbitrary) : arbitrary)
return V.it(
name,
// @ts-ignore
Expand All @@ -138,8 +139,8 @@ export const prop: Vitest.Vitest.Methods["prop"] = (name, schemaObj, self, timeo
}

const arbs = fc.record(
Object.keys(schemaObj).reduce(function(result, key) {
result[key] = Arbitrary.make(schemaObj[key])
Object.keys(arbitraries).reduce(function(result, key) {
result[key] = Schema.isSchema(arbitraries[key]) ? Arbitrary.make(arbitraries[key]) : arbitraries[key]
return result
}, {} as Record<string, fc.Arbitrary<any>>)
)
Expand Down
22 changes: 18 additions & 4 deletions packages/vitest/test/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { afterAll, describe, expect, it, layer } from "@effect/vitest"
import { Context, Effect, Layer, Schema } from "effect"
import { Context, Effect, FastCheck, Layer, Schema } from "effect"

it.live(
"live %s",
Expand Down Expand Up @@ -160,17 +160,31 @@ layer(Foo.Live)("layer", (it) => {

const realNumber = Schema.Finite.pipe(Schema.nonNaN())

it.prop("symmetry", [realNumber, realNumber], ([a, b]) => a + b === b + a)
it.prop("symmetry", [realNumber, FastCheck.integer()], ([a, b]) => a + b === b + a)

it.effect.prop("symmetry", [realNumber, realNumber], ([a, b]) =>
it.prop(
"symmetry with object",
{ a: realNumber, b: FastCheck.integer() },
({ a, b }) => a + b === b + a
)

it.effect.prop("symmetry", [realNumber, FastCheck.integer()], ([a, b]) =>
Effect.gen(function*() {
yield* Effect.void

return a + b === b + a
}))

it.effect.prop("symmetry with object", { a: realNumber, b: FastCheck.integer() }, ({ a, b }) =>
Effect.gen(function*() {
yield* Effect.void

return a + b === b + a
}))

it.scoped.prop(
"should detect the substring",
{ a: Schema.String, b: Schema.String, c: Schema.String },
{ a: Schema.String, b: Schema.String, c: FastCheck.string() },
({ a, b, c }) =>
Effect.gen(function*() {
yield* Effect.scope
Expand Down

0 comments on commit 62f12d8

Please sign in to comment.