There are three things I want to figure out. For now I am using shallow render. I use Enzyme and Jest.
I am wondering how I can test the branches in my React component. I
would like to test both sides of the if-else statement (? :). And I
do not want to pull it out in an own function.
How can I check if this.props.myFuncFromProps(value) is been called
when the input changes?
What is the best practice to test mapStateToProps and
mapDispatchToProps?
Here is an example of how my component would look like:
import React from 'react';
import MyChildComponent from 'wherever'; // This component is an input field in this example
export class MyComponent extends React.Component {
render() {
const myFunc(value) {
this.props.myFuncFromProps(value);
}
return (
<div>
{ this.props.isTrue ?
<MyChildComponent
value={this.props.value}
onChange={(value) => myFunc(value)}
/>
: null
}
</div>
);
}
}
To test the different states just render your component with the different attributes and make a snapshot (note, that you have to check the first time the snapshot was created). To test event callback, you have to pass a spy function (jest.fn()) into to component and use simulate to call the event, then test that the spy was called.
describe('MyComponent', () => {
describe('with isTrue is true', () => {
let myComponent
let myFuncFromProps
beforeEach(() => {
myFuncFromProps = jest.fn()
myComponent = shallow(
<MyComponent isTrue myFuncFromProps={myFuncFromProps} />
)
})
it('renders correct', () => {
expect(myComponent).matchSnapshot()
})
it('onchange will call myFuncFromProps', () => {
myComponent
.find('MyChildComponent')
.simulate('onChange', 'someValue')
expect(myFuncFromProps).toHaveBeenCalledWith('someValue')
})
})
it('with isTrue is false it renders correct', () => {
const myComponent = shallow(<MyComponent />)
expect(myComponent).matchSnapshot()
})
})
Related
I have a component which have this structure
return <Element>
{(a, b): React.ReactElement => (
...some elements here
)}
</Element>;
When I'm testing it I'm getting this with debug
<Element>
[function]
</Element>
My question is what is usually the way to get inside this function to check the elements which it returns?
My test
import React from 'react';
import {createShallow} from '#material-ui/core/test-utils';
import Component from './Component';
let shallow;
function setup() {
const props = {};
const wrapper = shallow(<Component {...props} />);
return {
props,
wrapper,
};
}
beforeAll(() => {
shallow = createShallow({ dive: true });
});
describe('Components', () => {
describe('Element', () => {
it('Should render self', () => {
const {wrapper, props} = setup();
console.log(wrapper.debug())
expect(wrapper.exists()).toBeTruthy();
});
});
});
There are two solutions:
Use wrapper.dive() or wrapper.shallow() that would cause your ShallowWrapper to render child of your top-level component. However, I do not recommend using shallow at all as there are many issues with it and you've just experienced one - it does not render everything.
Use mount instead of shallow and you would have your children function rendered by default.
I have a functional react component and I want to change a property value inside the component in an enzyme unit test (in my case the ready attribute). The unit test should use shallow to avoid rendering any children components.
Here is the simplified component code:
import {useTranslation} from 'react-i18next';
// ...
const MyComponent: React.FC<IProps> = (props: IProps) => {
const {t, ready} = useTranslation('my-translation-namespace');
// ...
return (
<React.Fragment>
{ready &&
<div className="my-component">some more content...</div>
}
</React.Fragment>)
};
export default MyComponent;
And this is the corresponding test:
describe('MyComponent', () => {
let component: ShallowWrapper;
it('should be displayed', () => {
component = shallow(<MyComponent/>);
// HERE I WOULD LIKE TO SET: component.ready = true
expect(component.find('.my-component').length).toBe(1);
});
});
Any idea how to change the ready attribute to true in my test?
This can be accomplished by mocking the react-i18next module with jest.
const mockT = jest.fn((a) => a)
const mockReady = true
jest.mock('react-i18next', () =>
jest.fn().mockImplementation(() => ({
useTranslation: () => ({ t: mockT, ready: mockReady })
}))
);
Take a look at the documentation or this article if you are using ES modules or this answer for other options.
edit: use module factory for second param of jest.mock instead if passing a plain object.
I am testing a component following the Container/Presentational pattern. What I need in order to have my coverage at 100% is to test the handleChange() function in which I have a setState(). The thing is that I'm just testing the Container component and the function is called in Presentational one.
Container Component:
import React, { Component } from 'react'
import DataStructureFormView from './DataStructureFormView'
export default class DataStructureForm extends Component {
state = {}
handleChange = name => event => {
this.setState({
[name]: event.target.value
})
}
render() {
return (
<DataStructureFormView
handleChange={this.handleChange}
form={this.state}
/>
)
}
}
As you can see, the DataStructureForm is the Container component and DataStructureFormView is the Presentational one.
Test file:
import React from 'react'
import { shallow, mount } from 'enzyme'
describe('DataStructureForm', () => {
it('should call the handleChange() function and change the state', () => {
const component = mount(<DataStructureForm />)
const handleChange = jest.spyOn(component.instance(), 'handleChange')
component.instance().handleChange()
expect(handleChange).toBeCalled()
}
}
This is one of the multiple approaches that I have done, but it is not testing the setState() inside the handleChange() method.
What else I can do?
The most straightforward solution is to check if state changed accordingly:
const component = shallow(<DataStructureForm />)
const value = 'someValue';
component.instance().handleChange('someName')({target: { value }});
expect(component.state('someName')).toEqual(value)
I'm trying a very simple shallow test for a component:
it('renders without crashing', () => {
shallow(<SampleComponent />);
});
In my sample component, I did a setState :
this.setState({myCurrentState: "InSample"});
Now somewhere in my return, I used that to output an element, say:
return ( <h1> this.state.myCurrentState </h1>)
When I try the above test, I get
TypeError: Cannot read property of undefined.
I know that I can pass in props to shallow, but I can't seem to figure how to do it with states. Is there a better way of doing it? Sorry I'm new to React and unit testing. thanks
Here you go
import React from 'react';
import { render } from 'enzyme';
import SampleComponent from './SampleComponent';
describe('< SampleComponent />', () => {
it('should render', () => {
const wrapper = shallow(<SampleComponent name="Example" />);
expect(wrapper).toHaveLength(1);
});
describe('check props', () => {
const wrapper = shallow(<SampleComponent name="Example" />);
console.log(warpper.instance().props); // you should see name='Example'
});
});
Please check out this link http://airbnb.io/enzyme/docs/api/
You can't call the state like this return ( <h1> this.state.myCurrentState </h1>) you have to put it into { } like
return ( <h1> {this.state.myCurrentState} </h1>)
If you still having a troubles watch this video
Use Something like this:
class SomeComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
myCurrentState: null
};
// somewhere in your code in one of the method
this.setState({myCurrentState: "InSample"});
render() {
return (
<h1>{this.state.myCurrentState}</h1>
);
}
}
I need help for understand how to improve my test ?
I covered branches tests to 100% but can't do statements tests, functions tests and lines tests so how to covered these ?
Here is my code-coverage (provided by jest):
And here is my test:
/**
* Testing our ItemList component
*/
import { shallow } from 'enzyme';
import React from 'react';
import { BootstrapProvider } from 'bootstrap-styled';
import ItemList from '../index';
const renderComponent = (props = {}) => shallow(
<BootstrapProvider>
<ItemList {...props} />
</BootstrapProvider>
);
describe('<ItemList />', () => {
it('should render an <ItemList /> tag', () => {
const renderedComponent = renderComponent();
expect(renderedComponent.find('ItemList').length).toBe(1);
});
});
Any advice are welcome.
Firstly, you can see that the this.props is highlighted and that you have set within the component the props className with a className by default.
You could test the presence of the default className and also trying to set one:
it('should render an <ItemList /> with a className', () => {
const renderedComponent = renderComponent({
className:'className-test'
});
expect(renderedComponent.find('ItemList').hasClass('className-test')).toEqual(true);
});
it('should render an <ItemList /> with a className 'item' by default ', () => {
const renderedComponent = renderComponent();
expect(renderedComponent.find('ItemList').hasClass('item')).toEqual(true);
});
As for the rendering, I suggest you follow the advice given in the comment.