Cypress data-testid not found

Viewed 69

I am running a cypress test on a remote web app and the cy.get method fails to capture elements based on their data-testid . This is a sample of the tests that I want to run :

describe('test: deny', () => {
  it('I can deny', () => {
    cy.visit('https://www.deepskydata.com/');
    cy.wait(1000)
    cy.get("[data-testid='uc-accept-all-button']").click();

  });
});

Here the button with data-testid='uc-accept-all-button' is not found by cy.get. Also cy.get('button') doesn't work despite that there are multiple button elements in the DOM. Has anyone ever encountered a similar issue ?

3 Answers

I could see that there is a Shadow DOM in your app. TO make sure cypress traverses through the shadow DOM, in your cypress config file write:

includeShadowDom: true

Your cypress.config.js should look like this:

const { defineConfig } = require("cypress");

module.exports = defineConfig({
  e2e: {
    ...
  },
  ...
  includeShadowDom: true
})

Then in your test, you can directly write:

describe('test: deny', () => {
  it('I can deny', () => {
    cy.visit('https://www.deepskydata.com/')
    cy.get("[data-testid='uc-accept-all-button']").should('be.visible').click()
  })
})

Avoid using cy.wait() as these can make the tests flaky. Instead use a visible assertion to first check that the element is visible and then click on it.

The button you want to click is for privacy settings.

The problem is this section of the page isn't consistently displayed, once you click the "Accept All" button it may not display on the next run.

To avoid the problem, you should poll for the button inside the shadow root container element before attempting to click.

function clickPrivacySettingsButton(attempt = 0) {

  // Poll for 4 seconds
  if (attempt === 40) {
    cy.log('No Accept All button to click')
    return
  }

  cy.get('#usercentrics-root', {log:false}).then($privacySettings => {

    const prvivacyShadow = $privacySettings.shadowRoot   // get shadow root 
    const $acceptAllButton = Cypress.$(prvivacyShadow) 
      .find('[data-testid="uc-accept-all-button"]')      // look for button 

    if ($acceptAllButton.length === 0) {
      cy.wait(100, {log:false})
      clickPrivacySettingsButton(++attempt)
    } else {
      cy.get('#usercentrics-root')
        .shadow()
        .find('[data-testid="uc-accept-all-button"]')
        .click()
      cy.log('Dismissed Accept All button')
      return
    }
  })
}

cy.visit('https://www.deepskydata.com/')
clickPrivacySettingsButton()

Notes

  • You cannot just use Cypress includeShadowDom setting, because the shadow root may or may not exist.

  • You will have to apply cy.wait() in small increments to effectively poll for the Privacy Settings section.

You may want to have a test to check the banner exists for a user meeting certain conditions.

Otherwise, you can bypass this modal, with correct permissions of course, by making a making a graphQL mutation saveConsents, so you will not need to making any checks at the UI level.

Note: you should choose your method of recursing and allow failOnStatusCode.

cy.request({
  method: 'POST',
  url: 'url-endpoint',
  auth: 'any-authorization',
  body: {
     operationName: 'saveConsents',
     query: 'graphQL mutation query'
  }
  variables: 'variables-if-needed',
  failOnStatusCode: false, // to allow recurse
})
Related