Mihail Yordanov
Mihail Yordanov

Reputation: 25

Cypress UI - get an element inside double within block

I have the following scenario: I find some text to navigate to a section in my HTML. Then I find some other text to navigate to a subsection. Inside this subsection I have a button when clicked displays a modal dialog (which is placed outside both sections that I'm currently in. If I try to grab the modal dialog from within the sections it does not work. If I go outside the sections, it works.

cy.contains("Some text").parent().within(() => {
   cy.contains("Some other text").parent().within(() => {
      cy.find("Button that triggers a modal dialog").click();
      //does not work
      cy.getModalDialog().within(() => {
         cy.contains("OK").click();
      })
   })
})
cy.contains("Some text").parent().within(() => {
   cy.contains("Some other text").parent().within(() => {
      cy.find("Button that triggers a modal dialog").click();
     })
})
//works
cy.getModalDialog().within(() => {
   cy.contains("OK").click();
})

Is there a better way how to grab this modal, without going outside the double within blocks?

Upvotes: 0

Views: 578

Answers (2)

Fody
Fody

Reputation: 32080

Cypress provides an option withinSubject that can remove the effect of .within() for that particular command.

Element to search for children in. If null, search begins from root-level DOM element

cy.get("div#1").within(() => {
  cy.get("span").within(() => {

    // cy.get("div#2");                          // ❌ fails

    cy.get("div#2", { withinSubject: null });    // ✅ passes

  })
})

Test page

<body>
  <div id="1">
    <span>one</span>
  </div>
  <div id="2">
    <span>two</span>
  </div>
</body>

Note this feature was broken in v12.0.2 and fixed again in v12.1.1

Upvotes: 2

Ron Newcomb
Ron Newcomb

Reputation: 3302

Although Cypress does allow things like cy.document() from which I presume you can go down from there, in general whenever I find a pattern where I "find a thing, then inside the thing, find another thing and do stuff", I'm better off never using .within at all. Instead I combine all the "find the thing" into one very large, very specific selector for a single .get

This does mean I need to repeat the long selector multiple times, and the .get is very heavy which seems backward, but it helps me avoid descending into callback heck.

In my current level of understanding, I do believe .within is a trap.

Upvotes: 0

Related Questions