1

This is basically for a ReactSelect element (behaves like a Select2 element with multi-select enabled), on which I'm trying to select some values which are not already selected.

If an option is selected, then there'll be an element as given below in the DOM

<div class="select__multi-value__label">option1</div>

and hence that options won't be present in the list. So, any code to click() that "option" will fail.

Is there a way to check whether an element with some particular text is available in the DOM?

something like,

options = ['option1','option2','option3'];
options.forEach(option =>{
   cy.get('[test-id="react-select"]').then(reactSelect =>{
      if(reactSelect.find('[class="select__multi-value__label"]').contains(option).length == 0){
      //code to select that option
        cy.get('div.select__menu-list > div[role="option"]').contains(option).click();
     }
   })
})

This find().contains() part doesn't work. How can I achieve this?

Thanks for any help.

Edit


Adding to the solution given below, can I get an exact match selector - say using a Regex?

let r = new RegExp("^" + option + "$");
 ...........
const selector = `div.select__multi-value__label:contains(${r})`;

This somehow doesn't work. Found a thread that recommends using filter(), but I don't know how to use it.

Is it possible?

art
  • 1,358
  • 1
  • 10
  • 24

2 Answers2

2

You can do it by moving the contains() inside the selector,

options = ['option1','option2','option3'];
options.forEach(option =>{
  cy.get('[test-id="react-select"]').then(reactSelect =>{

      const selector = `[class="select__multi-value__label"]:contains(${option})`

      if(reactSelect.find(selector).length == 0){
        //code to select that option
        cy.get('div.select__menu-list > div[role="option"]')
          .contains(option)
          .click();
     }
   })
})

The .find().contains() part in your code is using a different .contains() to to the Cypress .contains().

It's invoking the jQuery .contains() which has a different purpose

Description: Check to see if a DOM element is a descendant of another DOM element.


I suppose you could also select the options directly and iterate them

options = ['option1','option2','option3'];

cy.get('div.select__menu-list > div[role="option"]')
  .each(option =>{
    if (options.includes(option.text()) {
      option.click();
    }
  })

Exact match

options = ['option1','option2','option3'];
options.forEach(option =>{
  cy.get('[test-id="react-select"]').then(reactSelect =>{

    const matchedOptions = reactSelect
      .find('[class="select__multi-value__label"]')
      .filter((index, el) => el.innerText === option)   // exact

    if(matchedOptions.length === 0){
        //code to select that option
        cy.get('div.select__menu-list > div[role="option"]')
          .contains(option)
          .click();
     }
   })
})
Fody
  • 23,754
  • 3
  • 20
  • 37
  • Thanks for the code. I have had to use the `div.select__multi-value__label` selector though. – art Jul 31 '22 at 09:03
  • Edited the original question to include a selector with an exact text match. PLease check. – art Jul 31 '22 at 09:08
  • 2
    The regex is a good idea, but it doesn't work with `:contains()` unfortunately. It *can* be used with a string.match(r) expression inside a `.filter() as you mentioned - I'll add above what I think should work. – Fody Jul 31 '22 at 09:56
  • Actually, an exact match just needs `===` exact equality check. But if you want to use a regex, substitute `r.test(el.innerText)` which returns true or false. – Fody Jul 31 '22 at 10:07
  • Got it working with `===` itself. Thank you so much! – art Aug 01 '22 at 02:27
0

You should avoid conditionals in tests as it goes against best practice.

A solution in this case following good practices would be to mock the response that comes from the API for you to handle the request as you want, so you will know exactly when there will be specific text on the screen instead of being a random behavior and you won't have to do conditionals.

You can read more about mocks here: https://docs.cypress.io/api/commands/intercept#Stubbing-a-response

But I also advise you to read this Cypress documentation on testing with conditionals: https://docs.cypress.io/guides/core-concepts/conditional-testing#What-you-ll-learn

Caíque de Paula
  • 424
  • 5
  • 17
  • Thanks. My requirement is to test the app and insert some default data through UI. If nothing is there, the tests would run as expected, but in case there was some error in the previous runs, then the data added by those runs causes issues. – art Jul 31 '22 at 09:11