Creating a second test for a valid form submission

Now that we have got the gist of how to write robust tests, let's add a second test to check that no validation errors are shown when the form is filled incorrectly:

  1. We'll start by creating a new test in our ContactUs group:
describe("ContactUs", () => {
test("When submit without filling in fields should display errors", () => {
...
});

test("When submit after filling in fields should submit okay", () => {
// TODO - render component, fill in fields, submit the form and check there are no errors
});
});
  1. We'll render the component in the same way as the first test, but destructuring slightly different variables:
test("When submit after filling in fields should submit okay", () => {
const handleSubmit = async (): Promise<ISubmitResult> => {
return {
success: true
};
};
const { container, getByText, getByLabelText } = render(
<ContactUs onSubmit={handleSubmit} />
);
});

Now:

  • We'll need the container object to check whether there are any errors displayed
  • We'll use the getByText function to locate the Submit button
  • We'll use the getByLabelText function to get references to our inputs
  1. We can now get a reference to the name input using the getByLabelText function. After that, we do a little check to verify that the name input does exist:
const { container, getByText, getByLabelText } = render(
<ContactUs onSubmit={handleSubmit} />
);

const nameField: HTMLInputElement = getByLabelText(
"Your name"
) as HTMLInputElement;
expect(nameField).not.toBeNull();
  1. We then need to simulate the user filling in this input. We do this by calling the native change event, passing in the required event argument, which includes our input value:
const nameField: HTMLInputElement = getByLabelText(
"Your name"
) as HTMLInputElement;
expect(nameField).not.toBeNull();
fireEvent.change(nameField, {
target: { value: "Carl" }
});

We have simulated the user setting the name field as Carl.

We use a type assertion after the call to getByLabelText to inform the TypeScript compiler that the returned element is of type HTMLInputElement, so that we don't get a compilation error.
  1. We then can follow the same pattern for filling in the email field:
const nameField: HTMLInputElement = getByLabelText(
"Your name"
) as HTMLInputElement;
expect(nameField).not.toBeNull();
fireEvent.change(nameField, {
target: { value: "Carl" }
});

const emailField = getByLabelText("Your email address") as HTMLInputElement;
expect(emailField).not.toBeNull();
fireEvent.change(emailField, {
target: { value: "[email protected]" }
});

 Here, we have simulated the user setting the email field as [email protected].

  1. We can then submit the form by clicking the Submit button, in the same way as in our first test:
fireEvent.change(emailField, {
target: { value: "[email protected]" }
});

const submitButton = getByText("Submit");
fireEvent.click(submitButton);
  1. Our final task is to verify there are no errors displayed on the screen. Unfortunately, we can't use the getAllByText function we used in the last test, as this expects to find at least one element, and in our case we expect there to be no elements. So, before we carry out this check, we are going to add a wrapping div tag around errors. Let's go to Form.tsx and do this:
{context.errors[name] && context.errors[name].length > 0 && (
<div data-testid="formErrors">
{context.errors[name].map(error => (
<span key={error} className="form-error">
{error}
</span>
))}
</div>
)}

 We've given the div tag a data-testid attribute, which we'll use in our test. 

  1. Let's go back to our test. We can now locate the div tag around the errors using the data-testid attribute. We can then verify that this div tag is null, because no errors are displayed:
fireEvent.click(submitButton); 

const errorsDiv = container.querySelector("[data-testid='formErrors']");
expect(errorsDiv).toBeNull();

When the test runs in our suite of tests, we'll find we now have three passing tests.

Isn't referencing the data-testid attribute an implementation detail, though? The user doesn't see or care about the data-testid attribute—this seems to contradict what we said earlier.

It is kind of an implementation detail, but it is specifically for our test. So, an implementation refactor is unlikely to unexpectedly break our test. 

In the next section, we are going to add another test, this time using Jest snapshot tests.

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

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