Creating a basic component test

We are going to start by creating a unit test to verify that submitting the Contact Us form without filling in the fields results in errors being displayed on the page:

  1. We are going to implement a unit test on the ContactUs component. We'll start by creating a file called ContactUs.test.tsx in the src folder.
  2. We are going to use ReactDOM to render a test instance of the ContactUs component. Let's import React and ReactDOM:
import React from "react";
import ReactDOM from "react-dom";
  1. We are going to simulate the form submit event, so let's import the Simulate function from the React testing utilities:
import { Simulate } from "react-dom/test-utils";
  1. Let's now import the component we need to test:
import ContactUs from "./ContactUs";
  1. We also need to import the submission result interface from Form.tsx as well:
import { ISubmitResult } from "./Form";
  1. Let's start to create our test using the Jest test function, with the results outputting to a ContactUs group:
describe("ContactUs", () => {
test("When submit without filling in fields should display errors", () => {
// TODO - implement the test
});
});
  1. The first task in our test implementation is to create our React component in the DOM:
test("When submit without filling in fields should display errors", () => {
const handleSubmit = async (): Promise<ISubmitResult> => {
return {
success: true
};
};

const container = document.createElement("div");
ReactDOM.render(<ContactUs onSubmit={handleSubmit} />, container);

// TODO - submit the form and check errors are shown

ReactDOM.unmountComponentAtNode(container);
});

First, we create a container div tag and then render our ContactUs component into this. We have also created a handler for the onSubmit prop, which returns success. The last line in the test cleans up by removing the DOM elements that were created in the test.

  1. Next, we need to get a reference to the form, and then submit it:
ReactDOM.render(<ContactUs onSubmit={handleSubmit} />, container);

const form = container.querySelector("form");
expect(form).not.toBeNull();
Simulate.submit(form!);

// TODO - check errors are shown

ReactDOM.unmountComponentAtNode(container);

Here is the step-by-step description:

  • We use the querySelector function, passing in the form tag to get a reference to the form tag.
  • We then check that the form is not null by using the Jest expect function with the not and toBeNull functions chained together.
  • The submit event is simulated using the Simulate function from the React testing utilities. We use an ! after the form variable to inform the TypeScript compiler that it is not null.
  1. Our final task is to check that the validation errors are displayed:
Simulate.submit(form!);

const errorSpans = container.querySelectorAll(".form-error");
expect(errorSpans.length).toBe(2);

ReactDOM.unmountComponentAtNode(container);

Let's see this step-by-step:

  • We use the querySelectorAll function on the container DOM node, passing in a CSS selector to find the span tags that should contain the errors
  • We then use the Jest expect function to verify that two errors are displayed
  1. When the test runs, it should pass successfully, giving us two passing tests:

In this test, Jest is rendering the component in a fake DOM. The form submit event is also simulated, using the simulate function from standard React testing utilities. So, there's a lot of mocking going on in order to facilitate an interactive component test.

Also note that we are referencing internal implementation details in our test code. We reference a form tag, along with a form-error CSS class. What if we later change this CSS class name to contactus-form-error? Our test would break, without there necessarily being a problem with our app.

This is called a false positive, and can make code bases with these kinds of tests very time-consuming to change.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.148.177