UNPKG

remx

Version:
209 lines (169 loc) • 6.34 kB
import React from 'react'; import renderer from 'react-test-renderer'; import { StoreMock } from './StoreMock'; import remx from '../es6Remx'; import MyComponent from './UseConnectComponent'; import Store from './Store'; describe(`useConnect`, () => { let store; let storeMock; let renderSpy; const registerLoggerForDebug = remx.registerLoggerForDebug; beforeEach(() => { store = new Store(remx); storeMock = new StoreMock(); renderSpy = jest.fn(); }); it('renders normally', () => { const tree = renderer.create( <MyComponent store={store} renderSpy={renderSpy} />, ); expect(tree.toJSON().children).toEqual(['nothing']); expect(renderSpy).toHaveBeenCalledTimes(1); }); it('connected component automatically rerenders when selectors changes', async () => { const tree = renderer.create( <MyComponent store={store} renderSpy={renderSpy} />, ); expect(store.getters.getName()).toEqual('nothing'); expect(tree.toJSON().children).toEqual(['nothing']); expect(renderSpy).toHaveBeenCalledTimes(1); renderer.act(() => { store.setters.setName(`Gandalf`); }); expect(store.getters.getName()).toEqual('Gandalf'); expect(tree.toJSON().children).toEqual(['Gandalf']); expect(renderSpy).toHaveBeenCalledTimes(2); }); it.skip('should trigger a log event when a connected componentd re-rerendered', () => { renderer.create(<MyComponent store={store} renderSpy={renderSpy} />); expect(renderSpy).toHaveBeenCalledTimes(1); const spy = jest.fn(); registerLoggerForDebug(spy); renderer.act(() => { store.setters.setName(`Gandalf`); }); expect(renderSpy).toHaveBeenCalledTimes(2); const expectedEvents = { action: 'mapStateToProps', connectedComponentName: 'useConnect hook', returnValue: { dynamicObject: expect.anything(), name: 'Gandalf', product: undefined }, triggeredEvents: [ { action: 'getter', args: ['123'], name: 'getProduct' }, { action: 'getter', args: [], name: 'getDynamicObject' }, { action: 'getter', args: [], name: 'getName' } ] }; expect(spy.mock.calls[1][0]).toEqual(expectedEvents); }); describe('using remx.map', () => { it('detects changes on added keys', () => { const tree = renderer.create(<MyComponent store={store} />); expect(tree.toJSON().children).toEqual(['nothing']); renderer.act(() => { store.setters.addProduct('123', { title: 'my product' }); }); expect(tree.toJSON().children).toEqual(['my product']); }); }); it('should track dynamically added keys', () => { const tree = renderer.create( <MyComponent store={store} testDynamicObject />, ); expect(tree.toJSON().children).toEqual(['{}']); renderer.act(() => { store.setters.setDynamicObject('newKey', 'newValue'); }); expect(tree.toJSON().children).toEqual([ JSON.stringify({ newKey: 'newValue' }) ]); }); it('should track nested dynamically added keys', () => { const tree = renderer.create( <MyComponent store={store} testDynamicObject />, ); const nestedObject = { nestedKey: 'nestedValue' }; renderer.act(() => { store.setters.setDynamicObject('newKey', nestedObject); }); expect(tree.toJSON().children).toEqual([ JSON.stringify({ newKey: nestedObject }) ]); renderer.act(() => { store.setters.setDynamicObjectNestedValue('someNewValue'); }); expect(tree.toJSON().children).toEqual([ JSON.stringify({ newKey: { nestedKey: 'someNewValue' } }) ]); }); describe('dependencies', () => { it('should not update result on untracked values changes', () => { storeMock.setters.addProduct('123', { title: 'Initial' }); const props = { store: storeMock, renderSpy }; const tree = renderer.create(<MyComponent {...props} />); expect(tree.toJSON().children).toEqual(['Initial']); storeMock.setters.addProduct('123', { title: 'New' }); tree.update(<MyComponent {...props} />); expect(tree.toJSON().children).toEqual(['Initial']); }); it('should update result on untracked value changes if dependencies force to do so', () => { storeMock.setters.addProduct('123', { title: 'Initial' }); const props = { store: storeMock, renderSpy, dependenciesSelector: (props) => [props.store.getters.getProduct('123').title] }; const tree = renderer.create(<MyComponent {...props} />); expect(tree.toJSON().children).toEqual(['Initial']); storeMock.setters.addProduct('123', { title: 'New' }); tree.update(<MyComponent {...props} />); expect(tree.toJSON().children).toEqual(['New']); }); }); describe('errors handling', () => { it('should thow on error in mapStateToProps of 1st render', () => { const props = { store, mapStateToProps: () => { throw new Error('testError'); } }; const consoleSpy = jest.spyOn(console, 'warn').mockImplementation(); expect(() => { renderer.create(<MyComponent {...props} />); }).toThrow('testError'); expect(consoleSpy).toHaveBeenCalledWith( 'Encountered an uncaught exception that was thrown by mapStateToProps in useConnect hook', new Error('testError') ); consoleSpy.mockRestore(); }); it('should thow on error in mapStateToProps of update', () => { const props = { store, mapStateToProps: () => { if (props.store.getters.getProduct('123')) { throw new Error('testError'); } return {}; } }; const tree = renderer.create(<MyComponent {...props} />); const consoleSpy = jest.spyOn(console, 'warn').mockImplementation(); renderer.act(() => { store.setters.addProduct('123', { title: 'my product' }); }); expect(consoleSpy).toHaveBeenCalledWith( 'Encountered an uncaught exception that was thrown by mapStateToProps in useConnect hook', new Error('testError') ); consoleSpy.mockRestore(); expect(() => { tree.update(<MyComponent {...props} />); }).toThrow('testError'); }); }); });