Reputation: 157
I have a Layout hoc component and I wanna guarantee the state changes. Here my Layout component:
import React, { useState } from 'react'
import styles from './Layout.module.css'
import Toolbar from '../../components/UI/Navigation/Toolbar/Toolbar'
import SideDrawer from '../../components/UI/Navigation/SideDrawer/SideDrawer'
const Layout = (props) => {
const [sideDrawerIsVisible, setSideDrawerIsVisible] = useState(false)
const sideDrawerClosedHandler = () => {
setSideDrawerIsVisible(false)
}
const slideDrawerToggleHandler = () => {
setSideDrawerIsVisible((prevState) => !prevState)
}
return (
<>
<Toolbar
height="2em"
drawerToggleClicked={slideDrawerToggleHandler} />
<SideDrawer
open={sideDrawerIsVisible}
closed={sideDrawerClosedHandler} />
<main className={styles.Content}>
{props.children}
</main>
</>
);
}
export default Layout
The solution that I found is received the instance and use the useState()
.
I need the instance to set the state and verify it after the click action. The test in hand is should update state when drawer toggle clicked
but according to the Enzyme documentation to "stateless" components we receive null to instance()
but this changed in React Hooks. There is a better approach to test this situation?
import React from 'react';
import { configure, shallow } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import Layout from './Layout';
import Toolbar from '../../components/UI/Navigation/Toolbar/Toolbar';
configure({ adapter: new Adapter() });
describe('<Layout />', () => {
let wrapper;
beforeEach(() => {
wrapper = shallow(<Layout>children...</Layout>);
});
it('should update state when drawer toggle clicked', () => {
const toolbar = wrapper.find(Toolbar);
wrapper.instance().setSideDrawerIsVisible(true);
toolbar.props().drawerToggleClicked();
expect(wrapper.sideDrawerIsVisible).toEqual(false);
});
});
Upvotes: 0
Views: 247
Reputation: 23763
Just don't try to init state through workaround ways. Interact with component through its public interface - I mean props.
it('displays drawer after toolbar is clicked', () => {
const toolbar = wrapper.find(Toolbar);
toolbar.props().drawerToggleClicked();
expect(wrapper.find(SideDrawer).props().open).toEqual(true);
});
it('hides drawer after toolbar is clicked for second time', () => {
const toolbar = wrapper.find(Toolbar);
toolbar.props().drawerToggleClicked();
toolbar.props().drawerToggleClicked();
expect(wrapper.find(SideDrawer).props().open).toEqual(false);
});
it('hides drawer initially shown after closing it from inside', () => {
const toolbar = wrapper.find(Toolbar);
toolbar.props().drawerToggleClicked(); // to display drawer
const sideDrawer = wrapper.find(SideDrawer);
sideDrawer.props().closed();
expect(sideDrawer.props().open).toEqual(false);
});
when you operate on instance()
directly or use Enzyme's setState()
you are bounding your tests to component's internals and tests become fragile with no advantages.
Upvotes: 1