zaha
v0.1.5
Published
Library for building test builders
Downloads
9
Maintainers
Readme
Zaha
Zaha is a javascript utility for generating test builders! Builders allow you to:
- Quickly create test objects automatically populated with default fields
- Abstract the structure of complex objects behind a fluent interface
Get Started
First, you'll want to install the library:
npm i -D zaha
Then create a test builder:
// room-builder.js
import zaha, { is } from 'zaha';
export default zaha({
length: is.number(),
width: is.number(),
furniture: is.arrayOf(is.string())
});
Then use your new builder in a test!
// room.spec.js
import RoomBuilder from './room-builder';
const room = new RoomBuilder()
.withWidth(500),
.withFurniture(['chair', 'bed'])
.build();
Details
Zaha is a function which takes as input a schema and outputs a builder class.
Schemas
A schema is an object whose fields are all builders. It defines what fields you want your eventually build object to contain. The following example of a schema defines an object with a string and numeric field, for instance.
import { is } from 'zaha';
const schema = {
name: is.string(),
age: is.number()
};
is
You might notice that this mystical is
object can be used to define the types of fields. is
provides the following:
is(value)
: An exact value the field should be when the final object is builtis.string()
: A string fieldis.datestring()
: A string which represents a dateis.number()
: A decimal numberis.int()
: An integer numberis.boolean()
: A boolean valueis.object(schema)
: Converts the schema into a basic builder; useful for nested structuresis.array()
: Defines an array of any typeis.arrayOf(builder)
: Defines an array of the provided builder typeis.function()
: A callable functionis.oneOf(values)
: Value must be exactly one of the provided values; values is an array
The following example shows how to use is.object
and is.arrayOf
:
const schema = {
nested: is.object({
array: is.arrayOf(is.int()),
exact: is('This particular string')
})
};
Zaha Builders
Though is
is useful, in reality these fields can take any builder. A builder object is simply an object which has the build()
method defined on it. This means you can pass in builders created by Zaha into the schema:
const InnerBuilder = zaha(innerSchema);
const schema = {
value: new InnerBuilder()
};
Custom Builders
A builder is any object which has build()
defined on it. This means you can make your own collection of domain-specific basic builders that you can pass to a Zaha schema.
const randomString = {
build: () => random.string()
};
const author = is.object({
name: randomString,
age: is.number()
});
const schema = { author };
Builders
The purpose of Zaha is to create configurable builders. The zaha
function converts a schema into a builder class that can be instantiated, like so:
const Builder = zaha(schema);
const builder = new Builder();
Builders define two function types:
with<PropertyName>(value)
: Sets the value of the given property to the given argumentbuild()
: Emits an object with the values provided bywith
A with
function is generated for each first-order property defined in the schema. You can chain them like so:
const room = new RoomBuilder()
.withWidth(100)
.withLength(200)
.build();
Note on property names
- Snake-cased property names, like
last_name
, will end up with awith
function likewithLast_name
- Property names which contain arbitrary symbols, like
is-admin?
, are not supported
Extending Builders
Zaha emits a class which can be extended. If you want to define custom methods on the builder, it's simple to do:
const Base = zaha({
furniture: is.arrayOf(is.string())
});
export default class RoomBuilder extends Base {
withoutFurniture() {
this.schema.furniture = is([]);
return this;
}
}
Example
Here is a full use-case example. Chai is being used here, but any testing framework works with Zaha.
// room-builder.js
import zaha, { is } from 'zaha';
export default zaha({
length: is.number(),
width: is.number(),
furniture: is.arrayOf(is.string())
});
import { expect } from 'chai';
import RoomBuilder from './room-builder';
import { moveAllFurniture } from './room-utils';
describe('Furniture Mover', () => {
it('moves all furniture from one room into the other', () => {
const furniture = ['chair', 'table'];
const formerRoom = new RoomBuilder()
.withFurniture(furniture)
.build();
const newRoom = new RoomBuilder()
.withFurniture([])
.build();
moveAllFurniture.from(formerRoom).to(newRoom);
expect(formerRoom.furniture).to.be.empty;
expect(newRoom.furniture).to.deep.equal(furniture);
});
});