I am working on a react project which is built using react-bootstrap
UI. While there are a lot of options for writing test cases, I opted for Snapshot testing
using Jest
.
I have a component which is wrapped inside a bootstrap
Modal and is always rendered with a null
value in the generated snapshot. If remove the Modal
wrapper and directly return the form then it generates the output just fine.
I want to mock the bootstrap Modal
so as to return a simple implementation (while keeping rest of the library un-touched) and reduce the complexities of passing all the various props required by the react-boostrap
library.
function MyComponent(){
return (
<div>
<Modal
show={props.showReviewModal}
onHide={handleClose}
className="well-connection-review"
>
<Modal.Header closeButton>
<Modal.Title className="m-auto p-auto">
Modal Title
</Modal.Title>
</Modal.Header>
<Form
noValidate
validated={validated}
onSubmit={(e) => handleValidation(e)}
>
<Modal.Body>
<Form.Row className="m-2 d-flex align-items-center">
<Form.Group as={Col} controlId="formPowerCompany" className="m-1">
<Form.Label className="label">Power Company</Form.Label>
<Select
isClearable={true}
name="PowerCompany"
options={ELECTRIC_PROVIDERS}
className="basic-multi-select well-connection-report-filters"
onChange={PowerCompanyChange}
value={powerCompany}
isSearchable={false}
placeholder="Power Company"
/>
</Form.Group>
</Form.Row>
<Form.Row className="m-2 d-flex align-items-center">
<Form.Group as={Col} controlId="formMeterID" className="m-1">
<Form.Label className="label">Meter ID</Form.Label>
<Form.Control
type="text"
value={meterId}
name="meterId"
onChange={handleChange}
autoComplete="off"
/>
<Form.Control.Feedback type="invalid">
Please enter an ID
</Form.Control.Feedback>
</Form.Group>
</Form.Row>
</Modal.Body>
<Modal.Footer className="mr-3">
<Button
variant="primary"
onClick={() => handleClose()}
type="submit"
>
Close
</Button>
</Modal.Footer>
</Form>
</Modal>
</div>
);
}
export default MyComponent;
import React from "react";
import MyComponent from "../MyComponent";
import renderer from "react-test-renderer";
describe("Snapshot testing of MyComponent", () => {
it("MyComponent snapshot", () => {
const MyComponent = renderer.
create(<MyComponent message={"message"} />).toJSON();
expect(MyComponent).toMatchSnapshot();
});
});
// Jest Snapshot v1, [link to jest docs]
exports[`Snapshot testing of MyComponent`] = `null`;
Posting a solution here so that it helps anyone who stumbles upon it in future. The easiest way to do away with the complexities of passing the required props and mocking the various methods of the react-boostrap
library components is to mock the individual components of the library and return a custom implementation for it.
The idea here is to NOT test the structure of components of the external library but to just test the structure of your own components
.
// MyComponents.test.js
import React from "react";
import MyComponent from "../MyComponent";
import renderer from "react-test-renderer";
// this code will be auto hoisted by Jest
jest.mock("react-bootstrap", () => {
// get the original boostrap library
const orgBootstrap = jest.requireActual("react-bootstrap");
// mock the Modal component
const mockModal = ({ children }) => { return <div>{children}</div>; };
// mock the sub-components of the Modal
mockModal.Header = (props) => <div>{props.children}</div>;
mockModal.Body = (props) => <div>{props.children}</div>;
mockModal.Footer = (props) => <div>{props.children}</div>;
// return your modified boostrap library instance with mocked Modal
const mockBoostrap = { __esModule: true, ...orgBootstrap, Modal: mockModal };
return mockBoostrap;
});
describe("Snapshot testing of MyComponent", () => {
it("MyComponent snapshot", () => {
const MyComponent = renderer.
create(<MyComponent />).toJSON();
expect(MyComponent).toMatchSnapshot();
});
});