How to Get Text from List of Elements in Cypress
By Hamid Akhtar, Community Contributor - March 10, 2023
Among testing frameworks, Cypress has successfully carved out a position for itself in terms of web automation and end-to-end UI test automation. The question “What is Cypress get text” and “how to get text” are commonly addressed in Cypress.io tests. There are many different approaches to getting a text value from elements.
And while working and constructing a test, you may need to locate the text value and use it in other functions. This article will concentrate on the basic aspect to get a text value while also offering you a number of helpful suggestions.
Setting up the Cypress Test Environment
Cypress is a Node.js based application, thus users must have it already installed on their systems. A JavaScript runtime environment is Node.js. Users will require the following prerequisites in order to begin:
Once finished, execute the following command to install Cypress.
npm install cypress --save-dev
The following command should be run after navigating to the project directory if users want to install Cypress using the Yarn package manager:
yarn add cypress --dev
Also Read: How to perform Cypress Test Automation
Locating Elements on the Page
A locator is an identifier that notifies any automation tool in which GUI elements (such as Text Boxes, Buttons, Check Boxes, etc.) are required for operation. The cy.get() method is used to obtain the HTML element in Cypress using various locators.
There are numerous ways to locate the elements:
- Get HTML Element by ID Selector in Cypress
- Get HTML element by Class in Cypress
- Get HTML element by Tag Name in Cypress
- Get HTML element by Attribute in Cypress
- Working with Multiple Elements in Cypress
- Useful Cypress Locator Functions
- Get the HTML Element by XPath in Cypress
Extracting Text from Elements
When trying to extract text from an HTML element, it is essential to have a fundamental understanding of how HTML elements work. Let’s suppose there are two key elements:
- The <div> defines a section in an HTML document.
- The input element represents a typed data field such as a password field.
<div>Please type in your first name:</div> <input type="text"></input>
During our test, you will fill in the input box and then check to see if the text has the right content. You can see the text on the page with both of these elements. However, if you want to “check text” on each of these items, you must take a somewhat different approach:
cy .get('div') .should('have.text', 'Please type in your name:')
For input field, you can no longer use the approach you used to extract an element from a div. A different strategy is required. To type into DOM elements in Cypress, use the type command. You must add that command here. Check below the latest version for the input field:
cy .get('input') .type('Rick Sanchez') .should('have.value', 'Rick Sanchez')
The difference is that although our div element carries a specific text, HTML input elements are used to insert values.
Get attribute
Attributes can be used to set the HTML Element’s properties. They also help to define the behavior of the elements when a certain requirement is met and triggered. There are attributes for almost all HTML tags.
There may be times when you need to check your links. Then, it would be beneficial to obtain your href property from the anchor element. Suppose you have the following link:
<a href="https://www.browserstack.com/">App & Browser Testing Made Easy!</a>
You may create a test that looks like this to verify the href attribute:
cy .get('a') .invoke('attr', 'href') .should('eq', 'https://www.browserstack.com/')
Additionally, you may check the validity of the link by sending an HTTP request to it:
cy .get('a') .invoke('attr', 'href') .then(href => { cy .request(href) .its('status') .should('eq', 200); });
Text Validations in Cypress
Cypress uses the jQuery text() method to validate text on an element. The text content of the chosen element will be retrieved using this approach. Moreover, you can make assertions on the element’s text content.
cy.get('.product').should('have.text', Browserstack);
With the support of the Javascript methods match(), include(), and others, you may perform validations on the text, such as confirming its contents or matching requirements. As a solution, jQuery objects may be used by Cypress commands to interact with non-Cypress methods and invoke methods on them.
Under the hood, elem.textContent is automatically called by jQuery’s.text() function. You can choose to utilize innerText as an alternative by doing the following:
cy.get('div').should(($div) => { // access the native DOM element expect($div.get(0).innerText).to.eq('foobarbaz') })
Array vs jQuery object
<div> <div class="matching">first</div> <div>second</div> <div class="matching">third</div> <div class="matching">fourth</div> <div>fifth</div> </div>
cy.get('.matching') .then(($els) => { expect(Cypress.dom.isJquery($els), 'jQuery object').to.be .true const elements = Cypress.$.makeArray($els) expect(Cypress.dom.isJquery(elements), 'converted').to.be .false expect(elements, 'to array').to.be.an('array') return elements }) .then((x) => { // but get back a jQuery object again expect(Cypress.dom.isJquery(x), 'back to jQuery object').to .be.true expect(x, 'an not a array').to.not.be.an('array') expect(x.length, '3 elements').to.equal(3) })
<ul id="items"> <li>A</li> <li>B</li> <li>C</li> <li>D</li> </div>
cy.get('#items li').each(($li) => cy.log($li.text()))
//Collect the items then print const items = [] cy.get('#items li') .each(($li) => items.push($li.text())) .then(() => { cy.log(items.join(', ')) })
//Collect the items then assert the list const items = [] cy.get('#items li').each(($li) => items.push($li.text())) // the items reference is set once cy.wrap(items).should('deep.equal', [ 'A', 'B', 'C', 'D', ])
How to find text using contains() command
Using Cypress contains command, you may find the DOM element that contains the text. CSS selectors may make it challenging to locate the element by text, but Cypress offers a solution. You should be able to get the element by using the contains() function along with the tag name. In the event that more than one DOM element contains the necessary text, the first one will be matched. One of the most used commands in Cypress is .contains(). While sounding like an assertion in its name, this command is actually a selecting command. For contains command documentation, click here.
Read More: How to use findbytext in Cypress?
Contains with string content
cy.contains("Forms").click();
contains with number content
cy.contains(2023);
contains with get()
cy.get("span.menu-title").contains("layouts").click();
contains with selector and content
cy.contains("span.menu-title","layouts").click();
Using invoke() to call a function:
Since Cypress commands do not actually execute synchronously, they first check to see if the element specified by that selector is available or not. so you must use the .invoke() function to wait until the element becomes available. Click here to grasp it more:
const obj = {getNumber: () => { return 10;}}; cy.wrap(obj).invoke('getNumber').should('eq', 10);
If you require more, further arguments may be added to the function:
const obj = { sum: function(a, b) {return a + b} }; cy.wrap(obj).invoke('sum', 2, 3).should('eq', 5);
Taking attributes off of HTML elements
Text can be taken out of an HTML element. Consider the following h1 element:
<h1>Cypress testing</h1>
After that, you can confirm the text it contains:
cy.get('h1').invoke('text').should('contain', 'testing');
Using the following code, you might confirm if an image’s src property points to the correct url:
cy.get('img').eq(0).invoke('attr', 'src') .then((src) => { cy.request(src) .then((resp) => { cy.wrap(resp.status).should('eq', 200); }) });
Extract a select’s options list:
cy.get('.multiple-select') .invoke('val') .should('include', 'option1')
If the wrapped object lacks a function, you can extract a property by using “its” rather than “invoke”:
const obj = { value: 23 }; cy.wrap(obj).invoke('value').should('eq', 23); // This does not work! cy.wrap(obj).its('value').should('eq', 23);
Here are the ways that may be used to obtain a Cypress element’s text so that it can be utilized for text assertion:
You may preserve the value as an alias and utilise that alias for future references by using Alias=>.as(). In Cypress, the Alias is saved using the “.as()” function.
- Invoke-Command and Alias: You will call cy.get (locator). invoke (‘text’), then use an alias = > textFunction to save the value of text so that it may be printed using this.aliasName in the next function.
- Using the Wrap Command with Alias: This technique involves wrapping the text’s value in an alias = > textvalue before printing it using this.aliasName in the second function.
- Using the Variables: In addition to using an alias, You may store text values in variables and utilize those variables in multiple functions.
Cypress Selector Playground
Another helpful feature offered by Cypress for users is the ability to quickly find CSS selectors on pages right from the test runner. To avoid problems while using elements, Selector Playground will always match and discover their unique locators.
The primacy of the distinctive locators that Cypress supports is displayed below:
- data-cy
- data-test
- data-testid
- id
- class
- tag
- attributes
- nth-child
Read More: Quick CSS Selectors Cheat Sheet
The WebElements should have the Cypress-recommended attributes data-* added to them in order to protect them from JS/CSS changes that would cause the test to fail.
Custom Cypress Commands
Use the data-test attribute like so:
cy.get("[data-test='hero-heading']")
Even if this is true, wouldn’t it be wonderful if you could simplify this syntax to make our tests simpler to write, interpret, and analyze?
you can create our own unique Cypress command to do this. you can reuse code or functionality across all of our Cypress spec files thanks to a custom command.
To better “obtain” data-test attributes for our use case, you wish to develop a custom Cypress command. This requires that you modify the cypress/support/commands.ts file to include our new command.
This file will by default include a good amount of comments in the code that explain how to write a custom command. This file should be updated to the following and all code comments should be removed:
/// <reference types="cypress" /> Cypress.Commands.add("getByData", (selector) => { return cy.get(`[data-test=${selector}]`) })
Note: You could see compiler problems stating that it was unable to recognize the types in our custom command since you are using TypeScript. You may correct this by making the following additions to the file cypress/support/index.ts:
/// <reference types="cypress" /> declare namespace Cypress { interface Chainable { getByData(dataTestAttribute: string): Chainable<JQuery<HTMLElement>> } }
Now the custom command is ready and you will see here how to implement your custom command in place of the cypress command in the example given below:
You can only give the value of any data-test property into this custom command named “getByData,” like in the following example:
cy.getByData("hero-heading")
instead of:
cy.get("[data-test='hero-heading']")
After developing our custom command, let’s refactor our cypress/e2e/home.cy.ts test to make use of it and verify that our test is still passing.
// home.cy.ts it("the h1 contains the correct text", () => { cy.getByData("hero-heading").contains( "Testing Next.js Applications with Cypress" ) })
Conclusion
When testing Cypress, typical issues arise, and if you carefully heed the preceding guidance, your everyday operations should be error-free.
Note that for true results, Cypress testing needs to be run on actual browsers. Start using BrowserStack to conduct tests on more than 30 versions of the latest browsers on Windows and macOS.
Use quick, painless Cypress parallelization to run Cypress Parallel tests and get faster results without sacrificing accuracy. In order to find bugs before users do, applications must be tested using BrowserStack in real-world usage scenarios.