Cypress - how to find by text content?
Asked Answered
A

8

88

In Cypress, I want to select a button from a group of buttons based on its text-content. How can I do it? Here is my approach:

export const getCustomerButton = () => getNavigationSidenav()
  .find('mat-expansion-panel-header')
  .each(($el, index, $list) => {
    const text = $el.find('.mat-content > mat-panel-title').text();
    if (text === 'Customer') {
      return $el;
    }
    return null;
  });

The problem I have now is that I have to filter out the nulls from the element array. Is there a less complicated way?

Astronomical answered 17/8, 2019 at 6:10 Comment(1)
Do you have any HTML you can show. I see you already got your answer, but a bit of what you were trying to select would help.Gatling
M
102

This code will yield the DOM element with YOUR_BUTTON_CLASS which contains text 'Customer'. Is that what you're looking for?

cy.get('.YOUR_BUTTON_CLASS').contains('Customer');

Here the documentation for .contains cypress command.

Melinite answered 17/8, 2019 at 12:11 Comment(3)
Note that chaining commands like this can cause flakiness because the get is not retried after it finds something, even if none of the elements it finds contain 'Customer' (see the docs)Interlaminate
Just doing cy.get('Customer') would try to yield an element Customer instead which is not what we require.Potto
If you want to get the count of elements, better to use this refer this method https://mcmap.net/q/236696/-cypress-how-to-find-by-text-contentMarcos
A
48

Or maybe an even slicker solution is to use this:

cy.contains('YOUR_BUTTON_CLASS', 'Customer');

This can be done since contains() can hold 2 arguments. And if it gets two arguments the first one is always the element and the second the text.

Apathy answered 19/8, 2019 at 6:33 Comment(3)
contains method returns only first found elementMessing
and even simpler is this: cy.contains('Customer')Mccallion
This should be the default answer, due to the way Cypress handles query retries: "we recommend using cy.contains(selector, text) which is retried automatically as a single command." docs.cypress.io/guides/core-concepts/…Vandal
P
43

Another option that's not mentioned in the previous answers here.

Use testing-library/cypress-testing-library

After the installation, just import it in cypress' commands.js:

import '@testing-library/cypress/add-commands'

And in your tests

cy.findAllByText("Jackie Chan").click();
cy.findByText("Button Text").should("exist");
cy.findByText("Non-existing Button Text").should("not.exist");
cy.findByLabelText("Label text", { timeout: 7000 }).should("exist");
cy.get("form").within(() => {
  cy.findByText("Button Text").should("exist");
});
cy.get("form").then((subject) => {
  cy.findByText("Button Text", { container: subject }).should("exist");
});

This is pretty straightforward and easy to use. We use this in our production site along with react testing library. Highly recommend :)

Pieria answered 28/8, 2019 at 10:40 Comment(4)
I was just wondering before I install this plugin, will cy.findByText('Button').click() yield same results as the built-in command cy.contains('Button').click(). If no, what is the difference?Ladner
I did a quick test and it looks like the returned buttons are slightly different, see this screenshot but they both work as they shouldPieria
Is there a way for findAllByText() to only target visible elements?Oshea
Didn't test, but I think you can do a .filter(':visible')?Pieria
R
35

The accepted answer "can" work. However: if the element is not visible on the first try, the element cannot be found in subsequent retries.

See: https://github.com/cypress-io/cypress/issues/3745

Cypress uses "Sizzle" as selector library - so this:

cy.get('button:contains("FooBar")')`

would work in retries.

Requiescat answered 26/5, 2021 at 6:10 Comment(0)
S
10

There are multiple ways to do that

Syntaxes:

cy.contains(content)
cy.contains(content, options)
cy.contains(selector, content)
cy.contains(selector, content, options)

Examples:

cy.contains('button', 'Customer')
cy.contains('.buttonClass', 'Customer')
cy.get('button:contains("Customer")')
cy.contains('Customer')
Soliz answered 24/12, 2021 at 11:10 Comment(0)
G
0

The simplest way to do it would be :

cy.get('Button_Class').contains('Button_Text')

In your case, the solution would be :

cy.get('.mat-content > mat-panel-title').contains('Customer')

There is a documentation for this here.

Gayla answered 4/8, 2022 at 6:15 Comment(0)
P
0

While both cy.contains('selector', 'text') and cy.get('selector').contains('text') are valid solutions, it is important to understand the difference between them.

cy.contains() will yield the element that matches your selector and contains the text, while cy.get().contains() will yield the element within your selector that directly contains the text

Example

The command cy.get('div').contains('sample text') will yield the span element, while the cy.contains('div', 'sample text') command will yield the div element

<div>
    <span>
        sample text
    </span>
</div>
Prater answered 10/5 at 18:21 Comment(0)
P
0
cy.get('.your element class name').contains('text of the button').should('have.text','text of the button').click();

You can use this approach to ensure that Cypress accurately finds and interacts with the desired element on your webpage.

Perfervid answered 25/5 at 15:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.