How to test hoc stateful component with React Hooks? - reactjs

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);
});
});

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.

Related

Jest testing of hook onClick calls

This error appears when running this onClick call test with Jest, does anyone know why?
I'm developing an app with React, and I'm new to its testing framework. I'm trying to develop a testing method to check if an onClick button is clicked. I've read that I need a "spy" function to get the information about whether or not it's been called.
The preference is to keep an enzyme and jest test stack.
expect(received).toBe(expected) // Object.is equality
Expected: 1
Received: 0
46 | test("onClick calls props.onClick", () => {
47 | nodes.simulate("click");
> 48 | expect(onClickMock.mock.calls.length).toBe(1);
Since I'm mocking onClick in a way that was to return the value 1
Test
import React from "react";
import Enzyme, { shallow } from "enzyme";
import Adapter from "#wojtekmaj/enzyme-adapter-react-17";
import { expect } from "#jest/globals";
import { findByTestId } from "../../utils/test";
import Accordion from "./accordion.jsx";
Enzyme.configure({ adapter: new Adapter() });
const defaultProps = {
opened: {},
Accordion: {},
};
const setup = (props = {}) =>
shallow(<Accordion {...props} {...defaultProps} />).dive();
describe("Function calls", () => {
let wrapper, nodes, props;
describe("Button", () => {
let onClickMock;
beforeEach(() => {
onClickMock = jest.fn();
props = {onClick: onClickMock};
wrapper = setup(props);
nodes = findByTestId(wrapper, "arrow");
});
test("onClick calls props.onClick", () => {
nodes.simulate("click");
expect(onClickMock.mock.calls.length).toBe(1);
});
});
});
Component
import { useState } from 'react';
import styled from 'styled-components';
import { IoIosArrowForward, IoIosArrowDown } from 'react-icons/io';
import styles from '../../variables';
const Accordion = (props) => {
const [opened, setOpened] = useState(false);
const renderArrow = () => {
if (!opened) return <IoIosArrowForward className="is-size-4" color={styles.primaryBlue} />
return <IoIosArrowDown className="is-size-4" color={styles.primaryBlue} />
}
const renderPanel = () => {
if (opened) return <Panel>{props.children}</Panel>
}
const togglePanel = () => {
setOpened(!opened)
}
return (
<AccordionTile data-testid="accordionTile" className={props.className + " px-6 py-5 is-clickable"}>
<p data-testid="arrow" onClick={togglePanel} className="is-flex is-flex-direction-row is-align-items-flex-start is-justify-content-flex-start is-size-5">
{renderArrow()} {props.title}
</p>
{renderPanel()}
</AccordionTile>
);
}
export default Accordion
Could someone guide me to finish testing this onClick
So you click and check that content appears:
wrapper = setup({
children: <span id="test" />
});
// accordion is collapsed yet
expect(wrapper.find('span#test')).toHaveLength(0);
nodes.simulate('click');
// accordion is expanded; children nodes are rendered
expect(wrapper.find('span#test')).toHaveLength(1);
Also you better switch from shallow() to mount() before you run into issues with useEffect is not called. You will still be able to avoid rendering some nested components by explicitly mocking them:
jest.mock('react-icons/io', () => ({
IoIosArrowForward: (props) => <span {...props} />,
IoIosArrowDown: props => <span {...props} />
}));
And also in way you do it now:
<Accordion {...props} {...defaultProps} />
your defaultProps overwrite props with the same name. To have it working in reasonable way(when defaultProps can be overwritten by props if you want to) it should go in reverse order:
<Accordion {...defaultProps} {...props} />

How do you use Enzyme to check for changes to a React Hooks component after onClick?

I am trying to write a simple integration test in my 100% React Hooks (React v16.12) project with Enzyme (v3.10), Jest (v24.0) and TypeScript where if I click a button component in my App container, another component displaying a counter will go up by one. The current value of the counter is stored in the state of the App container (see snippets below).
Basically, I mount the App component to render its children, then try to simulate a click on the button with Enzyme and check the props of the counter display component to see if its value has gone up. But nothing happens. Not only does the onClick handler not get called but I don't seem to be able to retrieve the value prop I pass to the PaperResource component. So basically I can't test the counter display changes when I click on the button in my Enzyme integration test! The test asserts that the value prop goes from 0 to 1, but this assertion fails without an error per seenter code here. Is this because Enzyme support for Hooks is still not there yet or am I doing something daft here? When I run the app on my browser, everything works as expected.
Here's my integration test
import React from 'react';
import App from './App';
import { mount, ReactWrapper } from 'enzyme';
import { act } from 'react-dom/test-utils';
import MakePaperButton from './components/MakePaperButton';
import PaperResource from './components/PaperResource';
describe('App', () => {
let wrapper: ReactWrapper;
beforeEach(() => {
act(() => {
wrapper = mount(<App />);
});
});
describe('when make paper button is clicked', () => {
beforeEach(() => {
act(() => {
wrapper.find('.make-paper__button').simulate('click');
});
});
it('should increase paper resource', () => {
expect(wrapper.find('.resources__paper').prop('value')).toEqual(1);
});
});
});
And here is my React code
import React, { useState } from 'react';
import './App.scss';
import MakePaperButton from './components/MakePaperButton';
import PaperResource from './components/PaperResource';
const App: React.FC = () => {
const [ resources, setResources ] = useState({
paper: 0,
});
const handleMakePaperButtonClick = () => {
setResources({
...resources,
paper: resources.paper + 1,
});
};
return (
<div className="App">
<MakePaperButton onClick={handleMakePaperButtonClick} />
<div className="resources">
<PaperResource value={resources.paper} />
</div>
</div>
);
}
export default App;
My components are very simple
// PaperResource.tsx
import React from 'react';
export default (props: { value: number }) => (
<div className="resources__paper">
<span>Paper: {props.value}</span>
</div>
);
// MakePaperButton.tsx
import React from 'react';
export default (props: { onClick: () => void }) => (
<div className="make-paper__button">
<button onClick={props.onClick}>Make Paper</button>
</div>
);
The only solution I've found so far is wrapping the expect statement in a setTimeout().
it('should increase paper resource', () => {
setTimeout(() => {
expect(wrapper.find('.resources__paper').prop('value')).toEqual(1);
}, 0);
});

How to test function that passed from mapDispatchToProps (React/Redux/Enzyme/Jest)

I want to test that function passed from mapDispatchToProps was invoked when button clicking is simulated.
How to test that function which passed from mapDispatchToProps is invoked?
I tried to pass a mocked function by props, but it doesn't work. Any help will be appreciated.
Here below my fake class code and test example.
My component
// All required imports
class App extends React.Component<Props> {
render() {
const { onClick } = this.props;
return (
<>
<h1>Form</h1>
<input />
<button onClick={() => onClick()} />
</>
);
}
}
const mapStateToProps = (state) => {
return {
state
};
};
const mapDispatchToProps = (dispatch) => {
return {
onClick: () => dispatch(actions.onClick())
};
};
export default connect(mapStateToProps, mapDispatchToProps)(App);
My test file
import { configure, mount } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16/build/index';
import jsdom from 'jsdom';
import React from 'react';
import { Provider } from 'react-redux';
import configureMockStore from 'redux-mock-store';
import ConnectedApp, { App } from './App';
function setUpDomEnvironment() {
const { JSDOM } = jsdom;
const dom = new JSDOM('<!doctype html><html><body></body></html>', { url: 'http://localhost/' });
const { window } = dom;
global.window = window;
global.document = window.document;
global.navigator = {
userAgent: 'node.js',
};
copyProps(window, global);
}
function copyProps(src, target) {
const props = Object.getOwnPropertyNames(src)
.filter(prop => typeof target[prop] === 'undefined')
.map(prop => Object.getOwnPropertyDescriptor(src, prop));
Object.defineProperties(target, props);
}
setUpDomEnvironment();
configure({ adapter: new Adapter() });
const mockStore = configureMockStore();
describe('App', () => {
describe('When App connected to store', () => {
describe('When button clicked', () => {
it('should not crush after click on login button', () => {
const onClick = jest.fn()
const store = mockStore(initialStates[1]);
const wrapper = mount(
<Provider store={store}>
<ConnectedApp />
</Provider>);
wrapper.find('button').simulate('click');
??? how to test that function passed from mapDispatchToProps was fired?
});
});
});
});
I recommend following the approach described in the docs and export the connected component as the default export for use in the application, and export the component itself as a named export for testing.
For the code above export the App class and test the click like this:
import * as React from 'react';
import { shallow } from 'enzyme';
import { App } from './code';
describe('App', () => {
it('should call props.onClick() when button is clicked', () => {
const onClick = jest.fn();
const wrapper = shallow(<App onClick={onClick} />);
wrapper.find('button').simulate('click');
expect(onClick).toHaveBeenCalledTimes(1);
});
});
shallow provides everything that is needed for testing the component itself. (shallow even calls React lifecycle methods as of Enzyme v3)
As you have found, to do a full rendering of the component requires a mock redux store and wrapping the component in a Provider. Besides adding a lot of complexity, this approach also ends up testing the mock store and all child components during the component unit tests.
I have found it much more effective to directly test the component, and to export and directly test mapStateToProps() and mapDispatchToProps() which is very easy since they should be pure functions.
The mapDispatchToProps() in the code above can be tested like this:
describe('mapDispatchToProps', () => {
it('should dispatch actions.onClick() when onClick() is called', () => {
const dispatch = jest.fn();
const props = mapDispatchToProps(dispatch);
props.onClick();
expect(dispatch).toHaveBeenCalledWith(actions.onClick());
});
});
This approach makes unit testing the component very simple since you can pass the component props directly, and makes it very simple to test that the component will be handed the correct props by the pure functions (or objects) passed to connect().
This ensures that the unit tests are simple and targeted. Testing that connect() and redux are working properly with the component and all of its child components in a full DOM rendering can be done in the e2e tests.

Material UI + Enzyme testing component

I have component in React which I'm trying to test with Jest, unfortunately test do not pass.
The component code:
import React, {Component} from 'react';
import ProductItem from '../ProductItem/ProductItem';
import AppBar from "#material-ui/core/es/AppBar/AppBar";
import Tabs from "#material-ui/core/es/Tabs/Tabs";
import Tab from "#material-ui/core/es/Tab/Tab";
import {connect} from 'react-redux';
class ProductsTabsWidget extends Component {
state = {
value: 0
}
renderTabs = () => {
return this.props.tabs.map((item, index) => {
return item.products.length > 0 ? (<Tab key={index} label={item.title}/>) : false;
})
}
handleChange = (event, value) => {
this.setState({value});
};
renderConentActiveTab = () => {
if (this.props.tabs[this.state.value]) {
return this.props.tabs[this.state.value].products.map((productIndex) => {
return (<ProductItem key={productIndex} {...this.props.products[productIndex]} />);
});
}
}
render() {
let tabs = null;
let content = null;
if (this.props.tabs) {
tabs = this.renderTabs();
content = this.renderConentActiveTab();
}
return (
<div>
<AppBar position="static" color="default">
<Tabs
value={this.state.value}
onChange={this.handleChange}
indicatorColor="primary"
textColor="primary"
centered
scrollButtons="auto"
>
{tabs}
</Tabs>
</AppBar>
<div className="productWidget">
<div className="wrapper">
{content}
</div>
</div>
</div>
)
}
}
const mapStateToProps = state => {
return {
products: state.product.products,
}
}
export default connect(mapStateToProps)(ProductsTabsWidget);
I have tried to write proper test for this component, the code is below:
import React from 'react';
import {configure, shallow} from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import ProductsTabsWidget from "./ProductsTabsWidget";
configure({adapter: new Adapter()});
describe('ProductsTabsWidget - component', () => {
let wrapper;
beforeEach(() => {
wrapper = shallow(<ProductsTabsWidget/>);
});
it('renders with minimum props without exploding', () => {
wrapper.setProps({
tabs: [],
products:[]
});
expect(wrapper).toHaveLength(1);
});
})
But when I'm running test I am getting error:
Test suite failed to run
F:\PRACA\reactiveShop\node_modules\#material-ui\core\es\AppBar\AppBar.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import _extends from "#babel/runtime/helpers/builtin/extends";
^^^^^^
SyntaxError: Unexpected token import
at new Script (vm.js:51:7)
at Object.<anonymous> (src/components/product/ProductsTabsWidget/ProductsTabsWidget.js:3:15)
I have tried testing with shallow, mount, render but it did not help. What am I missing?
My application is created on create-react-app.
It's something different when you're using #material-ui.
You've to use #material-ui's Built-in API(s). Such as createMount, createShallow, createRender in order to use enzyme's shallow, mount & render.
These APIs are built on top of enzyme, so you can't use enzyme directly for testing #material-ui.
Example of Shallow Rendering with #material-ui
import { createShallow } from '#material-ui/core/test-utils';
describe('<MyComponent />', () => {
let shallow;
before(() => {
shallow = createShallow();
});
it('should work', () => {
const wrapper = shallow(<MyComponent />);
});
});
Reference: Official Docs of #material-ui
Following is a humble attempt to provide a more complete answer from create-react-app and #material-ui perspective.
1. Create setupTests.js directly in src folder and paste the following code.
import { configure } from "enzyme";
import Adapter from "enzyme-adapter-react-16";
configure({ adapter: new Adapter() });
2. The following is react stateless component which uses material-ui components.
import React from "react";
import TextField from "#material-ui/core/TextField";
const SearchField = props => (
<TextField InputProps={{ disableUnderline: true }} fullWidth
placeholder={props.placeholder}
onChange={props.onChange}
/>
);
export default SearchField;
Note that in the above component, the component expects parent component to pass the props for placeholder and onChange() event handler
3. Coming to the test case for for the above component we can write either in a way material-ui suggests or in a pure enzyme style. Both will work.
Pure Enzyme Style
import React from "react";
import { mount } from "enzyme";
import TextField from "#material-ui/core/TextField";
import SearchField from "../SearchField";
describe("SearchField Enzyme mount() ", () => {
const fieldProps = {
placeholder: "A placeholder",
onChange: jest.fn()
};
const Composition = props => {
return <SearchField {...fieldProps} />;
};
it("renders a <TextField/> component with expected props", () => {
const wrapper = mount(<Composition />);
expect(wrapper.childAt(0).props().placeholder).toEqual("A placeholder");
expect(wrapper.childAt(0).props().onChange).toBeDefined();
});
it("should trigger onChange on <SearchField/> on key press", () => {
const wrapper = mount(<Composition />);
wrapper.find("input").simulate("change");
expect(fieldProps.onChange).toHaveBeenCalled();
});
it("should render <TextField />", () => {
const wrapper = mount(<Composition />);
expect(wrapper.find(TextField)).toHaveLength(1);
expect(wrapper.find(TextField).props().InputProps.disableUnderline).toBe(
true
);
});
});
Material UI style
import React from "react";
import { createMount } from "#material-ui/core/test-utils";
import TextField from "#material-ui/core/TextField";
import SearchField from "../SearchField";
describe("SearchField", () => {
let mount;
const fieldProps = {
placeholder: "A placeholder",
onChange: jest.fn()
};
beforeEach(() => {
mount = createMount();
});
afterEach(() => {
mount.cleanUp();
});
it("renders a <TextField/> component with expected props", () => {
const wrapper = mount(<SearchField {...fieldProps} />);
expect(wrapper.props().placeholder).toEqual("A placeholder");
expect(wrapper.props().onChange).toBeDefined();
});
it("should trigger onChange on <SearchField/> on key press", () => {
const wrapper = mount(<SearchField {...fieldProps} />);
wrapper.find("input").simulate("change");
expect(fieldProps.onChange).toHaveBeenCalled();
});
});
5. The error you are getting is due to the fact that babel is not getting a chance to process your file. The create-react-app expects you to run tests like yarn run test and not like jest your/test/file.js. If you use latter babel won't be employed.
If you want to use jest to run the file you will have to write a jest.config.js file or configure jest in package.json file to use babel-jest + other babel dependencies to transpile your code before jest tries to execute tests.
I was in the same boat yesterday as I tried to use #material-ui for the first time and came here to get a more complete answer.
Something like this worked for me:
import {createMount} from '#material-ui/core/test-utils';
const WrappedComponent = () =>
<MUIThemeStuffEtc>
<MyComponent />
</MUIThemeStuffEtc>
const render = createMount();
const wrapper = render(<WrappedComponent />);
const state = wrapper.find(MyComponent).instance().wrappedInstance.state

How to test a TextField Material-UI element with React Jest?

I built up a component with React and Material-UI. I'm using React and Redux.
my index.jsx looks like this:
import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import configureStore from '../store/configureStore';
import Routes from '../routes/routes';
import '../styles/main.less';
const store = configureStore();
render(
<Provider store={store}>
<MuiThemeProvider>
<Routes />
</MuiThemeProvider>
</Provider>,
document.getElementById('app'),
);
My component InputSearch looks like this:
import React, { PropTypes, Component } from 'react';
import TextField from 'material-ui/TextField';
class InputSearch extends Component {
...
render() {
return (
...
<TextField
defaultValue={this.props.keyword}
ref={(input) => { this.input = input; }}
autoFocus
hintText='Type a keyword'
errorText={this.state.errorText}
floatingLabelText='Search for keyword'
style={styles.textField}
/>
);
}
}
InputSearch.propTypes = {
keyword: PropTypes.string.isRequired,
resetSearch: PropTypes.func.isRequired,
searchBooks: PropTypes.func.isRequired,
toggleResultsOpacity: PropTypes.func.isRequired,
firstSearch: PropTypes.bool.isRequired,
};
export default InputSearch;
I'm using Airbnb Enzyme and Jest to build unit tests.
My test to the InputSearch component looks like this:
import React from 'react';
import { shallow, mount } from 'enzyme';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import TextField from 'material-ui/TextField';
import InputSearch from '../components/InputSearch/InputSearch';
const resetSearchMock = jest.fn();
const searchBooksMock = jest.fn();
const toggleResultsOpacityMock = jest.fn();
const setup = () => {
const props = {
keyword: '',
resetSearch: resetSearchMock,
searchBooks: searchBooksMock,
toggleResultsOpacity: toggleResultsOpacityMock,
firstSearch: true,
};
const wrapper = shallow(<MuiThemeProvider><InputSearch {...props} /></MuiThemeProvider>);
return {
props,
wrapper,
};
};
describe('Initial test', () => {
test('Shows error message when input search is empty.', () => {
const { wrapper, props } = setup();
expect(wrapper.find(TextField).getValue()).toEqual('');
});
}
However, I'm getting the following error:
TypeError: wrapper.find(...).getValue is not a function
Can anyone help me reach the right way to check the value of the Material UI TextField, please?
I have been writing test for few days using mocha, enzyme and chai. The problem that comes with testing material-ui is these are inturn react component so they cannot be tested as you test regular html elements.
You can find out what property change by printing the whole component, like
console.log(wrapper.find('TextField').debug());
This will print the whole element for you, you can notice that the TestField has value prop which is what you are suppose to check because this prop is what decided the value in the TextField
So the code will go like this:
describe('Initial test', () => {
test('Shows error message when input search is empty.', () => {
const { wrapper, props } = setup();
expect(wrapper.find(TextField).props().value).to.equal('');
});
}
This is how I have been testing the TextField component.
Hope you find it helpful.
Please, if someone has a better solution answer my question. After some attempts, I figured out how to test some material UI components. Basically, we need to find the native html elements (input, button, etc) inside the material UI components via enzyme find. I also realized that "shallow", only do a one level deep search, as #Andreas Köberle said in comments below. To force a deep search in the DOM tree we need to use enzyme "mount". http://airbnb.io/enzyme/docs/api/ReactWrapper/mount.html
Here is my new test code.
import React from 'react';
import { shallow, mount } from 'enzyme';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import { search } from '../sagas/search';
import TextField from 'material-ui/TextField';
import RaisedButton from 'material-ui/RaisedButton';
import Toggle from 'material-ui/Toggle';
import InputSearch from '../components/InputSearch/InputSearch';
const resetSearchMock = jest.fn();
const searchBooksMock = jest.fn();
const toggleResultsOpacityMock = jest.fn();
const muiTheme = getMuiTheme();
const props = {
keyword: '',
resetSearch: resetSearchMock,
searchBooks: searchBooksMock,
toggleResultsOpacity: toggleResultsOpacityMock,
firstSearch: true,
};
const setup = () => {
const wrapper = mount(
<InputSearch {...props} />,
{
context: {muiTheme},
childContextTypes: {muiTheme: React.PropTypes.object}
}
);
return {
props,
wrapper,
};
};
const { wrapper } = setup();
const textFieldMUI = wrapper.find(TextField);
const toggleAuthor = wrapper.find(Toggle).find('input#author');
const toggleTitle = wrapper.find(Toggle).find('input#title');
const button = wrapper.find(RaisedButton).find('button');
describe ('Initial test, validate fields', () => {
test('TextField component should exists.', () => {
expect(textFieldMUI).toBeDefined();
});
test('Shows an error message when input search is empty and the search button is clicked.', () => {
const { props } = setup();
props.keyword = '';
const wrapper = mount(
<InputSearch {...props} />,
{
context: {muiTheme},
childContextTypes: {muiTheme: React.PropTypes.object}
}
);
button.simulate('click');
expect(textFieldMUI.props().errorText).toEqual('This field is required');
});
test('Shows an error message when both "author" and "title" toggles are off and the search button is clicked.', () => {
toggleTitle.simulate('click');
button.simulate('click');
expect(textFieldMUI.props().errorText).toEqual('Select at least one filter (Title or Author)');
});
});
Enzyme shallow renders only one level deep, so in your case only MuiThemeProvider and InputSearch are rendered. You can use Jest snapshot feature to see what was rendered inside wrapper. You can use dive to force Enzyme to render the content of a component:
expect(wrapper.('InputSearch').dive().find(TextField).getValue()).toEqual('');
or you dont wrap the component with MuiThemeProvider and render InputSearch directly. You only need to add the styles prop. Now InputSearch is the top level component and Enzyme will render its content.
const setup = () => {
const props = {
keyword: '',
resetSearch: resetSearchMock,
searchBooks: searchBooksMock,
toggleResultsOpacity: toggleResultsOpacityMock,
firstSearch: true,
styles: {textfield: {fontSize:10}}
};
const wrapper = shallow(<InputSearch {...props} />);
return {
props,
wrapper,
};
};
const event = { 'target': { 'value': 'No' } };
wrapper.find('#selectBox').prop('onChange').call(null, event);

Resources