const React = require('react');
const { Component } = require('react');
const { Text } = require('react-native');
const renderer = require('react-test-renderer');
const ContainerWrapper = require('./ContainerWrapper');
const Store = require('./Store');
describe('ContainerWrapper', () => {
let store;
const containerName = 'example.MyContainer';
let childRef;
class MyContainer extends Component {
render() {
return {'Hello, World!'};
}
}
class TestParent extends Component {
constructor(props) {
super(props);
this.ChildClass = props.ChildClass;
this.state = { propsFromState: {} };
}
render() {
const Child = this.ChildClass;
return (
childRef = r}
containerId="container1"
{...this.state.propsFromState}
/>
);
}
}
beforeEach(() => {
store = new Store();
});
it('must have containerId as prop', () => {
const NavigationContainer = ContainerWrapper.wrap(containerName, MyContainer, store);
const orig = console.error;
console.error = (a) => a;
expect(() => {
renderer.create();
}).toThrow(new Error('Container example.MyContainer does not have a containerId!'));
console.error = orig;
});
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(tree.getInstance().originalContainerRef).toBeInstanceOf(MyContainer);
});
it('injects props from wrapper into original container', () => {
const NavigationContainer = ContainerWrapper.wrap(containerName, MyContainer, store);
const tree = renderer.create();
expect(tree.getInstance().originalContainerRef.props.myProp).toEqual('yo');
});
it('updates props from wrapper into original container', () => {
const NavigationContainer = ContainerWrapper.wrap(containerName, MyContainer, store);
const tree = renderer.create();
expect(childRef.props.foo).toEqual(undefined);
tree.getInstance().setState({ propsFromState: { foo: 'yo' } });
expect(childRef.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);
const tree = renderer.create();
const originalContainerProps = tree.getInstance().originalContainerRef.props;
expect(originalContainerProps).toEqual({ containerId: 'container123', numberProp: 1, stringProp: 'hello', objectProp: { a: 2 } });
});
it('updates props from store into inner container', () => {
const NavigationContainer = ContainerWrapper.wrap(containerName, MyContainer, store);
const tree = renderer.create();
store.setPropsForContainerId('container1', { myProp: 'hello' });
expect(childRef.originalContainerRef.props.foo).toEqual(undefined);
expect(childRef.originalContainerRef.props.myProp).toEqual(undefined);
tree.getInstance().setState({ propsFromState: { foo: 'yo' } });
expect(childRef.originalContainerRef.props.foo).toEqual('yo');
expect(childRef.originalContainerRef.props.myProp).toEqual('hello');
});
it('protects id from change', () => {
const NavigationContainer = ContainerWrapper.wrap(containerName, MyContainer, store);
const tree = renderer.create();
expect(childRef.originalContainerRef.props.containerId).toEqual('container1');
tree.getInstance().setState({ propsFromState: { id: 'ERROR' } });
expect(childRef.originalContainerRef.props.containerId).toEqual('container1');
});
it('assignes key by id', () => {
const NavigationContainer = ContainerWrapper.wrap(containerName, MyContainer, store);
const tree = renderer.create();
expect(tree.getInstance().originalContainerRef.props.containerId).toEqual('container1');
expect(tree.getInstance().originalContainerRef._reactInternalInstance.key).toEqual('container1');
});
it('saves self ref into store', () => {
const NavigationContainer = ContainerWrapper.wrap(containerName, MyContainer, store);
const tree = renderer.create();
expect(store.getRefForContainerId('container1')).toBeDefined();
expect(store.getRefForContainerId('container1')).toBe(tree.getInstance());
});
it('cleans ref from store on unMount', () => {
const NavigationContainer = ContainerWrapper.wrap(containerName, MyContainer, store);
const tree = renderer.create();
expect(store.getRefForContainerId('container1')).toBeDefined();
tree.unmount();
expect(store.getRefForContainerId('container1')).toBeUndefined();
});
it('holds ref to OriginalContainer', () => {
const NavigationContainer = ContainerWrapper.wrap(containerName, MyContainer, store);
const tree = renderer.create();
expect(tree.getInstance().originalContainerRef).toBeDefined();
expect(tree.getInstance().originalContainerRef).toBeInstanceOf(MyContainer);
});
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 didAppearCallback = jest.fn();
const didDisappearCallback = jest.fn();
const onNavigationButtonPressedCallback = jest.fn();
class MyLifecycleContainer extends MyContainer {
didAppear() {
didAppearCallback();
}
didDisappear() {
didDisappearCallback();
}
onNavigationButtonPressed() {
onNavigationButtonPressedCallback();
}
}
it('didAppear, didDisappear and onNavigationButtonPressed are optional', () => {
const NavigationContainer = ContainerWrapper.wrap(containerName, MyContainer, store);
const tree = renderer.create();
expect(() => tree.getInstance().didAppear()).not.toThrow();
expect(() => tree.getInstance().didDisappear()).not.toThrow();
expect(() => tree.getInstance().onNavigationButtonPressed()).not.toThrow();
});
it('calls didAppear on OriginalContainer', () => {
const NavigationContainer = ContainerWrapper.wrap(containerName, MyLifecycleContainer, store);
const tree = renderer.create();
expect(didAppearCallback).toHaveBeenCalledTimes(0);
tree.getInstance().didAppear();
expect(didAppearCallback).toHaveBeenCalledTimes(1);
});
it('calls didDisappear on OriginalContainer', () => {
const NavigationContainer = ContainerWrapper.wrap(containerName, MyLifecycleContainer, store);
const tree = renderer.create();
expect(didDisappearCallback).toHaveBeenCalledTimes(0);
tree.getInstance().didDisappear();
expect(didDisappearCallback).toHaveBeenCalledTimes(1);
});
it('calls onNavigationButtonPressed on OriginalContainer', () => {
const NavigationContainer = ContainerWrapper.wrap(containerName, MyLifecycleContainer, store);
const tree = renderer.create();
expect(onNavigationButtonPressedCallback).toHaveBeenCalledTimes(0);
tree.getInstance().onNavigationButtonPressed();
expect(onNavigationButtonPressedCallback).toHaveBeenCalledTimes(1);
});
});
});