Skip to content
On this page

Zod Fixture

Fixture Generation with 1:1 Zod Parity


npm versionLicensestars


Creating test fixtures should be easy.
zod-fixture helps with the arrange phase of your tests by creating test fixtures based on a zod schema.

Table of Contents

Installation

sh
npm install -D vitepress
sh
pnpm add -D vitepress
sh
yarn add -D vitepress
sh
bun add -d zod-fixture

Getting Started

The easiest way to start using zod-fixture is to import the preconfigured (more details on this later) Fixture class.

INFO

The examples make use of a seed to generate the same fixture every time. This is useful for our docs, or to reproduce issues, but it's not needed in your test code.

ts
import { z } from 'zod';
import { Fixture } from 'zod-fixture';

const PersonSchema = z.object({
	name: z.string(),
	birthday: z.date(),
	address: z.object({
		street: z.string(),
		city: z.string(),
		state: z.string(),
	}),
	pets: z.array(z.object({ name: z.string(), breed: z.string() })),
	totalVisits: z.number(),
});

const fixture = new Fixture({ seed: 11 });
const person = fixture.fromSchema(PersonSchema);
ts
{
	address: {
		city: '43K>5SG250E',
		state: 'kbszkSZm^3Kg<CPyfa4z1HikF',
		street: 'oQes]5YUwRzbITAPk',
	},
	birthday: new Date('1980-09-26T06:36:51.341Z'),
	name: '8zGj;1humNI>G?8p6;ej\\T4jS3',
	pets: [
		{
			breed: 'RIEgfwDI7]yK6RE581:h]QM^P',
			name: 'wgIuUNfJKl;i4``l3`A',
		},
		{
			breed: 'iVI2P\\',
			name: 'YOMKN<ukgnGg1qp`CdV>',
		},
		{
			breed: 'fotFqP',
			name: '8Z?ap[eGC',
		},
	],
	totalVisits: 5544703130861567,
}

Customizing

This library provides utility methods to provide fine-grained support to create your fixtures. Take a look at the examples to see how you can use zod-fixture in your tests.

Extending

The Fixture class provides a predefined set of generators that supports each type that's included in zod.

For most cases this is fine, and offers a fast and easy way to create fixtures. But, for those times where you need a custom implementation, you can write your own Generator to change it's behavior using the extend method.

In the example below we create a custom implemantion addressGenerator to return a custom address object, and a totalVisitsGenerator to return a more realistic number of visits.

ts
import { ZodNumber, ZodObject, z } from 'zod';
import { Fixture, Generator } from 'zod-fixture';

const addressGenerator = Generator({
	schema: ZodObject,
	filter: ({ context }) => context.path.at(-1) === 'address',
	output: () => ({
		street: 'My Street',
		city: 'My City',
		state: 'My State',
	}),
});

const totalVisitsGenerator = Generator({
	schema: ZodNumber,
	output: ({ transform }) => transform.utils.random.int({ min: 0, max: 25 }),
});

const PersonSchema = z.object({
	name: z.string(),
	birthday: z.date(),
	address: z.object({
		street: z.string(),
		city: z.string(),
		state: z.string(),
	}),
	pets: z.array(z.object({ name: z.string(), breed: z.string() })),
	totalVisits: z.number(),
});

const fixture = new Fixture({ seed: 38 }).extend([
	addressGenerator,
	totalVisitsGenerator,
]);
const person = fixture.fromSchema(PersonSchema);
ts
{
	address: {
		city: 'My City',
		state: 'My State',
		street: 'My Street',
	},
	birthday: new Date('1926-02-23T02:07:24.494Z'),
	name: 'c',
	pets: [
		{
			breed: '5yOQfkYfI6=kRuH^F?5BCNHft',
			name: 'mYxRp1GBY2aw',
		},
		{
			breed: '6Qz\\s',
			name: '_',
		},
		{
			breed: '6e9',
			name: ';l]@',
		},
	],
	totalVisits: 22,
}

Create Your Own Transformer

Instead of using the opinionated Fixture class, you can extend the unopinionated Transformer and register the desired generators.

ts
import { z } from 'zod';
import { Transformer } from 'zod-fixture';

const transform = new Transformer().extend([
	/* insert your generators here */
]);

transform.from(z.any());

API

Generators

To generate a value based on a zod type we're using what we call a Generator.

To help you to create your own generators this library also includes some useful utility methods to generate data. For example, in the example below we create our own totalVisitsGenerator to return more realastic numbers using the random utilities.

TIP

The order the registered generators matters. The first generator that matches the conditions (schema and filter) is used to create the value.

ts
const totalVisitsGenerator = Generator({
	schema: ZodNumber,
	output: ({ transform }) => transform.utils.random.int({ min: 0, max: 25 }),
});

Contributing

Getting started with GitHub Codespaces

To get started, create a codespace for this repository by clicking this 👇

Open in GitHub Codespaces

A codespace will open in a web-based version of Visual Studio Code. The dev container is fully configured with software needed for this project.

Note: Dev containers is an open spec which is supported by GitHub Codespaces and other tools.

StackBlitz

Open in StackBlitz

Blog posts

Credits

This package is inspired on AutoFixture.