
Dropdown elements in Cypress can be tricky if you’re not familiar with how to interact with them effectively. Essentially, these elements can be targeted in a few different ways depending on their structure in the HTML. A common approach is to use the select element, which is often found in forms.
To select an option from a dropdown, you’ll want to use the cy.select() command. This command allows you to specify the value or the visible text of the option you want to select. Here’s a simple example:
cy.get('select#myDropdown').select('Option 1')
.should('have.value', 'option1');
In the above snippet, we target a select element with an ID of myDropdown and select the option with visible text “Option 1”. Following this, we verify that the value of the dropdown has indeed changed to option1.
For dropdowns that are styled with custom components, you might encounter a different approach. Sometimes, the dropdown is not a traditional select element but rather a div that opens a list of options. In such cases, you can simulate clicks to open the dropdown and then select the desired option:
cy.get('div.dropdown').click();
cy.get('div.dropdown-menu').contains('Option 2').click();
Here, we first click on the dropdown to display the options, followed by clicking on the specific option we wish to select. This method mimics user behavior more closely, and it’s essential for dropdowns that do not rely on standard HTML elements.
Another important aspect to consider is ensuring that the dropdown is visible and enabled before interacting with it. Cypress provides commands like should('be.visible') and should('not.be.disabled') to verify the state of the dropdown prior to making selections:
cy.get('select#myDropdown')
.should('be.visible')
.should('not.be.disabled')
.select('Option 3');
In addition, handling dropdowns that load their options dynamically can pose its own set of challenges. You might need to add assertions or waits to ensure that the necessary options are present before trying to select one:
cy.get('select#myDropdown')
.should('exist')
.then($select => {
const optionsCount = $select.find('option').length;
expect(optionsCount).to.be.greaterThan(0);
});
Using a combination of these strategies allows for robust testing of dropdown elements in various contexts. As you dive deeper into form interactions, keep in mind that Cypress offers a powerful suite of commands to facilitate your testing needs, making it a go-to choice for many developers.
When working with radio buttons, there are also nuances to consider…
Roku TV Remote Control (Official Manufacturer Product) - Simple Setup, & Pre-Set App Shortcuts - Replacement Remote Compatible with RokuTV Models ONLY (Not Roku Players)
$16.99 (as of June 2, 2026 22:39 GMT +00:00 - More infoProduct prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on [relevant Amazon Site(s), as applicable] at the time of purchase will apply to the purchase of this product.)Interacting with radio buttons in Cypress
When working with radio buttons, there are also nuances to consider. Unlike checkboxes, radio buttons are designed for single selections within a group. This means that when you select one radio button, any previously selected button in the same group will be deselected automatically. In Cypress, interacting with radio buttons is simpler, as you can target them directly using their name attribute or other identifying selectors.
To select a radio button, you can use the cy.check() command. This command simulates the action of checking a radio button. Here’s a simple example of how to select a radio button:
cy.get('input[type="radio"][value="option1"]').check()
.should('be.checked');
In this snippet, we are targeting a radio button with a specific value of option1. After using check(), we verify that the radio button is indeed checked by asserting its state with should('be.checked').
It’s also important to ensure that the radio button is visible and enabled before interacting with it. You can use similar assertions as with dropdowns to check the state of the radio button:
cy.get('input[type="radio"][value="option2"]')
.should('be.visible')
.should('not.be.disabled')
.check();
In cases where radio buttons are styled or wrapped in custom components, you might need to click on the visible label associated with the radio button instead of the input itself. That is especially true when the input is hidden for styling purposes:
cy.get('label[for="option3"]').click()
.should('be.checked');
This approach simulates a more realistic user interaction, as users typically click on the label rather than the radio button directly. By clicking the label, you ensure that the associated input element is checked correctly.
When testing forms with multiple sets of radio buttons, you can group your assertions to streamline your tests. For instance, if you have multiple groups of radio buttons, you can check one from each group like this:
cy.get('input[name="group1"]').check('option1');
cy.get('input[name="group2"]').check('option2');
This method allows you to clearly outline your intentions in the test and ensures that selections across different groups are handled correctly. Additionally, verifying that only one radio button is selected per group is crucial:
cy.get('input[name="group1"]').should('have.length', 1).and('be.checked');
cy.get('input[name="group2"]').should('have.length', 1).and('be.checked');
By incorporating these practices into your test scripts, you can effectively manage interactions with radio buttons in various scenarios. Remember to consider potential edge cases where radio buttons may be dynamically enabled or disabled based on user actions or other inputs. This can be addressed by adding appropriate waits or assertions:
cy.get('input[name="dynamicGroup"]').should('exist').then(($radio) => {
if ($radio.is(':disabled')) {
cy.log('Radio button is disabled');
} else {
cy.check('dynamicOption');
}
});
Using these strategies will allow you to create more resilient tests for radio button interactions, ensuring that your applications behave as expected under different conditions. The flexibility of Cypress combined with a clear understanding of form elements will lead to more effective testing outcomes.
Best practices for selecting form elements in Cypress
When selecting form elements in Cypress, consistency and clarity in your selectors are paramount. Avoid relying on fragile selectors such as element indexes or overly generic classes that can change frequently. Instead, prefer using unique attributes like id, name, or data-* attributes specifically added for testing purposes. This approach not only increases the stability of your tests but also makes them more readable and maintainable.
For example, using a data-cy attribute is a widely recommended practice:
cy.get('[data-cy="submit-button"]').click();
This selector is immune to UI changes like class renaming or layout restructuring, as it explicitly signals that the element is important for testing.
When dealing with forms containing many similar elements, such as multiple inputs with the same class or type, scoping your selectors can make your tests more robust. Use within() to limit the search context:
cy.get('form#loginForm').within(() => {
cy.get('input[name="username"]').type('user123');
cy.get('input[name="password"]').type('password');
cy.get('button[type="submit"]').click();
});
This technique reduces ambiguity and improves test performance by narrowing down the DOM subtree Cypress has to search.
Another best practice is to avoid chaining multiple get() calls when a single selector suffices. For example, prefer:
cy.get('form#signup input[name="email"]').type('[email protected]');
over
cy.get('form#signup').get('input[name="email"]').type('[email protected]');
because the latter resets the search context and can lead to unexpected results.
When working with checkboxes and radio buttons, always verify their state after interaction. For checkboxes, use:
cy.get('input[type="checkbox"][name="subscribe"]').check().should('be.checked');
cy.get('input[type="checkbox"][name="subscribe"]').uncheck().should('not.be.checked');
In some cases, you may want to toggle the checkbox state conditionally:
cy.get('input[type="checkbox"][name="terms"]').then($checkbox => {
if (!$checkbox.is(':checked')) {
cy.wrap($checkbox).check();
}
});
Similarly, when dealing with inputs that may be disabled or readonly, always assert their state before attempting to interact:
cy.get('input#email')
.should('be.visible')
.and('not.be.disabled')
.and('not.have.attr', 'readonly')
.type('[email protected]');
For inputs with dynamic validation or async behavior, use should() assertions to wait for the expected state before proceeding:
cy.get('input#username')
.should('have.class', 'valid')
.type('validUser');
When you need to verify the values of multiple form fields at the same time, consider using invoke('val') or then() for more complex assertions:
cy.get('input#firstName').invoke('val').should('equal', 'John');
cy.get('input#lastName').then($input => {
expect($input.val()).to.equal('Doe');
});
Lastly, avoid hardcoding waits like cy.wait(1000) to handle asynchronous UI changes. Instead, leverage Cypress’s built-in retry-ability with should() or custom commands to wait for specific conditions:
cy.get('button#submit').should('not.be.disabled').click();
or
cy.get('form#loginForm').within(() => {
cy.get('input[name="username"]').type('user123');
cy.get('input[name="password"]').type('password');
cy.get('button[type="submit"]').click();
});
Following these best practices for selecting and interacting with form elements will help you write Cypress tests that are both reliable and easy to understand, reducing maintenance overhead as your application evolves.
