App & Browser Testing Made Easy

Give your users a seamless experience by testing on 3000+ real devices and browsers. Don't compromise with emulators and simulators

Get Started free
Home Guide How to perform Visual Testing for React Apps

How to perform Visual Testing for React Apps

By Gurudatt S A, Community Contributor -

React JS is an excellent framework for developing Single Page Applications. React is a Javascript library that provides a flexible way of developing UIs and uses Components to render elements in the UI. 

In this quick guide, learn to efficiently use Percy in testing a React application to perform Continuous Testing within the CI/CD pipeline. For this article, we will e using the Cypress Real World React app.

Types of React App Testing

In the React application, we can perform two levels of testing:

  1. End-to-End Testing: is usually performed when the application is deployed and running with all its components rendered in the browser.
  2. Component Testing: Whereas Component testing is done during the development stage, this allows writing a majority number of tests with various combinations for a single Component. This will quickly increase the quality of the application at a very early stage.

React Component Visual Testing

Prerequisite

  • Refer to this documentation for Cypress and Percy’s setup
  • For this article’s purpose, we are using the Cypress Real World React app, which can be found here.
  • Please clone this repository to your local laptop for practice purposes.

We will be first writing a Cypress component test for the sign-in form, which looks like the following:

Cypress Login

The component source code for this can be found here.

Our Cypress component test for Sign-in Form will look like this

it("submits the username and password to the backend", () => {
mount(
<MemoryRouter>
<SignInForm authService={authService} />
</MemoryRouter>
);
cy.get("[data-test*=signin-username]").type("Katharina_Bernier");
cy.get("[data-test*=signin-password]").type("s3cret");
cy.get("[data-test*=signin-submit]").click();

cy.wait("@loginPost");

cy.get("[data-test*=signin-error]").should("not.exist");
});

Let’s take an example where we need to validate the background color of the SIGN IN button.

The Cypress code to get the background color will look like below

cy.get(".MuiButton-containedPrimary").should(
"have.css",
"background-color",
"rgb(63, 81, 181)"
);
  • But imagine writing this for several elements and covering for color and background color; this would become a time-consuming task.
  • To speed up the time-consuming task and better validate, we can now integrate Percy to capture the snapshot of this particular SIGN IN button and validate for any visual changes.
  • We will now use Percy’s command percySnapshot to capture a snapshot of this Sign in the form component.

The Cypress code will look like the below, further configuration details can be found here.

cy.percySnapshot("sign in form");

And the test will be as follows:

it("submits the username and password to the backend", () => {
mount(
<MemoryRouter>
<SignInForm authService={authService} />
</MemoryRouter>
);
cy.get("[data-test*=signin-username]").type("Katharina_Bernier");
cy.get("[data-test*=signin-password]").type("s3cret");
cy.get("[data-test*=signin-submit]").click();
cy.get("[data-test*=signin-error]").should("not.exist");
cy.percySnapshot("sign in form");
});

When we execute this test, the first-time snapshot build will be sent to Percy, and we need to approve it. Which will then become the baseline image for future comparison.

Percy Snapshot comparisonTo see how the Percy Snapshot comparison works, we will change the background color of the SIGN IN button from secondary to primary and create a pull request.

Once the Github actions run the build, we can see the build failed like below.

React Visual Testing - Percy build FailThis clearly shows that functional tests are passing, but the visual test we performed with Percy in our Component test failed, and we need to review this.

We can simply click on the Details link against the failed Percy check to review.

React Visual Testing - Percy Fail check

  • As we can see, the changed background color of the SIGN IN button is highlighted by Percy.
  • We can now approve or Reject the build based on the requirement.
  • The component-level Visual testing in React application consumes less time and gives early feedback on the appropriately used changes.

React End-to-End Visual Testing

End-to-End testing is generally time-consuming as the test usually covers the user journey in the application. The End-to-End tests usually focus on the functional aspects of the application, to ensure the visual aspect is not broken during the user journey, we can make use of Percy for Visual testing.

The Cypress test for the End-to-End flow will look like the following:

it.only("navigates to the new transaction form, selects a user and submits a transaction payment", function () {
const payment = {
amount: "35",
description: "Sushi dinner 🍣",
};

cy.getBySelLike("new-transaction").click();
cy.wait("@allUsers");

cy.getBySel("user-list-search-input").type(ctx.contact!.firstName, { force: true });
cy.wait("@usersSearch");
cy.visualSnapshot("User Search First Name Input");

cy.getBySelLike("user-list-item").contains(ctx.contact!.firstName).click({ force: true });
cy.visualSnapshot("User Search First Name List Item");

cy.getBySelLike("amount-input").type(payment.amount);
cy.getBySelLike("description-input").type(payment.description);
cy.visualSnapshot("Amount and Description Input");
cy.getBySelLike("submit-payment").click();
cy.wait(["@createTransaction", "@getUserProfile"]);
cy.getBySel("alert-bar-success")
.should("be.visible")
.and("have.text", "Transaction Submitted!");

const updatedAccountBalance = Dinero({
amount: ctx.user!.balance - parseInt(payment.amount) * 100,
}).toFormat();

if (isMobile()) {
cy.getBySel("sidenav-toggle").click();
}

cy.getBySelLike("user-balance").should("contain", updatedAccountBalance);
cy.visualSnapshot("Updated User Balance");

if (isMobile()) {
cy.get(".MuiBackdrop-root").click({ force: true });
}

cy.getBySelLike("create-another-transaction").click();
cy.getBySel("app-name-logo").find("a").click();
cy.getBySelLike("personal-tab").click().should("have.class", "Mui-selected");
cy.wait("@personalTransactions");

   cy.getBySel("transaction-list").first().should("contain", payment.description);

   cy.database("find", "users", { id: ctx.contact!.id })
     .its("balance")
     .should("equal", ctx.contact!.balance + parseInt(payment.amount) * 100);
   cy.getBySel("alert-bar-success").should("not.exist");
   cy.percySnapshot("Personal List Validate Transaction in List");
 });

As we can see, first, we perform all our function checks, and finally, we validate if the Visual aspect is proper.

  • The above Cypress test can be found on this repo
  • When we run the above test, we can see snapshots sent to Percy for the first time, and we need to Approve the build for making these images as baseline images.

React Visual App Testing - Cypress Test

If any change in the feature branch does not match the baseline image, our Percy test will fail, and Percy will highlight the changes, which we can Approve or Request for change.

Conclusion

  • The cost to fix a bug is very high during the later stages of the software development cycle.
  • Adding tests during the early stages of development will keep the product quality high and yield good ROI.
  • Adding more tests at the component level will speed up the test execution time and identify the bugs at a very early stage of development.

In this article, we have seen how to leverage Visual testing at a Component level and the End-to-End test level, enabling us to perform Continuous Testing within CI/CD pipeline. Make sure to sign up on BrowserStack to utilize Percy visual testing and the newly updated Percy visual engine.

Try Percy Visual Testing

How to perform Visual Testing for React Apps

Tags
Types of Testing Visual Testing

Featured Articles

How to test React Apps

Unit Testing of React Apps using JEST : Tutorial

App & Browser Testing Made Easy

Seamlessly test across 20,000+ real devices with BrowserStack