tuxx
Version:
Framework built on React and Flux
392 lines (312 loc) • 22.9 kB
JavaScript
;
var moduleToTest = 'tuxx/src/TuxxStoreMixinGenerator';
jest.dontMock(moduleToTest);
describe('TuxxStoreMixinGenerator', function () {
var TuxxStoreMixinGenerator, mockStore1, mockStore2, mockListener1, mockListener2, mockListener3, mockListener4, mockEvent1, mockEvent2, mockEvent3, mockEvent4, mockConnectComposerToStore1, mockConnectComposerToStoreReturn1, mockConnectComposerToStore2, mockConnectComposerToStoreReturn2, mockMixin;
beforeEach(function () {
TuxxStoreMixinGenerator = require(moduleToTest);
mockStore1 = {
addChangeListener: jest.genMockFunction(),
removeChangeListener: jest.genMockFunction()
};
mockStore2 = {
addChangeListener: jest.genMockFunction(),
removeChangeListener: jest.genMockFunction()
};
mockListener1 = jest.genMockFunction();
mockListener2 = jest.genMockFunction();
mockListener3 = jest.genMockFunction();
mockListener4 = jest.genMockFunction();
mockEvent1 = 'CHANGE1';
mockEvent2 = 'CHANGE2';
mockEvent3 = 'CHANGE3';
mockEvent4 = 'CHANGE4';
mockConnectComposerToStoreReturn1 = { store: mockStore1 };
mockConnectComposerToStore1 = function () {
return mockConnectComposerToStoreReturn1;
};
mockConnectComposerToStoreReturn2 = { store: mockStore2 };
mockConnectComposerToStore2 = function () {
return mockConnectComposerToStoreReturn2;
};
});
it('should return an empty object when no inut argument supplied', function () {
expect(TuxxStoreMixinGenerator()).toEqual({});
});
describe('mockConnectComposerToStore function', function () {
describe('single event and listener on mockConnectComposerToStoreReturn1 object', function () {
beforeEach(function () {
mockConnectComposerToStoreReturn1.listener = mockListener1;
mockConnectComposerToStoreReturn1.event = mockEvent1;
mockMixin = TuxxStoreMixinGenerator(mockConnectComposerToStore1);
});
it('should return an object with componentDidMount and componentWillUnmount keys', function () {
expect(mockMixin.componentDidMount).toBeDefined();
expect(mockMixin.componentWillUnmount).toBeDefined();
});
it('should add a change listener for provided event on componentDidMount', function () {
mockMixin.componentDidMount();
expect(mockStore1.addChangeListener.mock.calls[0][0]).toBe(mockConnectComposerToStoreReturn1.listener);
expect(mockStore1.addChangeListener.mock.calls[0][1]).toBe(mockConnectComposerToStoreReturn1.event);
expect(mockStore1.addChangeListener.mock.calls.length).toBe(1);
});
it('should remove a change listener for provided event on componentWillUnmount', function () {
mockMixin.componentDidMount();
mockMixin.componentWillUnmount();
expect(mockStore1.removeChangeListener.mock.calls[0][0]).toBe(mockConnectComposerToStoreReturn1.listener);
expect(mockStore1.removeChangeListener.mock.calls[0][1]).toBe(mockConnectComposerToStoreReturn1.event);
expect(mockStore1.removeChangeListener.mock.calls.length).toBe(1);
});
});
describe('more events than listeners', function () {
beforeEach(function () {
mockConnectComposerToStoreReturn1.listener = [mockListener1, mockListener2];
mockConnectComposerToStoreReturn1.event = [mockEvent1, mockEvent2, mockEvent3, mockEvent4];
mockMixin = TuxxStoreMixinGenerator(mockConnectComposerToStore1);
});
it('adds listeners and events one for one, until events are greater than listener length, at which point the last listener gets assigned to remaining events on componentDidMount', function () {
// addChangeListener should not have been called yet
expect(mockStore1.addChangeListener.mock.calls.length).toBe(0);
mockMixin.componentDidMount();
// addChangeListener should have been called once for each mockEvent
expect(mockStore1.addChangeListener.mock.calls.length).toBe(4);
// first call of addChangeListener
expect(mockStore1.addChangeListener.mock.calls[0][0]).toBe(mockConnectComposerToStoreReturn1.listener[0]);
expect(mockStore1.addChangeListener.mock.calls[0][1]).toBe(mockConnectComposerToStoreReturn1.event[0]);
// second call of addChangeListener
expect(mockStore1.addChangeListener.mock.calls[1][0]).toBe(mockConnectComposerToStoreReturn1.listener[1]);
expect(mockStore1.addChangeListener.mock.calls[1][1]).toBe(mockConnectComposerToStoreReturn1.event[1]);
// third call of addChangeListener
expect(mockStore1.addChangeListener.mock.calls[2][0]).toBe(mockConnectComposerToStoreReturn1.listener[1]);
expect(mockStore1.addChangeListener.mock.calls[2][1]).toBe(mockConnectComposerToStoreReturn1.event[2]);
// fourth call of addChangeListener
expect(mockStore1.addChangeListener.mock.calls[3][0]).toBe(mockConnectComposerToStoreReturn1.listener[1]);
expect(mockStore1.addChangeListener.mock.calls[3][1]).toBe(mockConnectComposerToStoreReturn1.event[3]);
});
it('removes the mapped change listeners to events, when there are more events than listeners, on componentWillUnmount', function () {
// removeChangeListener should not have been called yet
expect(mockStore1.removeChangeListener.mock.calls.length).toBe(0);
mockMixin.componentDidMount();
mockMixin.componentWillUnmount();
// removeChangeListener should have been called once for each mockEvent
expect(mockStore1.removeChangeListener.mock.calls.length).toBe(4);
// first call of removeChangeListener
expect(mockStore1.removeChangeListener.mock.calls[0][0]).toBe(mockConnectComposerToStoreReturn1.listener[0]);
expect(mockStore1.removeChangeListener.mock.calls[0][1]).toBe(mockConnectComposerToStoreReturn1.event[0]);
// second call of removeChangeListener
expect(mockStore1.removeChangeListener.mock.calls[1][0]).toBe(mockConnectComposerToStoreReturn1.listener[1]);
expect(mockStore1.removeChangeListener.mock.calls[1][1]).toBe(mockConnectComposerToStoreReturn1.event[1]);
// third call of removeChangeListener
expect(mockStore1.removeChangeListener.mock.calls[2][0]).toBe(mockConnectComposerToStoreReturn1.listener[1]);
expect(mockStore1.removeChangeListener.mock.calls[2][1]).toBe(mockConnectComposerToStoreReturn1.event[2]);
// fourth call of removeChangeListener
expect(mockStore1.removeChangeListener.mock.calls[3][0]).toBe(mockConnectComposerToStoreReturn1.listener[1]);
expect(mockStore1.removeChangeListener.mock.calls[3][1]).toBe(mockConnectComposerToStoreReturn1.event[3]);
});
});
describe('more listeners than events', function () {
beforeEach(function () {
mockConnectComposerToStoreReturn1.listener = [mockListener1, mockListener2, mockListener3, mockListener4];
mockConnectComposerToStoreReturn1.event = [mockEvent1, mockEvent2];
mockMixin = TuxxStoreMixinGenerator(mockConnectComposerToStore1);
});
it('should assign events one for one until there are more listeners than events, at which point the last event will be assigned to remaining listeners on componentDidMount', function () {
// addChangeListener should not have been called yet
expect(mockStore1.addChangeListener.mock.calls.length).toBe(0);
mockMixin.componentDidMount();
// addChangeListener should have been called once for each listener
expect(mockStore1.addChangeListener.mock.calls.length).toBe(4);
// first addChangeListener call
expect(mockStore1.addChangeListener.mock.calls[0][0]).toBe(mockConnectComposerToStoreReturn1.listener[0]);
expect(mockStore1.addChangeListener.mock.calls[0][1]).toBe(mockConnectComposerToStoreReturn1.event[0]);
// second addChangeListener call
expect(mockStore1.addChangeListener.mock.calls[1][0]).toBe(mockConnectComposerToStoreReturn1.listener[1]);
expect(mockStore1.addChangeListener.mock.calls[1][1]).toBe(mockConnectComposerToStoreReturn1.event[1]);
// third addChangeListener call
expect(mockStore1.addChangeListener.mock.calls[2][0]).toBe(mockConnectComposerToStoreReturn1.listener[2]);
expect(mockStore1.addChangeListener.mock.calls[2][1]).toBe(mockConnectComposerToStoreReturn1.event[1]);
// fourth addChangeListener call
expect(mockStore1.addChangeListener.mock.calls[3][0]).toBe(mockConnectComposerToStoreReturn1.listener[3]);
expect(mockStore1.addChangeListener.mock.calls[3][1]).toBe(mockConnectComposerToStoreReturn1.event[1]);
});
it('removes the mapped change listeners to events, when there are more listeners than events, on componentWillUnmount', function () {
// removeChangeListener should not have been called yet
expect(mockStore1.removeChangeListener.mock.calls.length).toBe(0);
mockMixin.componentDidMount();
mockMixin.componentWillUnmount();
// removeChangeListener should have been called once for each mockEvent
expect(mockStore1.removeChangeListener.mock.calls.length).toBe(4);
// first removeChangeListener call
expect(mockStore1.removeChangeListener.mock.calls[0][0]).toBe(mockConnectComposerToStoreReturn1.listener[0]);
expect(mockStore1.removeChangeListener.mock.calls[0][1]).toBe(mockConnectComposerToStoreReturn1.event[0]);
// second removeChangeListener call
expect(mockStore1.removeChangeListener.mock.calls[1][0]).toBe(mockConnectComposerToStoreReturn1.listener[1]);
expect(mockStore1.removeChangeListener.mock.calls[1][1]).toBe(mockConnectComposerToStoreReturn1.event[1]);
// third removeChangeListener call
expect(mockStore1.removeChangeListener.mock.calls[2][0]).toBe(mockConnectComposerToStoreReturn1.listener[2]);
expect(mockStore1.removeChangeListener.mock.calls[2][1]).toBe(mockConnectComposerToStoreReturn1.event[1]);
// fourth removeChangeListener call
expect(mockStore1.removeChangeListener.mock.calls[3][0]).toBe(mockConnectComposerToStoreReturn1.listener[3]);
expect(mockStore1.removeChangeListener.mock.calls[3][1]).toBe(mockConnectComposerToStoreReturn1.event[1]);
});
});
describe('no event type provided', function () {
beforeEach(function () {
mockConnectComposerToStoreReturn1.listener = [mockListener2, mockListener4];
mockMixin = TuxxStoreMixinGenerator(mockConnectComposerToStore1);
});
// The addChangeListener on the real store will assign a default change event, which is overwritten
// by the second input argument, so the test ensures that that input argument is undefined and thus will go to the default
it('should assign undefined as the event type when no event type provided on componentDidMount', function () {
// addChangeListener should not have been called yet
expect(mockStore1.addChangeListener.mock.calls.length).toBe(0);
mockMixin.componentDidMount();
// addChangeListener should have been called once for each mockListener
expect(mockStore1.addChangeListener.mock.calls.length).toBe(2);
// first call of addChangeListener
expect(mockStore1.addChangeListener.mock.calls[0][0]).toBe(mockConnectComposerToStoreReturn1.listener[0]);
expect(mockStore1.addChangeListener.mock.calls[0][1]).toBeUndefined();
// second call of addChangeListener
expect(mockStore1.addChangeListener.mock.calls[1][0]).toBe(mockConnectComposerToStoreReturn1.listener[1]);
expect(mockStore1.addChangeListener.mock.calls[1][1]).toBeUndefined();
});
// The removeChangeListener on the real store will assign a default change event, which is overwritten
// by the second input argument, so the test ensures that that input argument is undefined and thus will go to the default
it('removes the mapped listeners, on componentWillUnmount, when no event type is specified', function () {
// removeChangeListener should not have been called yet
expect(mockStore1.removeChangeListener.mock.calls.length).toBe(0);
mockMixin.componentDidMount();
mockMixin.componentWillUnmount();
// removeChangeListener should have been called once for each mockListener
expect(mockStore1.removeChangeListener.mock.calls.length).toBe(2);
// first call of removeChangeListener
expect(mockStore1.removeChangeListener.mock.calls[0][0]).toBe(mockConnectComposerToStoreReturn1.listener[0]);
expect(mockStore1.removeChangeListener.mock.calls[0][1]).toBeUndefined();
// second call of removeChangeListener
expect(mockStore1.removeChangeListener.mock.calls[1][0]).toBe(mockConnectComposerToStoreReturn1.listener[1]);
expect(mockStore1.removeChangeListener.mock.calls[1][1]).toBeUndefined();
});
});
});
describe('array of mockConnectComposerToStore functions', function () {
beforeEach(function () {
mockConnectComposerToStoreReturn1.listener = [mockListener1, mockListener3, mockListener4];
mockConnectComposerToStoreReturn1.event = [mockEvent2, mockEvent3];
mockConnectComposerToStoreReturn2.listener = [mockListener2, mockListener3];
mockConnectComposerToStoreReturn2.event = [mockEvent1, mockEvent3, mockEvent4];
mockMixin = TuxxStoreMixinGenerator([mockConnectComposerToStore1, mockConnectComposerToStore2]);
});
it('add change listeners to each individual store when multiple stores provided', function () {
// addChangeListener should not have been called on either store yet
expect(mockStore1.addChangeListener.mock.calls.length).toBe(0);
expect(mockStore2.addChangeListener.mock.calls.length).toBe(0);
// add change listeners to mockStore1 and mockStore2
mockMixin.componentDidMount();
// mockStore1 addChangeListener count should increase and mockStore2 addChangeListener count should remain the same
expect(mockStore1.addChangeListener.mock.calls.length).toBe(3);
expect(mockStore2.addChangeListener.mock.calls.length).toBe(3);
// first call of addChangeListener on mockStore1
expect(mockStore1.addChangeListener.mock.calls[0][0]).toBe(mockConnectComposerToStoreReturn1.listener[0]);
expect(mockStore1.addChangeListener.mock.calls[0][1]).toBe(mockConnectComposerToStoreReturn1.event[0]);
// second call of addChangeListener on mockStore1
expect(mockStore1.addChangeListener.mock.calls[1][0]).toBe(mockConnectComposerToStoreReturn1.listener[1]);
expect(mockStore1.addChangeListener.mock.calls[1][1]).toBe(mockConnectComposerToStoreReturn1.event[1]);
// third call of addChangeListener on mockStore1
expect(mockStore1.addChangeListener.mock.calls[2][0]).toBe(mockConnectComposerToStoreReturn1.listener[2]);
expect(mockStore1.addChangeListener.mock.calls[2][1]).toBe(mockConnectComposerToStoreReturn1.event[1]);
// first call of addChangeListener on mockStore2
expect(mockStore2.addChangeListener.mock.calls[0][0]).toBe(mockConnectComposerToStoreReturn2.listener[0]);
expect(mockStore2.addChangeListener.mock.calls[0][1]).toBe(mockConnectComposerToStoreReturn2.event[0]);
// second call of addChangeListener on mockStore2
expect(mockStore2.addChangeListener.mock.calls[1][0]).toBe(mockConnectComposerToStoreReturn2.listener[1]);
expect(mockStore2.addChangeListener.mock.calls[1][1]).toBe(mockConnectComposerToStoreReturn2.event[1]);
// third call of addChangeListener on mockStore2
expect(mockStore2.addChangeListener.mock.calls[2][0]).toBe(mockConnectComposerToStoreReturn2.listener[1]);
expect(mockStore2.addChangeListener.mock.calls[2][1]).toBe(mockConnectComposerToStoreReturn2.event[2]);
});
it('should remove change listeners on each individual store when multiple stores provided', function () {
// removeChangeListener should not have been called on either store yet
expect(mockStore1.removeChangeListener.mock.calls.length).toBe(0);
expect(mockStore2.removeChangeListener.mock.calls.length).toBe(0);
// remove change listeners from mockStore1 and mockStore2
mockMixin.componentDidMount();
mockMixin.componentWillUnmount();
// mockStore1 removeChangeListener count should increase and mockStore2 removeChangeListener count should remain the same
expect(mockStore1.removeChangeListener.mock.calls.length).toBe(3);
expect(mockStore2.removeChangeListener.mock.calls.length).toBe(3);
// first call of removeChangeListener on mockStore1
expect(mockStore1.removeChangeListener.mock.calls[0][0]).toBe(mockConnectComposerToStoreReturn1.listener[0]);
expect(mockStore1.removeChangeListener.mock.calls[0][1]).toBe(mockConnectComposerToStoreReturn1.event[0]);
// second call of removeChangeListener on mockStore1
expect(mockStore1.removeChangeListener.mock.calls[1][0]).toBe(mockConnectComposerToStoreReturn1.listener[1]);
expect(mockStore1.removeChangeListener.mock.calls[1][1]).toBe(mockConnectComposerToStoreReturn1.event[1]);
// third call of removeChangeListener on mockStore1
expect(mockStore1.removeChangeListener.mock.calls[2][0]).toBe(mockConnectComposerToStoreReturn1.listener[2]);
expect(mockStore1.removeChangeListener.mock.calls[2][1]).toBe(mockConnectComposerToStoreReturn1.event[1]);
// first call of removeChangeListener on mockStore2
expect(mockStore2.removeChangeListener.mock.calls[0][0]).toBe(mockConnectComposerToStoreReturn2.listener[0]);
expect(mockStore2.removeChangeListener.mock.calls[0][1]).toBe(mockConnectComposerToStoreReturn2.event[0]);
// second call of removeChangeListener on mockStore2
expect(mockStore2.removeChangeListener.mock.calls[1][0]).toBe(mockConnectComposerToStoreReturn2.listener[1]);
expect(mockStore2.removeChangeListener.mock.calls[1][1]).toBe(mockConnectComposerToStoreReturn2.event[1]);
// third call of removeChangeListener on mockStore2
expect(mockStore2.removeChangeListener.mock.calls[2][0]).toBe(mockConnectComposerToStoreReturn2.listener[1]);
expect(mockStore2.removeChangeListener.mock.calls[2][1]).toBe(mockConnectComposerToStoreReturn2.event[2]);
});
});
describe('no event type provided on one mockStore', function () {
beforeEach(function () {
mockConnectComposerToStoreReturn1.listener = [mockListener1, mockListener3];
mockConnectComposerToStoreReturn2.listener = [mockListener2, mockListener3];
mockConnectComposerToStoreReturn2.event = [mockEvent1, mockEvent4];
mockMixin = TuxxStoreMixinGenerator([mockConnectComposerToStore1, mockConnectComposerToStore2]);
});
// The addChangeListener on the real store will assign a default change event, which is overwritten
// by the second input argument, so the test ensures that that input argument is undefined and thus will go to the default
it('should assign undefined as the event type when no event type provided, while also mapping provided event types to listeners, on componentDidMount', function () {
// addChangeListener should not have been called yet
expect(mockStore1.addChangeListener.mock.calls.length).toBe(0);
expect(mockStore2.addChangeListener.mock.calls.length).toBe(0);
mockMixin.componentDidMount();
// addChangeListener should have been called once for each mockListener on both mockStores
expect(mockStore1.addChangeListener.mock.calls.length).toBe(2);
expect(mockStore2.addChangeListener.mock.calls.length).toBe(2);
// first call of addChangeListener on mockStore1
expect(mockStore1.addChangeListener.mock.calls[0][0]).toBe(mockConnectComposerToStoreReturn1.listener[0]);
expect(mockStore1.addChangeListener.mock.calls[0][1]).toBeUndefined();
// second call of addChangeListener on mockStore1
expect(mockStore1.addChangeListener.mock.calls[1][0]).toBe(mockConnectComposerToStoreReturn1.listener[1]);
expect(mockStore1.addChangeListener.mock.calls[1][1]).toBeUndefined();
// first call of addChangeListener on mockStore2
expect(mockStore2.addChangeListener.mock.calls[0][0]).toBe(mockConnectComposerToStoreReturn2.listener[0]);
expect(mockStore2.addChangeListener.mock.calls[0][1]).toBe(mockConnectComposerToStoreReturn2.event[0]);
// second call of addChangeListener on mockStore2
expect(mockStore2.addChangeListener.mock.calls[1][0]).toBe(mockConnectComposerToStoreReturn2.listener[1]);
expect(mockStore2.addChangeListener.mock.calls[1][1]).toBe(mockConnectComposerToStoreReturn2.event[1]);
});
// The removeChangeListener on the real store will assign a default change event, which is overwritten
// by the second input argument, so the test ensures that that input argument is undefined and thus will go to the default
it('removes the mapped listeners, on componentWillUnmount, when no event type is specified, as well as when they are provided', function () {
// removeChangeListener should not have been called yet on either mockStore
expect(mockStore1.removeChangeListener.mock.calls.length).toBe(0);
expect(mockStore2.removeChangeListener.mock.calls.length).toBe(0);
mockMixin.componentDidMount();
mockMixin.componentWillUnmount();
// removeChangeListener should have been called once for each mockListener on each mockStore
expect(mockStore1.removeChangeListener.mock.calls.length).toBe(2);
expect(mockStore2.removeChangeListener.mock.calls.length).toBe(2);
// first call of removeChangeListener on mockStore1
expect(mockStore1.removeChangeListener.mock.calls[0][0]).toBe(mockConnectComposerToStoreReturn1.listener[0]);
expect(mockStore1.removeChangeListener.mock.calls[0][1]).toBeUndefined();
// second call of removeChangeListener on mockStore1
expect(mockStore1.removeChangeListener.mock.calls[1][0]).toBe(mockConnectComposerToStoreReturn1.listener[1]);
expect(mockStore1.removeChangeListener.mock.calls[1][1]).toBeUndefined();
// first call of removeChangeListener on mockStore2
expect(mockStore2.removeChangeListener.mock.calls[0][0]).toBe(mockConnectComposerToStoreReturn2.listener[0]);
expect(mockStore2.removeChangeListener.mock.calls[0][1]).toBe(mockConnectComposerToStoreReturn2.event[0]);
// second call of removeChangeListener on mockStore2
expect(mockStore2.removeChangeListener.mock.calls[1][0]).toBe(mockConnectComposerToStoreReturn2.listener[1]);
expect(mockStore2.removeChangeListener.mock.calls[1][1]).toBe(mockConnectComposerToStoreReturn2.event[1]);
});
});
});