When within is used to find and return some element within some other element and then followed by should to test the returned element, this breaks _all_ subsequent commands (all, not just in the same chain) by permanently setting the root to the aforementioned other element.
In other words, cy.get('#scope').within(() => cy.get(…)).should(…) breaks the rest of the test, because it makes it impossible to find anything outside #scope.
cy.get(…).within(() => cy.get(…)).should(…) shouldn't impact subsequent commands at all. E.g. cy.get(…) used after it should search the entire document as usual.
<div id="foo"><p>foo</p></div>
cy.root().should('match', 'html') // passes, as it always should
cy.get('#foo')
.within(() => cy.get('p')) // returns `#foo p`
.should('match', 'p') // passes, but causes the scope of preceding `within` to become global
cy.root().should('match', 'html') // fails! root is still `div#foo`
_Obviously this example is contrived, it's just a minimum reproducible sample._
Cypress 3.3.2
Chrome 75.0.3770.100 (Official Build) (64-bit)
MacOS 10.14.5 (18F132)
I am able to reproduce this bug with the code below.
it('within scope', () => {
cy.visit('https://example.cypress.io/commands/actions')
cy.root().should('match', 'html') // passes, as it should outside a within
cy.get('#actions').within(() => {
cy.get('p') // returns `#foo p`
}).should('match', 'p') // passes, from docs, should return <div#actions>
cy.root().should('match', 'html') // fails! root is `div#actions`
})
Any update on this bug. I am facing this issue in various places.
This is the simplest one, we are facing it everytime. When we do any search and then assert the rows return fro search results using should(have.length,X); and then trying to target next element for further testing, but it finds the new element from inside the returned rows (due to should assertions).
It would be great if we can get work around for this,
@jennifer-shehane : Any news on this issue ?
Was facing the same issue. Using the cy.get() again seems to be resetting the scope.
Also running into this, this cost us a couple hours. This is supremely unintuitive. We found that cy.get after the .should did _not_ reset the scope (we were unable to even cy.get('body') until we removed the call to cy.within(..).should(...))
Had to add command, as a temp solution
Cypress.Commands.add('tempWithin', {
prevSubject: true
}, (subject, method) => {
cy.wrap(subject).within(() => method())
return cy.wrap(subject)
})
I'm seeing this in another situation... I am using .each, and Cypress isn't releasing the subject for the next get:
cy.get('.interest-mosaic').each(($tile) => {
cy.wrap($tile).invoke('removeAttr', 'style')
cy.wrap($tile).should('exist').and('not.have.attr', 'style')
})
cy.contains('Master Topics').should('be.visible')
This results in Cypress looking for 'Master Topics' _WITHIN_ the previous subject, which is not what I want:

Unless I'm using each wrong?
But if I remove the whole block before cy.contains('Master Topics').should('be.visible'), everything runs fine and it looks for 'Master Topics' on the whole page instead of just within the previous subject. Maybe within and each are doing something similar behind the scenes?
@krinhorn You're encountering this issue #4921
@jennifer-shehane Aha! Thank you!
Hi,
I am facing the same issue but with a different pattern.
Cypress.Commands.add("out", { prevSubject: "element" }, (subject) => {
return cy.get(subject).within(() => {
return cy.get(".port-AND-OUT");
});
});
cy.get(".parentA")
.out()
.should("exist");
cy.get(".parentB") --> Failed
I manage to fix it with
cy.get(".parentA")
.out()
.as("whatever")
.should("exist");
cy.get(".parentB") --> Worked
The code for this is done in cypress-io/cypress#8699, but has yet to be released.
We'll update this issue and reference the changelog when it's released.
Released in 5.4.0.
This comment thread has been locked. If you are still experiencing this issue after upgrading to
Cypress v5.4.0, please open a new issue.
Most helpful comment
@jennifer-shehane : Any news on this issue ?