-
Notifications
You must be signed in to change notification settings - Fork 0
2021 01 12 Insights of testing
By mocking of React Components, we have multiply options to do so.
So first is, to just simple do a global mock:
jest.mock('path/to/component', function () {
return function (props: any) {
return <div>Hello Replacement. (Debug: {JSON.stringify(props)})</div>;
};
});
But at moment you will add some specials, for example some attachment to external connectors it getting a bit complicated:
export default class SomeComponent extends Component<Properties, State> {
public set somethingFromOutsideOfReactWhatRerenderTheComponent(value: SomeData) {
this.setState({someData: value});
}
componentDidMount(): void {
Container.someExternal.attachToReact(this);
}
render(): JSX.Element {
return <SomeSubComponent data={this.state.someData}/>;
}
}
Now I want to mock SomeSubComponent
and see, that new someData
so I arrive somethings like:
it('test somethings', function() {
let componentInstance: SomeComponent|undefined;
// snipp
(Container.someExternal.attachToReact as jest.Mock).mockImplementation(
function (component: SomeComponent {
componentInstance = component;
component.somethingFromOutsideOfReactWhatRerenderTheComponent = 'first data';
}
);
// snipp
That seem "easy". But now I want to add new data:
componentInstance.somethingFromOutsideOfReactWhatRerenderTheComponent = 'second data';
That the state and all React stuff full work, I need a working React-Class now as replacement.
Also I need it inside the testing code context.
I came to follow result (maybe not correct restored example code;) :
beforeEach(function() {
// snipp
(SomeSubComponent as jest.Mock).mockImplementation(
(props:any) => new class SomeSubComponentMock extends Component<any, any> {
render(): JSX.Element {
return return <div>Hello Replacement. (Debug: {JSON.stringify(this.props)})</div>;
}
}(props)
);
To simplify it, wo create an helper.
JestHelper.ts:
import {Component} from 'react';
export type RenderImplementation = (props?: any, state?: any) => JSX.Element;
export default class JestHelper {
public static createReactMockImplementation<T>(renderImplementation: RenderImplementation): (...args: any) => T {
return function (props: any): T {
class ReactMock<T> extends Component<any, any> {
render(): JSX.Element {
return renderImplementation(this.props, this.state);
}
}
return new ReactMock<T>(props) as unknown as T;
};
}
}
Now is it more easy to rember, how to create an mock implementation:
beforeEach(function() {
// snipp
(SomeSubComponent as jest.Mock).mockImplementation(
JestHelper.createReactMockImplementation<SomeSubComponent>(function (props: any) {
return return <div>Hello Replacement. (Debug: {JSON.stringify(props)})</div>;
})
);
//snipp
Maybe it seems complecated, but now I can to inside the render-Implementation, what ever needed, inclusive interact with testing code, while building the testing output.
Where I need somethings like this?
The case is happend for component, which a manage by any kind of react router, or for the first Component of the application.