How to Test a Checkout Form React Component
Get the project source code below, and follow along with the lesson material.
Download Project Source CodeTo set up the project on your local machine, please follow the directions provided in the README.md
file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.
This lesson preview is part of the Fullstack React with TypeScript Masterclass course and can be unlocked immediately with a single-time purchase. Already have access to this course? Log in here.
Get unlimited access to Fullstack React with TypeScript Masterclass with a single-time purchase.

[00:00 - 00:11] Check out form. In this lesson we'll test the form defined in the checkout form component. Let's look at this page. Let's say we have something in the cart, we go to checkout and this is where we'll see the checkout form.
[00:12 - 00:31] It contains the cart holder name, card number, expiration date of the cart and the secret number that is usually on the back of the credit cards. Here we want to verify the following things. When the input values are invalid, so for example, we don't provide the cart holder name, we want to see the error message.
[00:32 - 00:55] Same for the card number and other fields. When the input values are valid, maximum, even of and here we provide some number, 111111, set the expiration date and the CVV. Then when you click the order button, you should call the submit function that in the app will end up redirecting us to the order page.
[00:56 - 01:06] But in the scope of the form, we don't really care. We just want to see that the submit function was called. The form component is defined in the src, checkout, checkout form TSX.
[01:07 - 01:24] Here it has the validations and the component rendering the form. Create a new file, check out form spec TSX. Let's plan the tests. Describe, checkout form, pass a callback. Here we first want to check that it renders correctly.
[01:25 - 01:43] Eat to do renders correctly. Then we want to check what will happen with invalid inputs. Describe with invalid inputs. Pass in a callback and here we'll have only one test case. Eat to do, it should show the errors.
[01:44 - 02:03] Then we want to have another describe block that will group the tests for the valid inputs. Describe with valid inputs. Pass in the callback and here we have another describe because with valid inputs, we may test a bunch of things and here we want to check what will happen when we click the order button.
[02:04 - 02:22] Describe on place order button click. Here we describe another aspect. What will happen when we place an order with valid inputs. Then we expect it eat to do that it calls, submit, function with form data.
[02:23 - 02:33] Alright, so when we render the form, we expect the form to have the following fields. Cards holder name, card number, card expiration date and CVV number.
[02:34 - 03:03] This will be our first test. Define a callback, render the form, const container equals render, checkout form and then write a bunch of expect statements. First we expect that container, inner, HTML, matches, card holders name. Then we expect that it also matches card number. We also want to see that it has expiration date and CVV.
[03:04 - 03:29] Alright and the test passes. If you get an error at this point regarding missing mutation observer, then you can fix it by installing a shim and including it into the setup tests. ts file. Run, yarn, add, mutation, observer, shim and add a flag ignore engines. After it's done, go to setuptest.ts and import mutation observer shim.
[03:30 - 05:24] Now let's check if the form will show the errors within valid input values. Remove the to do, add a callback, render the form, we want to get the container and the get by text method equals render, checkout form. Then you run fire event, click get by text, place, order. After you clicked on this button, we expect that container inner HTML will match error. Here the test will fail because there won't be any error messages containing the error colon. That's because validations are asynchronous in React hook form. And to fix this we have a bunch of options . One of them will be to call await, act and then pass in an async function here async and put the fire event click inside of this function. As now fire event is executed asynchronously and only then we expect that container inner HTML will match error. The test will pass. Unless the asynchronous nature of React hook form validations, we wouldn't have to use the act here because by default all the fire event methods already use act inside of them. And in react, all the methods that end up changing the state of the component must be wrapped into act. Now let's describe the with valid input case. Here we have a test that checks that it calls submit function with form data when we place order with bottom click and we have valid inputs. Let's remove that to do add a callback. It is also going to be an async function for exactly same reason why we had an async function here. That's because we'll perform the validations, they're going to be passing. And then we will submit the form. First thing that we want to do here is to get a mock submit function.
[05:25 - 05:58] const mock submit equals just a fan. We will pass this function as a submit function to checkout form. const get by label text get by text equals render passing the checkout form and pass the mock submit prop mock submit. Next you want to fill in the inputs. We want to find each input by its label text. For example, the cardholders name, the card number, expiration date and CvV.
[05:59 - 06:41] And then call the fire event change with the value that the form would expect. The name of the cardholder, the card number, expiration date and the CvV. After we are done with that, we call fire event click get by text place order. And finally, we need to check if the mock function was called. Here, there is another method of waiting for the async form submission using the await wait for. And here we wait for the mock submit to have been called. Let's import wait for and the test is passing.