Conditional Testing in Cypress: Tutorial

Hamid Akhtar
Coinmonks
10 min readMar 2, 2023

--

When you perform one action or a different one, you are using conditional testing, a basic programming pattern. It is also referred to as control flow. This is typically stated as If X, then Y, otherwise Z.

  • The key to developing effective Cypress tests is to give Cypress as much information and data as possible while preventing it from sending new commands until your application has achieved the appropriate condition at which it must proceed.
  • Conditional testing in Cypress, however, is a serious challenge since the test writers are frequently unclear about what the provided state will be.
  • Every developer and QA engineer needs Cypress, the new benchmark in front-end testing.

Importance of Conditional testing in Software Testing

If the element exists, you want to do something, and if it doesn’t, you want to do something else. Despite how straightforward this question initially appears, answering it correctly involves much complexity. The goal of conditional testing is to test every condition or test in the source code thoroughly.

Consider a situation where your application might do two things you cannot control. In other words, you tried every tactic but, for whatever reason, could not predict how your application would behave in advance. Conditional testing makes it easy to test this in Cypress!

Setting up Cypress for Conditional Testing

Installing Cypress and configuring the environment

Installing all prerequisites first in our project is necessary. Refer to the Cypress test Automation tutorial first.

Create a new project folder and set up a new Cypress project after ensuring all the requirements are met.

  • Create the folder anywhere on your computer, then launch Visual Studio Code by choosing File>Open Folder>Choose the file from the system>click Ok.
  • The next step is to use the ‘npm init -y’ command in the terminal to generate the ‘package.json’ file in our project. This file initializes the npm project and serves as a dependency management file, allowing us to run npm commands directly on the project.
  • The project name, version, description, keywords, author, license, and script section are all included in the package.json file. The script section is used to run the test scripts from the terminal.
  • Install Cypress by using the ‘npm install cypress’ command to install the most recent version of Cypress or ‘npm install cypress@version number‘ to install the specific version of Cypress that is needed, for example, ‘npm install cypress@10.10‘ after creating the ‘package.json’ file.

Run the “npx cypress open” command to launch Cypress.

Once Cypress has been launched, select E2E Testing, click Continue, pick a browser, and then click Start Cypress E2E Testing in that browser.

After selecting “Start E2E Testing,” a Cypress runner appears, allowing us to create spec files with the “.cy.js” extension. A copy of this file will also be created in Visual Studio Code, where we can write your test cases.

Creating a basic Test Suite in Cypress

An array of test cases is known as a test suite, and it is used to run tests and record their outcomes. You can have a test suite for any of a software application’s fundamental features or a specific sort, like smoke, security test suites, etc. The Cypress approach to organizing numerous connected tests is known as ‘describe’. Every describe block is part of a group of tests.

Writing Test Cases with Conditional statements

Assume that when you visit your website, the content will vary depending on the A/B campaign your server chooses to transmit. It could depend on a user’s geolocation, IP address, time of day, location, or other hard-to-control circumstances.

How is it possible to create tests in this way?

Regulate which campaign is sent or offer a trustworthy way to identify it.

// this sends us the session cookies
cy.visit('https://app.com')
// assuming this sends us back
// the campaign information
cy.request('https://app.com/me')
.its('body.campaign')
.then((campaign) => {
// runs different cypress test code
// based on the type of campaign
return campaigns.test(campaign)
})

You might now ask your server to inform you the campaign you are currently in if it saves the campaign along with a session.

A session cookie that you can read off from your server may be another way to test this:

cy.visit('https://app.com')
cy.getCookie('campaign').then((campaign) => {
return campaigns.test(campaign)
})

Another viable tactic would be to embed data into the DOM directly, but to do it in a way that makes the data constantly accessible and searchable.

This would not function unless it were present constantly:

cy.get('html')
.should('have.attr', 'data-campaign')
.then((campaign) => {
return campaigns.test(campaign)
})

Using Conditional Statements in Cypress tests

Common use cases for conditional testing in Cypress

  • Users get a “welcome wizard,” but existing users don’t. Can you always close the wizard in case it appears and ignore it when it doesn’t?
  • Can you undo unsuccessful Cypress commands, such as when cy.get() fails to find an element?
  • Attempting to develop dynamic tests that react differently depending on the text on the page.
  • What should you do differently depending on whether an element exists?
  • How can you account for the A/B testing that your application conducts?
  • You want to locate every <a> element automatically, and depending on which ones you locate, you want to verify that each link operates.

The basic goal of Cypress conditional testing is to conduct tests on an element with multiple potential outcomes, each of which may require you to act on a different outcome.

Best Practices for Conditional Statements in Cypress Tests

