import * as React from 'react'; import { mount, render } from 'enzyme'; import { merge, Observable, of, Subject } from 'rxjs'; import { map, scan, startWith, switchMap } from 'rxjs/operators'; import { combineProps, connect, RxReactContainer } from '.'; interface AppProps { onMinus: (event: any) => void; onPlus: (event: any) => void; totalCount: number; title: string; } function App({ onMinus, onPlus, totalCount, title }: AppProps) { return (

{title}

[{totalCount}]
); } App.navStatic = { header: 'ok', }; interface ContainerProps { step: number; heading: string; } function sampleController( container: RxReactContainer ): Observable { const onMinus$ = new Subject(); const onPlus$ = new Subject(); const click$ = merge( onMinus$.pipe(map(() => -1)), onPlus$.pipe(map(() => +1)) ); const totalCount$ = container.getProp('step').pipe( switchMap(step => click$.pipe(map(v => v * step))), startWith(0), scan((acc, x) => acc + x, 0) ); const title$ = container .getProps('step', 'heading') .pipe(map(([step, heading]) => `${heading} - ${step}`)); return combineProps( { totalCount: totalCount$, title: title$ }, { onMinus: onMinus$, onPlus: onPlus$ } ); } const AppContainer = connect(sampleController)(App); test('connect', done => { const wrapper = mount(); expect(wrapper.find('#count').text()).toBe('0'); expect(wrapper.find('#title').text()).toBe('Test - 1'); wrapper.find('#plus').simulate('click'); expect(wrapper.find('#count').text()).toBe('1'); wrapper.find('#plus').simulate('click'); wrapper.find('#plus').simulate('click'); expect(wrapper.find('#count').text()).toBe('3'); wrapper.find('#minus').simulate('click'); wrapper.find('#minus').simulate('click'); expect(wrapper.find('#count').text()).toBe('1'); wrapper.setProps({ step: 3 }); expect(wrapper.find('#title').text()).toBe('Test - 3'); wrapper.find('#plus').simulate('click'); expect(wrapper.find('#count').text()).toBe('4'); wrapper.find('#minus').simulate('click'); expect(wrapper.find('#count').text()).toBe('1'); wrapper.setProps({ step: 3, heading: 'New' }); expect(wrapper.find('#title').text()).toBe('New - 3'); expect(wrapper.find('#count').text()).toBe('1'); wrapper.setProps({ step: 3 }); expect(wrapper.find('#title').text()).toBe('New - 3'); expect(wrapper.find('#count').text()).toBe('1'); wrapper.unmount(); done(); }); test('connect to throw if no observable returned', () => { expect(() => { // @ts-ignore const Cmp = connect(() => 0)(() => null); // @ts-ignore return new Cmp({}, {}); }).toThrow('controller should return an observable'); }); test('connect - displayName', () => { const Cmp1 = connect(() => of({}))(function Name1() { return null; }); expect(Cmp1.displayName).toBe('connect(Name1)'); const NODE_ENV = process.env.NODE_ENV; process.env.NODE_ENV = 'production'; const Cmp2 = connect(() => of({}))(function Name2() { return null; }); expect(Cmp2.displayName).toBe(undefined); process.env.NODE_ENV = NODE_ENV; }); test('connect - keep component statics', () => { // @ts-ignore expect(AppContainer.navStatic).toEqual({ header: 'ok' }); }); test('server side rendering', () => { const wrapper = render(); expect(wrapper.find('#count').text()).toBe('0'); expect(wrapper.find('#title').text()).toBe('Test - 1'); });