I have methods in my test code that uses within to find and access selectors. Mainly, it's because there are several blocks of code with identically named selectors, which I cannot change. But also because I find it more tidy than dealing with complex and often poorly created indexed selectors/id's.
Simplified markup:
<div data-e2e-selector="byggrad>
<div data-e2e-selector="adresserad">
<div data-e2e-selector="etasjerad">
<div data-e2e-selector="finansieringsobjektrad">
<input data-e2e-selector="boligbetegnelse">
</div>
<div data-e2e-selector="finansieringsobjektrad">
<input data-e2e-selector="boligbetegnelse">
</div>
</div>
<div data-e2e-selector="etasjerad">
<div data-e2e-selector="finansieringsobjektrad">
<input data-e2e-selector="boligbetegnelse">
</div>
<div data-e2e-selector="finansieringsobjektrad">
<input data-e2e-selector="boligbetegnelse">
</div>
</div>
</div>
</div>
There may be several elements of each, all nested as above. So, using eq(0) to get the selector with a specific index seems to work fine.
This code works fine:
cy.get('[data-e2e-selector=byggrad]').eq(0)
.within(() => {
cy.get('[data-e2e-selector=adresserad]').eq(0)
.within(() => {
cy.get('[data-e2e-selector=etasjerad]').eq(0)
.within(() => {
cy.get('[data-e2e-selector=finansieringsobjektrad]').eq(0)
.within(() => {
cy.get('[data-e2e-selector=boligbetegnelse]').clear();
cy.get('[data-e2e-selector=boligbetegnelse]').type('TEST');
});
});
});
});
However, this does not:
this.getBoligbetegnelse().clear();
this.getBoligbetegnelse().type('TEST');
getBoligbetegnelse() {
return cy.get('[data-e2e-selector=byggrad]').eq(0)
.within(() => {
cy.get('[data-e2e-selector=adresserad]').eq(0)
.within(() => {
cy.get('[data-e2e-selector=etasjerad]').eq(0)
.within(() => {
cy.get('[data-e2e-selector=finansieringsobjektrad]').eq(0)
.within(() => {
cy.get('[data-e2e-selector=boligbetegnelse]');
});
});
});
});
}
Of course, I realized after a while, this is because the method returns the [data-e2e-selector=byggrad] element, and not the [data-e2e-selector=boligbetegnelse] element.
So, then I try this:
getBoligbetegnelse() {
cy.get('[data-e2e-selector=byggrad]').eq(0)
.within(() => {
cy.get('[data-e2e-selector=adresserad]').eq(0)
.within(() => {
cy.get('[data-e2e-selector=etasjerad]').eq(0)
.within(() => {
cy.get('[data-e2e-selector=finansieringsobjektrad]').eq(0)
.within(() => {
return cy.get('[data-e2e-selector=boligbetegnelse]');
});
});
});
});
}
But that doesn't work at all, since the method then is not returning anything at all. Of course, because of Cypress' asynchroneous way.
I've played around a bit with .then as well, having read that this is a way to make a command run after the execution has started. But I've found no way to make use of it here.
So, is it possible to find the element this way, and return the inner element instead of the top element? Or do I have to think differently, and start passing values to the methods instead of having them return elements? I'm guessing this is related to the asynchroneous running of Cypress commands and the code?
If this is just how it must be done, it seems to make it hard, if not impossible, impossible to do more effective refactoring, since it's impossible to have ONE method that returns the a code block and then multiple methods that take that code block and look for different specific elements within it.