rakitin
rakitin

Reputation: 2175

How do I locate dom elements within nested shadow doms using cypress when `find(...).shadow` is not a function`

I am working with Cypress v9.6.1 and custom elements with shadow dom. We have several custom elements which are deeply nested - I am able to query for an input that is deeply nested with several web components successfully with something like this:

// WORKS!
cy.get(‘custom-element-1’)
    .shadow()
    .find('custom-element-2’)
    .shadow()
    .find('custom-element-3’)
    .shadow()
    .find(`custom-element-4[id=“ce”4]`)
    .shadow()
    .find('input');

What I'd like to do is determine the presence of that input before moving forward in the test.

Pseudo code - 
if (cy.('.deeply-nested-element').exists() ){
  do.not.click(button-a)
} else {
  click(button-a)
}

Following the cypress docs for conditional testing -> element presence I attempted to express the above in a conditional and use on the length attribute to determine presence

//DOES NOT WORK
cy.get(‘custom-element-1').then(($ce) => {
    if($ce.shadow()
    .find('custom-element-2’)
    .shadow()
    .find('custom-element-3’)
    .shadow()
    .find(`custom-element-4[id=“ce”4]`)
    .shadow()
    .find('input')) // then do something
}

This gave me an error. Property 'shadow' does not exist on type 'JQuery<HTMLElement>'. Did you mean 'show'?ts(2551)

Ignoring the ts error resulted in cypress test failing with: $ce.find(...).shadow is not a function

I switched it up a little by chaining off of shadow() with the same result

//ALSO DOES NOT WORK
cy.get(‘custom-element-1').shadow().then(($ceshadow) => {
    $ce
    .find('custom-element-2’)
    .shadow()
    .find('custom-element-3’)
    .shadow()
    .find(`custom-element-4[id=“ce”4]`)
    .shadow()
    .find('input');
}

And for this one: $ce.find(...).shadow is not a function

It looks to me like the promise off of the get method does not pass to the callback an element with a shadow dom (JQuery). The small problem I'm trying to figure out is a workaround to that. The larger problem is how to set up a conditional that is determined by the presence of an element that is deeply nested within custom element shadow doms. Any advice would be much appreciated.

Upvotes: 0

Views: 1327

Answers (1)

Fody
Fody

Reputation: 31974

The .shadow() command is a Cypress command, but $ce is a jQuery object that can't call Cypress commands directly.

$ce.find(...).shadow is not a function occurs because both jQuery and Cypress have .find(), but only Cypress has .shadow().

By making includeShadowDom:true global either in config or the test options, Cypress commands can be used without needing to chain .shadow() at every step.

If it's custom-element-1 that is conditional, this should work

it('tests deeply-nested shadow elements', {includeShadowDom:true}, () => {

  cy.get('body').then($body => {

    const ce1 = $body.find('custom-element-1');
    if (ce1.length) {

      cy.wrap(ce1)                 // wrap jQuery element into Cypress result
                                   // so that includeShadowDom:true is effective
        .find('custom-element-2')
        .find('custom-element-3')
        .find('custom-element-4[id="ce4"]')
        .find('input')) 
    }
  })
})

Upvotes: 2

Related Questions