| /** | |
| * Provides helpers for testing Schema behavior. | |
| * | |
| * These utilities assert how schemas construct values, decode input, encode | |
| * output, generate arbitrary values, and round-trip between encoded and decoded | |
| * forms. The `Asserts` class groups the common checks for one schema, while | |
| * `Decoding` and `Encoding` can be used directly when a test only needs one | |
| * direction. | |
| * | |
| * @since 4.0.0 | |
| */ | |
| import * as assert from "node:assert"; | |
| import * as Effect from "../Effect.js"; | |
| import * as Record from "../Record.js"; | |
| import * as Result from "../Result.js"; | |
| import * as Schema from "../Schema.js"; | |
| import * as SchemaAST from "../SchemaAST.js"; | |
| import * as SchemaParser from "../SchemaParser.js"; | |
| import * as FastCheck from "../testing/FastCheck.js"; | |
| /** | |
| * Provides schema test assertions for decoding, encoding, make, arbitrary generation, and round-trip verification. | |
| * | |
| * **When to use** | |
| * | |
| * Use when writing schema unit tests for decoding, encoding, construction, property-based round-trip, or generation behavior. | |
| * | |
| * **Example** (Decoding and encoding a struct) | |
| * | |
| * ```ts | |
| * import { Schema } from "effect" | |
| * import { TestSchema } from "effect/testing" | |
| * | |
| * const schema = Schema.Struct({ name: Schema.String }) | |
| * const asserts = new TestSchema.Asserts(schema) | |
| * | |
| * // decoding | |
| * await asserts.decoding().succeed({ name: "Alice" }) | |
| * | |
| * // encoding | |
| * await asserts.encoding().succeed({ name: "Alice" }) | |
| * ``` | |
| * | |
| * @see {@link Decoding} | |
| * @see {@link Encoding} | |
| * @category testing | |
| * @since 4.0.0 | |
| */ | |
| export class Asserts { | |
| /** | |
| * Static helpers for comparing schema AST structures. | |
| * | |
| * **When to use** | |
| * | |
| * Use to assert that two schema field or tuple element definitions produce | |
| * the same AST structure. | |
| * | |
| * **Details** | |
| * | |
| * `ast.fields.equals(a, b)` compares struct field ASTs via `assert.deepStrictEqual`. `ast.elements.equals(a, b)` compares tuple element ASTs via `assert.deepStrictEqual`. | |
| * | |
| * **Example** (Comparing struct fields) | |
| * | |
| * ```ts | |
| * import { Schema } from "effect" | |
| * import { TestSchema } from "effect/testing" | |
| * | |
| * const fieldsA = { name: Schema.String } | |
| * const fieldsB = { name: Schema.String } | |
| * TestSchema.Asserts.ast.fields.equals(fieldsA, fieldsB) // no error | |
| * ``` | |
| */ | |
| static ast = { | |
| fields: { | |
| equals: (a, b) => { | |
| assert.deepStrictEqual(Record.map(a, SchemaAST.getAST), Record.map(b, SchemaAST.getAST)); | |
| } | |
| }, | |
| elements: { | |
| equals: (a, b) => { | |
| assert.deepStrictEqual(a.map(SchemaAST.getAST), b.map(SchemaAST.getAST)); | |
| } | |
| } | |
| }; | |
| schema; | |
| constructor(schema) { | |
| this.schema = schema; | |
| } | |
| /** | |
| * Returns an object with `succeed` and `fail` helpers for testing the schema's `make` operation. | |
| * | |
| * **When to use** | |
| * | |
| * Use to assert how `Schema.make` accepts, transforms, or rejects | |
| * construction input for this schema. | |
| * | |
| * **Details** | |
| * | |
| * `succeed(input)` asserts make returns the input unchanged. `succeed(input, expected)` asserts make returns `expected`. `fail(input, message)` asserts make fails with `message`. | |
| * | |
| * **Example** (Testing make) | |
| * | |
| * ```ts | |
| * import { Schema } from "effect" | |
| * import { TestSchema } from "effect/testing" | |
| * | |
| * const schema = Schema.String | |
| * const asserts = new TestSchema.Asserts(schema) | |
| * await asserts.make().succeed("hello") | |
| * ``` | |
| * | |
| * @see {@link decoding} for assertions against decoded input | |
| * @see {@link encoding} for assertions against encoded output | |
| */ | |
| make(options) { | |
| const makeEffect = SchemaParser.makeEffect(this.schema); | |
| async function succeed(input, expected) { | |
| const r = await Effect.runPromise(makeEffect(input, options).pipe(Effect.mapErrorEager(issue => issue.toString()), Effect.result)); | |
| expected = arguments.length === 1 ? input : expected; | |
| assert.deepStrictEqual(r, Result.succeed(expected)); | |
| } | |
| return { | |
| succeed, | |
| async fail(input, message) { | |
| const r = await Effect.runPromise(makeEffect(input, options).pipe(Effect.mapErrorEager(issue => issue.toString()), Effect.result)); | |
| assert.deepStrictEqual(r, Result.fail(message)); | |
| } | |
| }; | |
| } | |
| /** | |
| * Runs a property-based test that encodes arbitrary values and then decodes them, asserting the decoded value equals the original. | |
| * | |
| * **When to use** | |
| * | |
| * Use to verify that generated schema values survive an encode-then-decode | |
| * round trip. | |
| * | |
| * **Details** | |
| * | |
| * FastCheck generates arbitrary values matching the schema's `Type`. The assertion fails if any generated value does not round-trip. Pass `options.params` to control FastCheck parameters such as `numRuns`. | |
| * | |
| * **Example** (Round-trip verification) | |
| * | |
| * ```ts | |
| * import { Schema } from "effect" | |
| * import { TestSchema } from "effect/testing" | |
| * | |
| * const asserts = new TestSchema.Asserts(Schema.NumberFromString) | |
| * await asserts.verifyLosslessTransformation() | |
| * ``` | |
| * | |
| * @see {@link arbitrary} for checking that generated values satisfy the schema | |
| */ | |
| verifyLosslessTransformation(options) { | |
| const decodeUnknownEffect = SchemaParser.decodeUnknownEffect(this.schema); | |
| const encodeEffect = SchemaParser.encodeEffect(this.schema); | |
| const arbitrary = Schema.toArbitrary(this.schema); | |
| return FastCheck.assert(FastCheck.asyncProperty(arbitrary, async t => { | |
| const r = await Effect.runPromise(encodeEffect(t).pipe(Effect.flatMapEager(e => decodeUnknownEffect(e)), Effect.mapErrorEager(issue => issue.toString()), Effect.result)); | |
| assert.deepStrictEqual(r, Result.succeed(t)); | |
| }), options?.params); | |
| } | |
| /** | |
| * Returns a {@link Decoding} instance for this schema with helpers for decoding assertions. | |
| * | |
| * **When to use** | |
| * | |
| * Use to test how unknown input is decoded into the schema's type. | |
| * | |
| * **Details** | |
| * | |
| * Pass `parseOptions` to control error reporting, for example `{ errors: "all" }`. | |
| * | |
| * **Example** (Decoding assertions) | |
| * | |
| * ```ts | |
| * import { Schema } from "effect" | |
| * import { TestSchema } from "effect/testing" | |
| * | |
| * const asserts = new TestSchema.Asserts(Schema.NumberFromString) | |
| * const decoding = asserts.decoding() | |
| * await decoding.succeed("42", 42) | |
| * await decoding.fail(null, "Expected string, got null") | |
| * ``` | |
| * | |
| * @see {@link Decoding} | |
| * @see {@link encoding} for assertions in the opposite direction | |
| */ | |
| decoding(options) { | |
| return new Decoding(this.schema, options); | |
| } | |
| /** | |
| * Returns an {@link Encoding} instance for this schema with helpers for encoding assertions. | |
| * | |
| * **When to use** | |
| * | |
| * Use to test how schema values are encoded into their external form. | |
| * | |
| * **Details** | |
| * | |
| * Pass `parseOptions` to control error reporting, for example `{ errors: "all" }`. | |
| * | |
| * **Example** (Encoding assertions) | |
| * | |
| * ```ts | |
| * import { Schema } from "effect" | |
| * import { TestSchema } from "effect/testing" | |
| * | |
| * const asserts = new TestSchema.Asserts(Schema.NumberFromString) | |
| * const encoding = asserts.encoding() | |
| * await encoding.succeed(42, "42") | |
| * ``` | |
| * | |
| * @see {@link Encoding} | |
| * @see {@link decoding} for assertions in the opposite direction | |
| */ | |
| encoding(options) { | |
| return new Encoding(this.schema, options); | |
| } | |
| /** | |
| * Returns an object with property-based testing helpers for the schema's arbitrary generator. | |
| * | |
| * **When to use** | |
| * | |
| * Use to verify that arbitrary values generated for this schema satisfy the | |
| * schema's predicate. | |
| * | |
| * **Details** | |
| * | |
| * `verifyGeneration()` generates arbitrary values and asserts each value satisfies the schema's `is` predicate. It defaults to 20 runs. Pass `options.params` to override FastCheck parameters. | |
| * | |
| * **Example** (Verifying arbitrary generation) | |
| * | |
| * ```ts | |
| * import { Schema } from "effect" | |
| * import { TestSchema } from "effect/testing" | |
| * | |
| * const asserts = new TestSchema.Asserts(Schema.String) | |
| * asserts.arbitrary().verifyGeneration() | |
| * ``` | |
| * | |
| * @see {@link verifyLosslessTransformation} for property-based round-trip checks | |
| */ | |
| arbitrary() { | |
| const schema = this.schema; | |
| return { | |
| verifyGeneration(options) { | |
| const params = options?.params; | |
| const is = Schema.is(schema); | |
| const arb = Schema.toArbitrary(schema); | |
| FastCheck.assert(FastCheck.property(arb, a => is(a)), { | |
| numRuns: 20, | |
| ...params | |
| }); | |
| } | |
| }; | |
| } | |
| } | |
| /** | |
| * Provides decoding test assertions through `succeed` and `fail` methods that run the schema's decoder and compare the result. | |
| * | |
| * **When to use** | |
| * | |
| * Use when you want to assert that specific inputs decode to expected values, invalid inputs produce specific error messages, or schemas receive required decoding services. | |
| * | |
| * **Details** | |
| * | |
| * All assertions are async and use `assert.deepStrictEqual` internally. `succeed(input)` asserts the decoded output equals `input`; `succeed(input, expected)` asserts it equals `expected`; `fail(input, message)` asserts decoding fails and the stringified issue equals `message`. `provide(key, impl)` returns a new `Decoding` with the service injected into the decoding context. | |
| * | |
| * **Example** (Decoding with service provision) | |
| * | |
| * ```ts | |
| * import { Schema } from "effect" | |
| * import { TestSchema } from "effect/testing" | |
| * | |
| * const asserts = new TestSchema.Asserts(Schema.String) | |
| * const decoding = asserts.decoding() | |
| * await decoding.succeed("hello") | |
| * ``` | |
| * | |
| * @see {@link Asserts} | |
| * @see {@link Encoding} | |
| * @category testing | |
| * @since 4.0.0 | |
| */ | |
| export class Decoding { | |
| schema; | |
| decodeUnknownEffect; | |
| options; | |
| constructor(schema, options) { | |
| this.schema = schema; | |
| this.decodeUnknownEffect = SchemaParser.decodeUnknownEffect(schema); | |
| this.options = options; | |
| } | |
| async succeed(input, expected) { | |
| const r = await Effect.runPromise(this.decodeUnknownEffect(input, this.options?.parseOptions).pipe(Effect.mapErrorEager(issue => issue.toString()), Effect.result)); | |
| expected = arguments.length === 1 ? input : expected; | |
| assert.deepStrictEqual(r, Result.succeed(expected)); | |
| } | |
| /** | |
| * Asserts that decoding `input` fails and the stringified issue equals | |
| * `message`. | |
| * | |
| * **When to use** | |
| * | |
| * Use to verify that invalid decoding input produces the expected issue text. | |
| * | |
| * **Example** (Asserting a decoding failure) | |
| * | |
| * ```ts | |
| * import { Schema } from "effect" | |
| * import { TestSchema } from "effect/testing" | |
| * | |
| * const decoding = new TestSchema.Asserts(Schema.String).decoding() | |
| * await decoding.fail(42, "Expected string, got 42") | |
| * ``` | |
| * | |
| * @see {@link succeed} for asserting successful decoding | |
| */ | |
| async fail(input, message) { | |
| const r = await Effect.runPromise(this.decodeUnknownEffect(input, this.options?.parseOptions).pipe(Effect.mapErrorEager(issue => issue.toString()), Effect.result)); | |
| assert.deepStrictEqual(r, Result.fail(message)); | |
| } | |
| /** | |
| * Returns a new {@link Decoding} instance with the given service injected into the decoding effect context. | |
| * | |
| * **When to use** | |
| * | |
| * Use when the schema's decoder requires a service dependency. | |
| * | |
| * @see {@link Encoding.provide} | |
| */ | |
| provide(service, implementation) { | |
| return new Decoding(this.schema.pipe(Schema.middlewareDecoding(Effect.provideService(service, implementation))), this.options); | |
| } | |
| } | |
| /** | |
| * Provides encoding test assertions through `succeed` and `fail` methods that run the schema's encoder and compare the result. | |
| * | |
| * **When to use** | |
| * | |
| * Use when you want to assert that specific values encode to expected outputs, invalid inputs produce specific error messages, or schemas receive required encoding services. | |
| * | |
| * **Details** | |
| * | |
| * All assertions are async and use `assert.deepStrictEqual` internally. `succeed(input)` asserts the encoded output equals `input`; `succeed(input, expected)` asserts it equals `expected`; `fail(input, message)` asserts encoding fails and the stringified issue equals `message`. `provide(key, impl)` returns a new `Encoding` with the service injected into the encoding context. | |
| * | |
| * **Example** (Encoding assertions) | |
| * | |
| * ```ts | |
| * import { Schema } from "effect" | |
| * import { TestSchema } from "effect/testing" | |
| * | |
| * const encoding = new TestSchema.Asserts(Schema.NumberFromString).encoding() | |
| * await encoding.succeed(42, "42") | |
| * ``` | |
| * | |
| * @see {@link Asserts} | |
| * @see {@link Decoding} | |
| * | |
| * @category testing | |
| * @since 4.0.0 | |
| */ | |
| export class Encoding { | |
| schema; | |
| encodeUnknownEffect; | |
| options; | |
| constructor(schema, options) { | |
| this.schema = schema; | |
| this.encodeUnknownEffect = SchemaParser.encodeUnknownEffect(schema); | |
| this.options = options; | |
| } | |
| async succeed(input, expected) { | |
| const r = await Effect.runPromise(this.encodeUnknownEffect(input, this.options?.parseOptions).pipe(Effect.mapErrorEager(issue => issue.toString()), Effect.result)); | |
| expected = arguments.length === 1 ? input : expected; | |
| assert.deepStrictEqual(r, Result.succeed(expected)); | |
| } | |
| /** | |
| * Asserts that encoding `input` fails and the stringified issue equals | |
| * `message`. | |
| * | |
| * **When to use** | |
| * | |
| * Use to verify that invalid encoding input produces the expected issue text. | |
| * | |
| * **Example** (Asserting an encoding failure) | |
| * | |
| * ```ts | |
| * import { Schema } from "effect" | |
| * import { TestSchema } from "effect/testing" | |
| * | |
| * const encoding = new TestSchema.Asserts(Schema.NumberFromString).encoding() | |
| * await encoding.fail("not-a-number", "Expected number, got \"not-a-number\"") | |
| * ``` | |
| * | |
| * @see {@link succeed} for asserting successful encoding | |
| */ | |
| async fail(input, message) { | |
| const r = await Effect.runPromise(this.encodeUnknownEffect(input, this.options?.parseOptions).pipe(Effect.mapErrorEager(issue => issue.toString()), Effect.result)); | |
| assert.deepStrictEqual(r, Result.fail(message)); | |
| } | |
| /** | |
| * Returns a new {@link Encoding} instance with the given service injected into the encoding effect context. | |
| * | |
| * **When to use** | |
| * | |
| * Use when the schema's encoder requires a service dependency. | |
| * | |
| * @see {@link Decoding.provide} | |
| */ | |
| provide(service, implementation) { | |
| return new Encoding(this.schema.pipe(Schema.middlewareEncoding(Effect.provideService(service, implementation))), this.options); | |
| } | |
| } | |
| //# sourceMappingURL=TestSchema.js.map |
Xet Storage Details
- Size:
- 14.4 kB
- Xet hash:
- 651c8257406bc8c5056d07bd285c469367902afecd015f845c864d62f87106ed
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.