Skip to content

Commit

Permalink
feat: make resetting sequences easier in testing
Browse files Browse the repository at this point in the history
When defining factories that use sequences there's no public API for resetting the sequences at the start of every test. This commit adds `Factory.resetAll()` to make resetting all factory sequences easy, including both named and unnamed factories.
  • Loading branch information
eventualbuddha committed Mar 24, 2021
1 parent d8398d4 commit 0393a3d
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 3 deletions.
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,28 @@ Identical to `.build` except it returns an array of built objects. `size` is req
- **Factory.buildList(`factory_name`, size, `attributes`, `options`)** - when buildList is called against the rosie Factory singleton, the first param is the name of the factory to use to build the object. The `attributes` and `options` behave the same as the call to `.build`.
- **instance.buildList(size, `attributes`, `options`)** - when buildList is called on a factory instance only the size, `attributes` and `options` objects are necessary (strictly speaking only the size is necessary)

### Testing

You may find `resetAll` useful when working with testing frameworks such as Jest. It resets any build state, such as sequences, to their original values:

```js
import Factory from 'rosie';

beforeEach(() => {
Factory.resetAll();
});
```

Or call `reset` on a specific factory:

```js
import Game from './game';

beforeEach(() => {
Game.reset();
});
```

## Contributing

1. Fork it
Expand Down
43 changes: 42 additions & 1 deletion src/__tests__/rosie.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const { Factory } = require('../rosie');

describe('Factory', () => {
afterEach(() => {
Factory.factories = {};
Factory.implode();
});

describe('build', () => {
Expand Down Expand Up @@ -224,6 +224,13 @@ describe('Factory', () => {
const list = Another.buildList(2, {}, {});
expect(list[0].number).not.toEqual(list[1].number);
});

it('should be reset by resetAll', () => {
const Counter = new Factory().sequence('count');
expect(Counter.build()).toEqual({ count: 1 });
Factory.resetAll();
expect(Counter.build()).toEqual({ count: 1 });
});
});
});

Expand All @@ -247,6 +254,7 @@ describe('Factory', () => {
beforeEach(() => {
Factory.define('thing', Thing)
.attr('name', 'Thing 1')
.sequence('count')
.after((obj) => {
obj.afterCalled = true;
});
Expand Down Expand Up @@ -278,6 +286,32 @@ describe('Factory', () => {
it('should override attributes', () => {
expect(Factory.build('differentThing').name).toBe('Different Thing');
});

it('should reset sequences', () => {
expect(Factory.build('thing')).toEqual(
expect.objectContaining({ count: 1 })
);
expect(Factory.build('thing')).toEqual(
expect.objectContaining({ count: 2 })
);
Factory.reset('thing');
expect(Factory.build('thing')).toEqual(
expect.objectContaining({ count: 1 })
);
});

it('should be reset by resetAll', () => {
expect(Factory.build('thing')).toEqual(
expect.objectContaining({ count: 1 })
);
expect(Factory.build('thing')).toEqual(
expect.objectContaining({ count: 2 })
);
Factory.resetAll();
expect(Factory.build('thing')).toEqual(
expect.objectContaining({ count: 1 })
);
});
});

describe('with unregistered factories', () => {
Expand Down Expand Up @@ -528,6 +562,13 @@ describe('Factory', () => {
time: startTime + 2,
});
});

it('should be able to be reset', () => {
factory.sequence('count');
expect(factory.attributes()).toEqual({ count: 1 });
factory.reset();
expect(factory.attributes()).toEqual({ count: 1 });
});
});

describe('attributes', () => {
Expand Down
42 changes: 40 additions & 2 deletions src/rosie.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/**
* Creates a new factory with attributes, options, etc. to be used to build
* objects. Generally you should use `Factory.define()` instead of this
* constructor.
* objects.
*
* @param {Function=} constructor
* @class
Expand All @@ -13,6 +12,8 @@ class Factory {
this.opts = {};
this.sequences = {};
this.callbacks = [];

Factory._allFactories.push(this);
}

/**
Expand Down Expand Up @@ -351,9 +352,21 @@ class Factory {
this.callbacks = factory.callbacks.slice();
return this;
}

/**
* Resets any state changed by building objects back to the original values.
* Preserves attributes and options as-is.
*/
reset() {
this.sequences = {};
}
}

Factory.factories = {};
Object.defineProperty(Factory, '_allFactories', {
value: [],
enumerable: false,
});

/**
* Defines a factory by name and constructor function. Call #attr and #option
Expand Down Expand Up @@ -413,6 +426,31 @@ Factory.attributes = function (name, attributes, options) {
return this.factories[name].attributes(attributes, options);
};

/**
* Resets a factory by name. Preserves attributes and options as-is.
*
* @param {string} name
*/
Factory.reset = function (name) {
Factory.factories[name].reset();
};

/**
* Resets all factory build state. Preserves attributes and options as-is.
*/
Factory.resetAll = function () {
Factory._allFactories.forEach((factory) => factory.reset());
};

/**
* Unregister and forget all existing factories.
*/
Factory.implode = function () {
Factory.factories = {};
Factory._allFactories.length = 0;
};

/* istanbul ignore next */
if (typeof exports === 'object' && typeof module !== 'undefined') {
/* eslint-env commonjs */
exports.Factory = Factory;
Expand Down

0 comments on commit 0393a3d

Please sign in to comment.