123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- import * as React from 'react';
- import { View, Text } from 'react-native';
- import * as renderer from 'react-test-renderer';
- import { ComponentWrapper } from './ComponentWrapper';
- import { Store } from './Store';
- import { mock, verify, instance } from 'ts-mockito';
- import { ComponentEventsObserver } from '../events/ComponentEventsObserver';
-
- describe('ComponentWrapper', () => {
- const componentName = 'example.MyComponent';
- let store: Store;
- let myComponentProps: any;
- let mockedComponentEventsObserver: ComponentEventsObserver;
- let componentEventsObserver: ComponentEventsObserver;
- let uut: ComponentWrapper;
-
- class MyComponent extends React.Component<any, any> {
- static options = {
- title: 'MyComponentTitle'
- };
-
- render() {
- myComponentProps = this.props;
- if (this.props.renderCount) {
- this.props.renderCount();
- }
- return <Text>{this.props.text || 'Hello, World!'}</Text>;
- }
- }
-
- class TestParent extends React.Component<any, any> {
- private ChildClass: any;
-
- constructor(props: any) {
- super(props);
- this.ChildClass = props.ChildClass;
- this.state = { propsFromState: {} };
- }
-
- render() {
- return (
- <this.ChildClass
- componentId='component1'
- {...this.state.propsFromState}
- />
- );
- }
- }
-
- beforeEach(() => {
- store = new Store();
- mockedComponentEventsObserver = mock(ComponentEventsObserver);
- componentEventsObserver = instance(mockedComponentEventsObserver);
- uut = new ComponentWrapper();
- });
-
- it('must have componentId as prop', () => {
- const NavigationComponent = uut.wrap(componentName, () => MyComponent, store, componentEventsObserver);
- const orig = console.error;
- console.error = (a: any) => a;
- expect(() => {
- renderer.create(<NavigationComponent />);
- }).toThrowError('Component example.MyComponent does not have a componentId!');
- console.error = orig;
- });
-
- it('wraps the component', () => {
- const NavigationComponent = uut.wrap(componentName, () => MyComponent, store, componentEventsObserver);
- expect(NavigationComponent).not.toBeInstanceOf(MyComponent);
- const tree = renderer.create(<NavigationComponent componentId={'component1'} />);
- expect(tree.toJSON()!.children).toEqual(['Hello, World!']);
- });
-
- it('injects props from wrapper into original component', () => {
- const renderCount = jest.fn();
- const NavigationComponent = uut.wrap(componentName, () => MyComponent, store, componentEventsObserver);
- const tree = renderer.create(<NavigationComponent componentId={'component1'} text={'yo'} renderCount={renderCount} />);
- expect(tree.toJSON()!.children).toEqual(['yo']);
- expect(renderCount).toHaveBeenCalledTimes(1);
- });
-
- it('updates props from wrapper into original component on state change', () => {
- const NavigationComponent = uut.wrap(componentName, () => MyComponent, store, componentEventsObserver);
- const tree = renderer.create(<TestParent ChildClass={NavigationComponent} />);
- expect(myComponentProps.foo).toEqual(undefined);
- (tree.getInstance() as any).setState({ propsFromState: { foo: 'yo' } });
- expect(myComponentProps.foo).toEqual('yo');
- });
-
- it('pulls props from the store and injects them into the inner component', () => {
- store.setPropsForId('component123', { numberProp: 1, stringProp: 'hello', objectProp: { a: 2 } });
- const NavigationComponent = uut.wrap(componentName, () => MyComponent, store, componentEventsObserver);
- renderer.create(<NavigationComponent componentId={'component123'} />);
- expect(myComponentProps).toEqual({ componentId: 'component123', numberProp: 1, stringProp: 'hello', objectProp: { a: 2 } });
- });
-
- it('updates props from store into inner component', () => {
- const NavigationComponent = uut.wrap(componentName, () => MyComponent, store, componentEventsObserver);
- const tree = renderer.create(<TestParent ChildClass={NavigationComponent} />);
- store.setPropsForId('component1', { myProp: 'hello' });
- expect(myComponentProps.foo).toEqual(undefined);
- expect(myComponentProps.myProp).toEqual(undefined);
- (tree.getInstance() as any).setState({ propsFromState: { foo: 'yo' } });
- expect(myComponentProps.foo).toEqual('yo');
- expect(myComponentProps.myProp).toEqual('hello');
- });
-
- it('protects id from change', () => {
- const NavigationComponent = uut.wrap(componentName, () => MyComponent, store, componentEventsObserver);
- const tree = renderer.create(<TestParent ChildClass={NavigationComponent} />);
- expect(myComponentProps.componentId).toEqual('component1');
- (tree.getInstance() as any).setState({ propsFromState: { id: 'ERROR' } });
- expect(myComponentProps.componentId).toEqual('component1');
- });
-
- xit('assigns key by componentId', () => {
- const NavigationComponent = uut.wrap(componentName, () => MyComponent, store, componentEventsObserver);
- const tree = renderer.create(<NavigationComponent componentId={'component1'} />);
- expect(myComponentProps.componentId).toEqual('component1');
- console.log(Object.keys(tree.root.findByType(NavigationComponent).instance._reactInternalFiber));
- console.log(tree.root.findByType(NavigationComponent).instance._reactInternalFiber.child.child.child.return.return.key);
- expect((tree.getInstance() as any)._reactInternalInstance.child.child.Fibernode.key).toEqual('component1');
- });
-
- it('cleans props from store on unMount', () => {
- store.setPropsForId('component123', { foo: 'bar' });
- const NavigationComponent = uut.wrap(componentName, () => MyComponent, store, componentEventsObserver);
- const tree = renderer.create(<NavigationComponent componentId={'component123'} />);
- expect(store.getPropsForId('component123')).toEqual({ foo: 'bar' });
- tree.unmount();
- expect(store.getPropsForId('component123')).toEqual({});
- });
-
- it('merges static members from wrapped component when generated', () => {
- const NavigationComponent = uut.wrap(componentName, () => MyComponent, store, componentEventsObserver) as any;
- expect(NavigationComponent.options).toEqual({ title: 'MyComponentTitle' });
- });
-
- it('calls unmounted on componentEventsObserver', () => {
- const NavigationComponent = uut.wrap(componentName, () => MyComponent, store, componentEventsObserver);
- const tree = renderer.create(<NavigationComponent componentId={'component123'} />);
- verify(mockedComponentEventsObserver.unmounted('component123')).never();
- tree.unmount();
- verify(mockedComponentEventsObserver.unmounted('component123')).once();
- });
-
- it('renders HOC components correctly', () => {
- const generator = () => (props) => (
- <View>
- <MyComponent {...props}/>
- </View>
- );
- uut = new ComponentWrapper();
- const NavigationComponent = uut.wrap(componentName, generator, store, componentEventsObserver);
- const tree = renderer.create(<NavigationComponent componentId={'component123'} />);
- expect(tree.root.findByType(View)).toBeDefined()
- expect(tree.root.findByType(MyComponent).props).toEqual({componentId: 'component123'});
- });
-
- describe(`register with redux store`, () => {
- class MyReduxComp extends React.Component<any> {
- static get options() {
- return { foo: 123 };
- }
- render() {
- return (
- <Text>{this.props.txt}</Text>
- );
- }
- }
- interface RootState {
- txt: string;
- }
- function mapStateToProps(state: RootState) {
- return {
- txt: state.txt
- };
- }
- const ConnectedComp = require('react-redux').connect(mapStateToProps)(MyReduxComp);
- const ReduxProvider = require('react-redux').Provider;
- const initialState: RootState = { txt: 'it just works' };
- const reduxStore = require('redux').createStore((state = initialState) => state);
-
- it(`wraps the component with a react-redux provider with passed store`, () => {
- const NavigationComponent = uut.wrap(componentName, () => ConnectedComp, store, componentEventsObserver, undefined, ReduxProvider, reduxStore);
- const tree = renderer.create(<NavigationComponent componentId={'theCompId'} />);
- expect(tree.toJSON()!.children).toEqual(['it just works']);
- expect((NavigationComponent as any).options).toEqual({ foo: 123 });
- });
- });
-
- });
-
-
|