name: effect-ts-testing description: Testing guidelines and patterns for Effect-based code.
Effect-TS Testing Skill
Use this skill when writing or reviewing tests for Effect-based code.
Effect testing rules (for *.spec.* files)
When testing a method that returns an Effect type, use the @effect/vitest
package.
- Use
import { it } from '@effect/vitest'as opposed to importingitfrom regular vitest. - Usage:
it.effect('test name', () => { return Effect.gen(...) }) - Use
it.layer()to provide test dependencies when your Effect requires specific services:it.layer(Layer.fresh(IncrementalIdGenerator))((it) => { it.effect('test name', () => { return Effect.gen(...) }) })
Testing for type-safety
Use tsafe package for compile-time type assertions to validate type safety in
tests.
- Import:
import { assert } from 'tsafe'andimport type { Equals } from 'tsafe' - Usage:
assert<Equals<ActualType, ExpectedType>>()- validates exact type equality at compile time
Test time helpers
Never use new Date() in tests. Always use yield* DateTime.now and convert to
Date if needed.
import { DateTime, Effect } from 'effect';
const nowDateTime = yield* DateTime.now;
const now = DateTime.toDateUtc(nowDateTime);
Schema decoding with decodeUnknown
When decoding unknown values using Effect schemas, always use the
decodeUnknown function exported from zerospin instead of
Schema.decodeUnknown directly.
- Import:
import { decodeUnknown } from 'zerospin' - Always specify
onExcessProperty:'error','ignore', or'preserve'based on your needs - Map errors to
ZerospinErrorwith code'failed-to-decode-unknown'
In Effect.gen contexts:
import { decodeUnknown } from 'zerospin';
import { ZerospinError } from '@zerospin/error';
import { Effect } from 'effect';
const decoded = yield* decodeUnknown({
onExcessProperty: 'error', // or 'ignore' or 'preserve'
schema: MySchema,
value: unknownValue,
}).pipe(
Effect.mapError((error) => {
return new ZerospinError({
code: 'failed-to-decode-unknown',
message: error.message,
cause: error,
});
})
);
In async/await contexts:
import { decodeUnknown } from 'zerospin';
import { ZerospinError } from '@zerospin/error';
import { Effect } from 'effect';
const decoded = await Effect.runPromise(
decodeUnknown({
onExcessProperty: 'error',
schema: MySchema,
value: unknownValue,
}).pipe(
Effect.mapError((error) => {
return new ZerospinError({
code: 'failed-to-decode-unknown',
message: error.message,
cause: error,
});
})
)
);