Rosie is a factory for building JavaScript objects, mostly useful for setting up test data. It is inspired by factory_girl.
Define your factory, giving it a name and optionally a constructor function (Game
in this example):
Factory.define('game'/*, Game*/)
.sequence('id')
.attr('is_over', false)
.attr('created_at', function() { return new Date(); })
.attr('random_seed', function() { return Math.random(); })
// Default to two players. If players were given, fill in
// whatever attributes might be missing.
.attr('players', ['players'], function(players) {
if (!players) { players = [{}, {}]; }
return players.map(function(data) {
return Factory.attributes('player', data);
});
});
Factory.define('player')
.sequence('id')
.sequence('name', function(i) { return 'player' + i; })
// Define `position` to depend on `id`.
.attr('position', ['id'], function(id) {
var positions = ['pitcher', '1st base', '2nd base', '3rd base'];
return positions[id % positions.length];
});
Factory.define('disabled-player').extend('player').attr('state', 'disabled')
Now you can build an object, passing in attributes that you want to override:
var game = Factory.build('game', {is_over:true});
Which returns an object that looks roughly like:
{
id: 1,
is_over: true, // overriden when building
created_at: Fri Apr 15 2011 12:02:25 GMT-0400 (EDT),
random_seed: 0.8999513240996748,
players: [
{id: 1, name:'Player 1'},
{id: 2, name:'Player 2'}
]
}
For a factory with a constructor, if you want just the attributes:
Factory.attributes('game') // return just the attributes
You can also define a callback function to be run after building an object:
Factory.define('coach')
.option('buildPlayer', false)
.sequence('id')
.attr('players', ['id', 'buildPlayer'], function(id, buildPlayer) {
if (buildPlayer) {
return [Factory.build('player', {coach_id: id})];
}
})
.after(function(coach, options) {
if (options.buildPlayer) {
console.log('built player:', coach.players[0]);
}
});
Factory.build('coach', {}, {buildPlayer: true});
To use Rosie in node, you'll need to require it first:
var Factory = require('rosie').Factory;
You might also choose to use unregistered factories, as it fits better with node's module pattern:
// factories/game.js
var Factory = require('rosie').Factory;
module.exports = new Factory()
.sequence('id')
.attr('is_over', false)
// etc
To use the unregistered Game
factory defined above:
var Game = require('./factories/game');
var game = Game.build({is_over: true});
Unregistered factories are even more natural in ES6:
// factories/game.js
import { Factory } from 'rosie';
export default new Factory()
.sequence('id')
.attr('is_over', false)
// etc
// index.js
import Game from './factories/game');
const game = Game.build({is_over: true});
A tool like babel is currently required to use this syntax.
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Install the test dependencies (
script/bootstrap
- requires NodeJS and npm) - Make your changes and make sure the tests pass (
npm test
) - Commit your changes (
git commit -am 'Added some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request
Thanks to Daniel Morrison for the name and Jon Hoyt for inspiration and brainstorming the idea.