How To Call Custom Methods Of React Component While Doing Unit Testing. I Am Using Typescript
I am using react with typescript. Can anyone tell me how to call the custom methods which is written in component inside unit testing.
I tried shallow
and mount
but I am not able to call custom methods.
import React from 'react';
import {
Theme,
withStyles,
createStyles,
} from '@material-ui/core';
export interface IFileUploadProps{}
export interface IFileUploadState {}
const styles = (theme: Theme) => {
return createStyles({
root: {
paddingTop: theme.spacing(2),
paddingBottom: theme.spacing(2),
width: '100%',
backgroundColor: 'inherit',
},
input: {
display: 'none',
},
padding24: {
paddingLeft: theme.spacing(3),
paddingRight: theme.spacing(3),
},
});
};
class FileUpload extends React.Component<IFileUploadProps, IFileUploadState> {
validateImage = () => {
console.log('validate image');
}
render() {
return <div>file upload</div>;
}
}
export default withStyles(styles)(FileUpload);
I need to do something like this.
import React from 'react';
import { shallow, configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16'
import FileUpload from './FileUpload';
configure({ adapter: new Adapter() });
describe('FileUpload', () => {
test('should call validateImage method correctly', () => {
const wrapper = shallow(<FileUpload ></FileUpload>);
wrapper.instance()['validateImage']();
});
});
Here I am getting error.
TypeError: Cannot read property 'validateImage' of null
This error occurs when i export file using "export default withStyles(styles)(FileUpload);" When i use export default FileUpload it is working fine.
Answer
It should work. For example:
FileUpload.tsx
:
import React from 'react';
interface IFileUploadProps {}
interface IFileUploadState {}
export class FileUpload extends React.Component<IFileUploadProps, IFileUploadState> {
validateImage() {
console.log('validate image');
}
render() {
return <div>file upload</div>;
}
}
FileUpload.spec.tsx
:
import React from 'react';
import { shallow } from 'enzyme';
import { FileUpload } from './FileUpload';
describe('FileUpload', () => {
test('should call validateImage method correctly', () => {
const logSpy = jest.spyOn(console, 'log');
const wrapper = shallow(<FileUpload></FileUpload>);
expect(wrapper.text()).toBe('file upload');
// @ts-ignore
// tslint:disable-next-line: no-string-literal
wrapper.instance()['validateImage']();
expect(logSpy).toBeCalledWith('validate image');
});
});
Unit test result with 100% coverage
PASS src/stackoverflow/58642342/FileUpload.spec.tsx
FileUpload
✓ should call validateImage method correctly (14ms)
console.log node_modules/jest-mock/build/index.js:860
validate image
----------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
FileUpload.tsx | 100 | 100 | 100 | 100 | |
----------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 4.487s, estimated 9s
Update 1
You should disable strict: true
in your tsconfig.json
file. Or, use // @ts-ignore
to skip the static type check of tsc.
Update 2
Since you use HOC - the withStyles
high order function, so you need use .dive([options]) => ShallowWrapper method of enzyme
to get the shallow wrapper of FileUpload
component.
FileUpload.tsx
:
import React from 'react';
import { Theme, withStyles, createStyles } from '@material-ui/core';
interface IFileUploadProps {}
interface IFileUploadState {}
const styles = (theme: Theme) => {
return createStyles({
root: {
paddingTop: theme.spacing(2),
paddingBottom: theme.spacing(2),
width: '100%',
backgroundColor: 'inherit'
},
input: {
display: 'none'
},
padding24: {
paddingLeft: theme.spacing(3),
paddingRight: theme.spacing(3)
}
});
};
class FileUpload extends React.Component<IFileUploadProps, IFileUploadState> {
validateImage() {
console.log('validate image');
}
render() {
return <div>file upload</div>;
}
}
export default withStyles(styles)(FileUpload);
FileUpload.spec.tsx
:
import React from 'react';
import { shallow } from 'enzyme';
import FileUpload from './FileUpload';
describe('FileUpload', () => {
test('should call validateImage method correctly', () => {
const logSpy = jest.spyOn(console, 'log');
const wrapper = shallow(<FileUpload></FileUpload>);
expect(wrapper.dive().text()).toBe('file upload');
// @ts-ignore
// tslint:disable-next-line: no-string-literal
wrapper
.dive()
.instance()
['validateImage']();
expect(logSpy).toBeCalledWith('validate image');
});
});
Unit test result with 100% coverage:
PASS src/stackoverflow/58642342/FileUpload.spec.tsx
FileUpload
✓ should call validateImage method correctly (31ms)
console.log node_modules/jest-mock/build/index.js:860
validate image
----------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
FileUpload.tsx | 100 | 100 | 100 | 100 | |
----------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 5.517s, estimated 12s
Source code: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/58642342
Related Questions
- → Import statement and Babel
- → should I choose reactjs+f7 or f7+vue.js?
- → Uncaught TypeError: Cannot read property '__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED' of undefined
- → .tsx webpack compile fails: Unexpected token <
- → React-router: Passing props to children
- → ListView.DataSource looping data for React Native
- → React Native with visual studio 2015 IDE
- → Can't test submit handler in React component
- → React + Flux - How to avoid global variable
- → Webpack, React & Babel, not rendering DOM
- → How do I determine if a new ReactJS session and/or Browser session has started?
- → Alt @decorators in React-Native
- → How to dynamically add class to parent div of focused input field?