/* eslint-disable consistent-this, react/no-multi-comp */
import React, { Component } from 'react';
import { AppRegistry, Text } from 'react-native';
import renderer from 'react-test-renderer';
import ContainerWrapper from './ContainerWrapper';
import Store from './Store';
describe('ContainerWrapper', () => {
let myContainerRef;
let testParentRef;
let store;
const containerName = 'example.MyContainer';
class MyContainer extends Component {
constructor(props) {
super(props);
myContainerRef = this;
}
render() {
return {'Hello, World!'};
}
}
class TestParent extends Component {
constructor(props) {
super(props);
testParentRef = this;
this.ChildClass = props.ChildClass;
this.state = { propsFromState: {} };
}
render() {
const Child = this.ChildClass;
return (
);
}
}
beforeEach(() => {
store = new Store();
});
it('must have id as prop', () => {
const NavigationContainer = ContainerWrapper.wrap(containerName, MyContainer, store);
expect(() => {
renderer.create();
}).toThrow(new Error('Container example.MyContainer does not have an id!'));
});
it('wraps the container', () => {
const NavigationContainer = ContainerWrapper.wrap(containerName, MyContainer, store);
expect(NavigationContainer).not.toBeInstanceOf(MyContainer);
const tree = renderer.create();
expect(tree.toJSON().children).toEqual(['Hello, World!']);
expect(myContainerRef).toBeInstanceOf(MyContainer);
});
it('injects props from wrapper into original container', () => {
const NavigationContainer = ContainerWrapper.wrap(containerName, MyContainer, store);
renderer.create();
expect(myContainerRef.props.myProp).toEqual('yo');
});
it('updates props from wrapper into original container', () => {
const NavigationContainer = ContainerWrapper.wrap(containerName, MyContainer, store);
renderer.create();
expect(myContainerRef.props.foo).toEqual(undefined);
testParentRef.setState({ propsFromState: { foo: 'yo' } });
expect(myContainerRef.props.foo).toEqual('yo');
});
it('pulls props from the store and injects them into the inner container', () => {
store.setPropsForContainerId('container123', { numberProp: 1, stringProp: 'hello', objectProp: { a: 2 } });
const NavigationContainer = ContainerWrapper.wrap(containerName, MyContainer, store);
renderer.create();
expect(myContainerRef.props).toEqual({ id: 'container123', numberProp: 1, stringProp: 'hello', objectProp: { a: 2 } });
});
it('updates props from store into inner container', () => {
const NavigationContainer = ContainerWrapper.wrap(containerName, MyContainer, store);
renderer.create();
store.setPropsForContainerId('container1', { myProp: 'hello' });
expect(myContainerRef.props.foo).toEqual(undefined);
expect(myContainerRef.props.myProp).toEqual(undefined);
testParentRef.setState({ propsFromState: { foo: 'yo' } });
expect(myContainerRef.props.foo).toEqual('yo');
expect(myContainerRef.props.myProp).toEqual('hello');
});
it('protects id from change', () => {
const NavigationContainer = ContainerWrapper.wrap(containerName, MyContainer, store);
renderer.create();
expect(myContainerRef.props.id).toEqual('container1');
testParentRef.setState({ propsFromState: { id: 'ERROR' } });
expect(myContainerRef.props.id).toEqual('container1');
});
it('assignes key by id', () => {
const NavigationContainer = ContainerWrapper.wrap(containerName, MyContainer, store);
renderer.create();
expect(myContainerRef.props.id).toEqual('container1');
expect(myContainerRef._reactInternalInstance._currentElement.key).toEqual('container1');
});
it('saves self ref into store', () => {
const NavigationContainer = ContainerWrapper.wrap(containerName, MyContainer, store);
const tree = renderer.create();
expect(store.getRefForId('container1')).toBeDefined();
expect(store.getRefForId('container1')).toBe(tree.getInstance());
});
it('cleans ref from store on unMount', () => {
const NavigationContainer = ContainerWrapper.wrap(containerName, MyContainer, store);
const tree = renderer.create();
expect(store.getRefForId('container1')).toBeDefined();
tree.unmount();
expect(store.getRefForId('container1')).toBeUndefined();
});
it('holds ref to OriginalContainer', () => {
const NavigationContainer = ContainerWrapper.wrap(containerName, MyContainer, store);
const tree = renderer.create();
expect(tree.getInstance().originalContainerRef).toBe(myContainerRef);
});
it('cleans ref to internal container on unount', () => {
const NavigationContainer = ContainerWrapper.wrap(containerName, MyContainer, store);
const tree = renderer.create();
const instance = tree.getInstance();
expect(instance.originalContainerRef).toBeInstanceOf(Component);
tree.unmount();
expect(instance.originalContainerRef).toBeFalsy();
});
describe('container lifecycle', () => {
const onStartCallback = jest.fn();
const onStopCallback = jest.fn();
class MyLifecycleContainer extends MyContainer {
onStart() {
onStartCallback();
}
onStop() {
onStopCallback();
}
}
it('onStart and onStop are optional', () => {
const NavigationContainer = ContainerWrapper.wrap(containerName, MyContainer, store);
const tree = renderer.create();
expect(() => tree.getInstance().onStart()).not.toThrow();
expect(() => tree.getInstance().onStop()).not.toThrow();
});
it('calls onStart on OriginalContainer', () => {
const NavigationContainer = ContainerWrapper.wrap(containerName, MyLifecycleContainer, store);
const tree = renderer.create();
expect(onStartCallback).toHaveBeenCalledTimes(0);
tree.getInstance().onStart();
expect(onStartCallback).toHaveBeenCalledTimes(1);
});
it('calls onSop on OriginalContainer', () => {
const NavigationContainer = ContainerWrapper.wrap(containerName, MyLifecycleContainer, store);
const tree = renderer.create();
expect(onStopCallback).toHaveBeenCalledTimes(0);
tree.getInstance().onStop();
expect(onStopCallback).toHaveBeenCalledTimes(1);
});
});
});