Zod Factory States
What is a Factory State?
Zod Factories mock schema by generating random values that conform to a Zod Schema's type definitions.
Factory states allow us to define discrete modifications to apply to mocked Zod Schema model.
In other words, by implementing a Factory States we can take control over how our Zod Schema is mocked.
Creating a Factory State
Imagine you have a Zod Schema called TransformedCarSchema that looks like this:
import { z } from 'zod';
export const TransformedCarSchema = z.object({
make: z.string(),
model: z.string(),
color: z.string(),
doors: z.literal(2).or(z.literal(4)),
team: z.literal('Decepticon').or(z.literal('Autobot')),
});
If you look closely, you'll notice that there are 4 potential states this Zod Schema supports:
{ doors: 2, team: 'Autobot' }{ doors: 4, team: 'Autobot' }{ doors: 2, team: 'Decepticon' }{ doors: 4, team: 'Decepticon' }
Now, let's say we want to mock a transformed car with 2 doors. We can add a Factory State to help us accomplish this like so:
export default class TransformedCarFactory extends Factory<TTransformedCar> {
constructor() {
super(TransformedCarSchema);
}
/**
* @description Sets the "doors" property state to 2
* @returns {this}
*/
coupe(): this {
this.state((schema) => {
return schema.extend({ doors: z.literal(2) });
});
return this;
}
}
We can now generate a transformed car with 2 doors by calling:
import TransformedCarFactory from '@schwab/schema/factories/transformed/TransformedCarSchema';
const data = new TransformedCarFactory().coupe().mock();
We will also want to mock 4 doors too right? So let's add a "sedan" state to handle that like so:
export default class TransformedCarFactory extends Factory<TTransformedCar> {
constructor() {
super(TransformedCarSchema);
}
/**
* @description Sets the "doors" property state to 2
* @returns {this}
*/
coupe = (): this => {
this.state((schema) => {
return schema.extend({ doors: z.literal(2) });
});
return this;
}
/**
* @description Sets the "doors" property state to 4
* @returns {this}
*/
sedan = (): this => {
this.state((schema) => {
return schema.extend({ doors: z.literal(4) });
});
return this;
}
}
We can now generate a transformed car with 4 doors by calling:
import TransformedCarFactory from '@schwab/schema/factories/transformed/TransformedCarSchema';
const data = new TransformedCarFactory().sedan().mock();
This is nice to have and much easier than editing a mocked object after creation. Especially in the case where you are required to mock multiple transformed cars.
However, there are 2 more "team" states we haven't added. Let's do that now:
export default class TransformedCarFactory extends Factory<TTransformedCar> {
constructor() {
super(TransformedCarSchema);
}
/**
* @description Sets the "doors" property state to 2
* @returns {this}
*/
coupe = (): this => {
this.state((schema) => {
return schema.extend({ doors: z.literal(2) });
});
return this;
}
/**
* @description Sets the "doors" property state to 4
* @returns {this}
*/
sedan = (): this => {
this.state((schema) => {
return schema.extend({ doors: z.literal(4) });
});
return this;
}
/**
* @description Sets the "team" property state to "Autobot"
* @returns {this}
*/
autobot = (): this => {
this.state((schema) => {
return schema.extend({ team: z.literal('Autobot') });
});
return this;
}
/**
* @description Sets the "team" property state to "Decepticon"
* @returns {this}
*/
decepticon = (): this => {
this.state((schema) => {
return schema.extend({ team: z.literal('Decepticon') });
});
return this;
}
}
This is great! Our Factory now has all its "States" defined. Now let's review how we can chain Factory States.
Chaining Factory States
We now have all 4 States (permutations) defined in our Factory.
These states can be appended to an instantiated Factory instructing it to generate a mocked Zod Schema model with specific permutations.
Let's try this out by generating a transformed Autobot car with 4 doors by chaining our Factory States like so:
import TransformedCarFactory from '@schwab/schema/factories/transformed/TransformedCarSchema';
const data = new TransformedCarFactory().autobot().sedan().mock();
Pretty simple right?!?
So when we define discrete modifications representing each potential data state our Zod Schema permits, you and your fellow developers will gain the ability to mock all model permutations effortlessly in a single line of code!
Thanks for reading & Happy Mocking!