UNPKG

test-fixture-factory

Version:

A minimal library for creating and managing test fixtures using Vitest, enabling structured, repeatable, and efficient testing processes.

103 lines (98 loc) 6.26 kB
type OneOrMany<T> = T | readonly T[]; type KeysAssignableTo<C, V> = { [P in keyof C & string]: C[P] extends V ? P : never; }[keyof C & string]; declare class FieldBuilder<Context extends object, Fixtures extends keyof Context & string, Value, Flag extends RequiredFlag> { private readonly state; constructor(field: Field<Pick<Context, Fixtures>, Value, Flag>); from<K extends KeysAssignableTo<Context, Value>>(keyOrList: OneOrMany<K>): FieldBuilder<Context, Fixtures | K, Value, 'from'>; from<K extends keyof Context & string>(keyOrList: OneOrMany<K>, getValueFromContext: (ctx: Pick<Context, K>) => Value): FieldBuilder<Context, Fixtures | K, Value, 'from'>; maybeFrom<K extends KeysAssignableTo<Context, Value | undefined>>(keyOrList: OneOrMany<K>): FieldBuilder<Context, Fixtures | K, Value, 'maybeFrom'>; maybeFrom<K extends keyof Context & string>(keyOrList: OneOrMany<K>, getValueFromContext: (ctx: Pick<Context, K>) => Value | undefined): FieldBuilder<Context, Fixtures | K, Value, 'maybeFrom'>; optional(): FieldBuilder<Context, Fixtures, Value | undefined, "optional">; default(defaultValue: Value | (() => Value)): FieldBuilder<Context, Fixtures, Value, "default">; } type NewFieldBuilder<Context extends object> = { type: <T>() => FieldBuilder<Context, never, T, 'required'>; }; type Prettify<T> = { [K in keyof T]: T[K]; } & {}; type RequiredFlag = 'required' | 'optional' | 'default' | 'from' | 'maybeFrom'; type Field<Fixtures extends object, Value, Flag extends RequiredFlag> = { fixtureList: (keyof Fixtures & string)[]; getValueFromContext: undefined | ((ctx: Fixtures) => Value | undefined); isRequired: Flag extends 'required' ? true : Flag extends 'default' ? true : Flag extends 'from' ? true : Flag extends 'maybeFrom' ? true : Flag extends 'optional' ? false : true; defaultValue: undefined | Value | (() => Value); }; type AsField<F extends FieldBuilder<any, any, any, any>> = F extends FieldBuilder<infer Context, infer Fixtures, infer Value, infer Flag> ? Field<Prettify<Pick<Context, Fixtures>>, Value, Flag> : never; type AnySchemaBuilder = Record<string, FieldBuilder<any, any, any, any>>; type SchemaOf<SchemaBuilder extends AnySchemaBuilder> = { [K in keyof SchemaBuilder]: AsField<SchemaBuilder[K]>; }; type AnySchemaBuilderWithContext<Context extends object> = Record<string, FieldBuilder<Context, any, any, any>>; type AnyFieldWithContext<Context extends object> = Field<Context, any, any>; type AnySchema = Record<string, AnyFieldWithContext<any>>; type EmptySchema = Record<string, never>; type MissingField = { key: string; fixtureList: string[]; }; type DestroyFn = () => Promise<void> | void; type VitestFixtureFn<Context, FixtureValue> = (context: object & Context, use: (value: FixtureValue) => Promise<void>) => Promise<void>; type FactoryResult<Value> = { value: Value; destroy?: DestroyFn; }; type FactoryFn<Attrs extends object, Value> = (attrs: Attrs) => Promise<FactoryResult<Value>> | FactoryResult<Value>; type FactoryOptions = { shouldDestroy?: boolean; }; type ValueOf<S extends AnySchema, K extends keyof S> = S[K] extends Field<infer _C, infer Value, infer _F> ? Value : never; type FixturesOf<S extends AnySchema, K extends keyof S> = S[K] extends Field<infer Fixtures, infer _V, infer _F> ? Fixtures : never; type FlagOf<S extends AnySchema, K extends keyof S> = S[K] extends Field<infer _F, infer _V, infer Flag> ? Flag : never; type OptionalInputKeysOf<S extends AnySchema> = { [K in keyof S]: FlagOf<S, K> extends 'optional' | 'default' | 'from' | 'maybeFrom' ? K : never; }[keyof S]; type RequiredInputKeysOf<S extends AnySchema> = S extends EmptySchema ? never : Exclude<keyof S, OptionalInputKeysOf<S>>; type InputOf<S extends AnySchema> = S extends EmptySchema ? EmptySchema : Prettify<{ [K in RequiredInputKeysOf<S>]: ValueOf<S, K>; } & { [K in OptionalInputKeysOf<S>]?: ValueOf<S, K>; }>; type OutputOf<S extends AnySchema> = S extends EmptySchema ? EmptySchema : { [K in keyof S]: ValueOf<S, K>; }; type VoidableInputOf<Schema extends AnySchema> = RequiredInputKeysOf<Schema> extends never ? InputOf<Schema> | void : InputOf<Schema>; type RequiredKeys<T> = { [K in keyof T]-?: {} extends Pick<T, K> ? never : K; }[keyof T]; type MaybeVoid<T> = RequiredKeys<T> extends never ? T | void : T; type InferFixtureValue<T> = T extends () => VitestFixtureFn<infer _Deps, infer Value> ? Value : never; type SetSchemaFieldsOptional<Schema extends AnySchema, Keys extends keyof Schema> = { [K in keyof Schema]: K extends Keys ? Field<FixturesOf<Schema, K>, ValueOf<Schema, K>, 'optional'> : Schema[K]; }; type FactoryState<S extends AnySchema, V> = { name: string; schema: S; factoryFn: FactoryFn<Prettify<OutputOf<S>>, V> | undefined; }; type CreateFn<Schema extends AnySchema, Value> = (attrs: VoidableInputOf<Schema>) => Promise<Value>; declare class FactoryBuilder<Context extends object, Schema extends AnySchema, Value> { private readonly state; constructor(state: FactoryState<Schema, Value>); withContext<Context extends object>(): FactoryBuilder<Context, Schema, Value>; withSchema<SchemaBuilder extends AnySchemaBuilderWithContext<Context>>(schemaFn: (f: NewFieldBuilder<Context>) => SchemaBuilder): FactoryBuilder<Context, SchemaOf<SchemaBuilder>, Value>; withValue<Value>(factoryFn: FactoryFn<Prettify<OutputOf<Schema>>, Value>): FactoryBuilder<Context, Schema, Value>; build(attrs: VoidableInputOf<Schema>, context: MaybeVoid<Context>): Promise<{ value: Value; destroy: DestroyFn; }>; useCreateValue<PresetAttrs extends void | undefined | Partial<InputOf<Schema>>>(presetAttrs?: PresetAttrs, { shouldDestroy }?: FactoryOptions): VitestFixtureFn<Context, CreateFn<SetSchemaFieldsOptional<Schema, keyof PresetAttrs & keyof Schema>, Value>>; useValue(attrs: VoidableInputOf<Schema>, options?: FactoryOptions): VitestFixtureFn<Context, Value>; } declare const createFactory: (name: string) => FactoryBuilder<object, EmptySchema, unknown>; declare class UndefinedFieldError extends Error { constructor(name: string, missingFields: MissingField[]); } export { type InferFixtureValue, UndefinedFieldError, createFactory };