The foundation of Cypress framework is writing trustworthy tests. The key to creating effective tests is to give Cypress as much “state” and “facts” as you can while “guarding” it from issuing new commands until your application has achieved the state you want it to be to continue.

Understanding how your application behaves is essential to avoid writing flaky tests. For example,

  • You cannot perform conditional testing on the DOM without server-side rendering and no asynchronous JavaScript.
  • Another strategy is to use client-side JavaScript that does synchronous rendering alone.
  • The fact that the test writers are unsure of the provided state when conducting conditional testing adds a significant challenge.
  • Under certain circumstances, embedding a dynamic state reliably and consistently is the only reliable approach to having accurate tests.

Must Read: How to write Test Case in Cypress?

Working with Conditional Logic in Cypress

The following examples will help you understand conditional testing and how to use it in your test:

Case Study:

Step 1: Visit https://automationteststore.com/ as the first step.

Step 2: Select the Login button.

Step 3: If the option to “Register Account” is not checked, select it.

/// <reference types="cypress" /> 
describe('My first test', function()
{
it('account registration test', () => {
cy.visit('https://automationteststore.com/')
cy.get('#customer_menu_top').click()
cy.get('#accountFrm_accountregister').then(($input) => {
if ($input.is(':checked')) {
cy.log('The option for account registration is chosen by default')
} else {
cy.wrap($input).click()
}
})
})
})

Here is a single test case in the test file mentioned above that will click on the registration option on the web page only if it is not already selected by default; otherwise, it will simply print a statement indicating that the option for account registration is already selected by default without carrying out any click action on the registration option.

To run the test file, you must first open the Cypress test runner using the ‘npx cypress open‘ command and then click the test file on the test runner. This will start the execution, and the test results will be displayed.

Using ssertions with the conditional statement

The cypress-if plugin is where the child commands .if() and .else() originate. Any Cypress assertion can be used as the .if(assertion) condition; element existence is used by default. The test follows the “IF” path and bypasses the “ELSE” section of the command chain.

describe('Example to demo conditional testing in cypress', () => {
beforeEach(() => {
cy.visit('https://wikipedia.org')
})
it('Check that if you find WikiVoyage on the page, then click on it and validate (Go to If)', () => {
cy.title().should('eq', 'Wikipedia')
cy.get('body').then((body) => {
if (body.find('[data-jsl10n="wikivoyage.name"]').length > 0) {
cy.get('[data-jsl10n="wikivoyage.name"]').click()
}
else {
cy.get('[data-jsl10n="wiktionary.name"]').click()
}
})
cy.title().should('eq', 'Wikivoyage')
})
it('Check that if you dont find WikiVoyage in the page, then click on Wiktionary and validate (Go to Else)', () => {
cy.title().should('eq', 'Wikipedia')
cy.get('body').then((body) => {
if (body.find('wrongLocator').length > 0) {
cy.get('[data-jsl10n="wikivoyage.name"]').click()
}
else {
cy.get('[data-jsl10n="wiktionary.name"]').click()
}
})
cy.title().should('eq', 'Wiktionary')
})
})

Cypress code eloboration for the scenario mentioned above.

  • First, check that the body of the website has loaded. Now, using the find() command, you will attempt to locate the element WikiVoyage using the body.
  • Checking an element’s length is the simplest way to confirm its presence.
  • Therefore, if an element exists, its length should be larger than 0, which is why we typed (body.find(‘[data-jsl10n=”wikivoyage.name”]’)). length > 0).
  • When you locate the element, it should click on it to access the WikiVoyage website and verify the page title using the cy.title().should(‘eq’, ‘Wikivoyage’).
  • Check the location of the else condition execution once more in the above scenario. The WikiVoyage element must not be present for this to be feasible.
  • You then typed body.find(‘wrongLocator’). length > 0 to simulate that situation.
  • In this case, the else condition is executed because wrongLocator is merely some dummy text that prevents you from retrieving the element.
  • Click the Wiktionary title in the else block to launch the website and check the page title with cy.title(). should(‘eq’, ‘Wiktionary’).

Use npm test to run the test at the end, and you should see a successful execution.

cy.then

When the input box is not checked, you need a mechanism to click it.

it('submits the terms forms', () => {
cy.visit('cypress/terms.html')
cy.get('#agreed').then(($input) => {
if ($input.is(':checked')) {
cy.log('The user already agreed')
} else {
cy.wrap($input).click()
}
})
cy.get('button#submit').click()
})

If the code is little unclear to you, you will need to be familiar with the jQuery selectors and commands. You will also need to use the cy.wrap command to put the element back into a Cypress chain before using the .click() command.

Using loops and iterations in conditional testing

