UNPKG

@sigi/react

Version:

React bindings for sigi framework

193 lines 7.18 kB
import { __decorate, __metadata } from "tslib"; import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime"; import '@abraham/reflection'; import { Module, EffectModule, Effect, ImmerReducer } from '@sigi/core'; import { useEffect } from 'react'; import { render, act } from '@testing-library/react'; import { Observable, timer } from 'rxjs'; import { mergeMap, map, endWith, switchMap } from 'rxjs/operators'; import { useModuleState, useModule } from '../index.browser'; let CountModel = class CountModel extends EffectModule { constructor() { super(...arguments); this.defaultState = { count: 0, name: 'John Doe' }; } setCount(state, count) { state.count = count; } setName(state, name) { state.name = name; } getCount(payload$) { return payload$.pipe(mergeMap(() => timer(20).pipe(map(() => this.getActions().setCount(1)), endWith(this.terminate())))); } skippedEffect(payload$) { return payload$.pipe(switchMap((name) => timer(20).pipe(map(() => this.getActions().setName(name)), endWith(this.terminate())))); } }; __decorate([ ImmerReducer(), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Number]), __metadata("design:returntype", void 0) ], CountModel.prototype, "setCount", null); __decorate([ ImmerReducer(), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, String]), __metadata("design:returntype", void 0) ], CountModel.prototype, "setName", null); __decorate([ Effect({ ssr: true, }), __metadata("design:type", Function), __metadata("design:paramtypes", [Observable]), __metadata("design:returntype", Observable) ], CountModel.prototype, "getCount", null); __decorate([ Effect({ payloadGetter: (ctx, skip) => ctx.url || skip, skipFirstClientDispatch: false, }), __metadata("design:type", Function), __metadata("design:paramtypes", [Observable]), __metadata("design:returntype", Observable) ], CountModel.prototype, "skippedEffect", null); CountModel = __decorate([ Module('CountModel') ], CountModel); describe('React components test', () => { const mockRender = jest.fn(); const TestComponent = () => { const state = useModuleState(CountModel); mockRender(); return (_jsxs("div", { children: [state.name, ": ", state.count] })); }; afterEach(() => { mockRender.mockReset(); }); it('should render once while initial rendering', () => { const node = render(_jsx(TestComponent, {})); expect(mockRender).toHaveBeenCalledTimes(1); expect(node.baseElement.innerHTML).toMatchSnapshot(); }); }); describe('Hooks', () => { const resetStore = jest.fn(); const setCount = jest.fn(); const mockRender = jest.fn(); const TestComponent = () => { const [state, dispatcher] = useModule(CountModel, { selector: (state) => { return state.count; }, }); mockRender(); useEffect(() => { setCount.mockImplementation(() => { dispatcher.setCount(10); }); resetStore.mockImplementation(() => { dispatcher.reset(); }); }, []); return _jsx("div", { children: state }); }; let testWrapper; beforeEach(() => { act(() => { testWrapper = render(_jsx(TestComponent, {})); }); }); afterEach(() => { act(() => { resetStore(); testWrapper.unmount(); }); mockRender.mockReset(); setCount.mockReset(); resetStore.mockReset(); }); it('could reset state from dispatcher', () => { var _a, _b, _c; expect((_a = testWrapper.container.querySelector('div')) === null || _a === void 0 ? void 0 : _a.textContent).toBe('0'); expect(mockRender).toHaveBeenCalledTimes(1); act(() => { setCount(); }); expect((_b = testWrapper.container.querySelector('div')) === null || _b === void 0 ? void 0 : _b.textContent).toBe('10'); expect(mockRender).toHaveBeenCalledTimes(2); act(() => { resetStore(); }); expect((_c = testWrapper.container.querySelector('div')) === null || _c === void 0 ? void 0 : _c.textContent).toBe('0'); expect(mockRender).toHaveBeenCalledTimes(3); }); it('should not re-render if return state shallow equaled', () => { var _a; const fooRenderSpy = jest.fn(); const FooComponent = () => { const state = useModuleState(CountModel, { selector: (state) => ({ name: state.name }), }); fooRenderSpy(); return _jsx("div", { children: state.name }); }; let fooWrapper; act(() => { fooWrapper = render(_jsx(FooComponent, {})); }); expect((_a = fooWrapper.container.querySelector('div')) === null || _a === void 0 ? void 0 : _a.textContent).toBe('John Doe'); act(() => { setCount(); }); expect(fooRenderSpy).toHaveBeenCalledTimes(1); expect(mockRender).toHaveBeenCalledTimes(2); fooRenderSpy.mockReset(); }); it('should re-render if return state not pass custom equality function', () => { var _a; const fooRenderSpy = jest.fn(); const FooComponent = () => { const state = useModuleState(CountModel, { selector: (state) => ({ name: state.name }), equalFn: (a, b) => a === b, }); fooRenderSpy(); return _jsx("div", { children: state.name }); }; let fooWrapper; act(() => { fooWrapper = render(_jsx(FooComponent, {})); }); expect((_a = fooWrapper.container.querySelector('div')) === null || _a === void 0 ? void 0 : _a.textContent).toBe('John Doe'); act(() => { setCount(); }); expect(fooRenderSpy).toHaveBeenCalledTimes(2); fooRenderSpy.mockReset(); }); it('Child <-> Parent scenario', () => { var _a, _b; const name = 'tj'; const ChildComponent = () => { const [state, dispatcher] = useModule(CountModel); useEffect(() => { dispatcher.setName(name); }, [dispatcher]); return _jsx("span", { children: state.name }); }; const FooComponent = () => { const state = useModuleState(CountModel); return (_jsxs("div", { children: [state.name, _jsx(ChildComponent, {})] })); }; let fooWrapper; act(() => { fooWrapper = render(_jsx(FooComponent, {})); }); expect((_a = fooWrapper.container.querySelector('span')) === null || _a === void 0 ? void 0 : _a.textContent).toBe(name); expect((_b = fooWrapper.container.querySelector('div')) === null || _b === void 0 ? void 0 : _b.childNodes.item(0).textContent).toBe(name); }); }); //# sourceMappingURL=react.spec.js.map