it('cy.each stops iteration when returning false', () => {
const fruits = ['apples', 'bananas', 'oranges', 'pears']
cy.wrap(fruits)
.each((fruit, k) => {
console.log(k, fruit)
if (k === 2) {
return false
}
cy.log('fruit', fruit)
})
// cy.each yields the original subject
// even if you stop the iteration early
.should('equal', fruits)
})

The snippet above will come to a stop when it determines that k == 2. You can manipulate and adjust the loop’s control per conditional logic.

Grouping test cases with conditional logic

With this.skip(), which can be applied conditionally based on, for example, an environment variable, you can dynamically skip a test through condition logic.

beforeEach(function() {
const testFilter = Cypress.env('TEST_FILTER');
if (!testFilter) {
return;
}
const testName = Cypress.mocha.getRunner().test.fullTitle();
if (!testName.includes(testFilter)) {
this.skip();
}
})

Handling Exceptions and Errors in Conditional Testing

You should consider unsuccessful commands in Cypress to be similar to uncaught exceptions in server-side programming. In those circumstances, the system has changed to an unreliable state, making any attempt at recovery impossible. In contrast, you almost always choose to crash and log.

It is what Cypress is doing when it fails the test. Reporting the failure, bypassing any remaining commands in the test, and bailing out. But here, you need to assume for the purposes of argument that Cypress did include error handling.

Enabling this would result in error recovery for every command, but only after the corresponding command timeout was reached. It would take a very long time to fail because timeouts begin at 4 seconds (and increase from there).

//! You cannot add error handling to Cypress commands.
//! This code is just for demonstration purposes
function keepCalmAndCarryOn () {
cy.get(...). should(...). click()
}
cy.get('#wizard').
contains('Close').
click().catch((err) => {
// no problem, i guess the wizard didn't exist
// or something... no worries
keepCalmAndCarryOn()
}).
then(keepCalmAndCarryOn)
  • In the best case, you had wasted at least 4 seconds waiting for the <#wizard> element to exist before we erred and moved on possibly.
  • The <#wizard> was supposed to be rendered, but in the worst-case scenario, it didn’t render within the timeout you were allowed.
  • Assume that this resulted from a timer in the queue, a WebSocket message, a waiting network request, or anything else.
  • In this case, not only did you wait a long time for the< #wizard> element to appear, but it also probably led to an error farther down the line on other commands.

No matter what programming idioms are available to you, you cannot build 100% deterministic tests if you cannot determine the state of your application reliably.

Debugging and Troubleshooting Cypress Conditional Tests

1. Debugging conditional tests with Cypress’ debugger

A key consideration when selecting an automation framework is debugging. Let’s take the scenario when a tester has created ten lines of the test script, and it fails or throws an error. They must investigate the causes of its failure. Now you can easily create your first condition test with Cypress debugging successfully.

2. Using console logs and error messages for troubleshooting

On both the Cypress window console and the browser console, testers can print logs when using Cypress. Even printing the stack trace to the browser console is an option.

In Cypress, console logs can be used in one of two ways:

  • cy.log() command
  • console.log() by configuring cypress tasks

3. Analyzing test results and fixing failures

Debugging Cypress tests can be done in various ways, each with different levels of complexity. Each technique needs to undergo several testing rounds before testers can select one (or more) that best meets their skill set, available resources, and overall convenience.

By allowing test retries, Cypress Cloud can identify, report, and monitor flaky tests from your recorded Cypress test runs in your CI/CD workflow.

Organizing and methodically monitoring Cypress flaky tests can help you identify them as they happen, estimate their severity, and prioritize their fix.

Closing Notes

Applications written in JavaScript today are highly dynamic and mutable. Over time, the state and DOM undergo constant change. Conditional testing has the drawback of only being applicable when the state has stabilized. However, it is frequently impossible to tell when a situation is stable.

A change that occurs every 10 or even 100 milliseconds could escape your notice. However, a computer will have the ability to monitor those changes. Most of the time, you cannot use the state of the DOM to guide your conditional behavior. This results in flaky testing, which Cypress API is built to address at every stage.

While leveraging a real device cloud like BrowserStack, teams may take advantage of various advantages. Without external emulators, they will inevitably achieve the highest test coverage. Additionally, teams save a lot of the time and expense needed to build device labs.

For automated testing in an Agile environment, BrowserStack uses a cloud-based grid comprising more than 3000+ device-browser-OS combinations.

Source: https://www.browserstack.com/guide/conditional-testing-cypress

New to trading? Try crypto trading bots or copy trading on best crypto exchanges

Join Coinmonks Telegram Channel and Youtube Channel get daily Crypto News

Also, Read

--

--

Hamid Akhtar
Coinmonks

Let us talk!!! hmdlabee@gmail.com Telegram: @binarycole =* I write 1000 words daily.