Reputation: 27
This is my code, according to the docs this isnt a good practice, docs call this "code doing backflips" but it should work:
let sizeVar;
before(() => {
cy.visit("https://web-page");
cy.get("a").not("[href='']").not("[href='#']").its("length").then((size) => {
sizeVar = Cypress.$(size);
return sizeVar;
});
})
for (let i = 0; i < sizeVar; i++) {
it(`tag <a> index ${i}`, () => {
cy.get("a").not("[href='']").not("[href='#']").eq(i).should("have.attr", "title");
})
}
Unfortunately, it doesnt :( after runing above test in Cypress I have "No tests found in your file. We could not detect any tests in the above file. Write some tests and re-run." What the hell?! The funny fact is that when I will change in the loop the sizeVar for some static number, for example 100, it will work and move smoothly.
for (let i = 0; i < 100; i++)
But I dont need the static number, I need it done in the right way... According to the docs the best way is to use aliases. So I did, this is the code:
before(() => {
cy.visit("https://web-page");
cy.get("a").not("[href='']").not("[href='#']").its("length").as("size");
})
for (let i = 0; i < this.size; i++) {
it(`tag <a> index ${i}`, () => {
cy.get("a").not("[href='']").not("[href='#']").eq(i).should("have.attr", "title");
})
}
And again I doesnt work, this time I get "Cannot read property 'size' of undefined". Where am I doing mistake? Please help.
=======================UPDATE===============================
I was thinking about to use pure JS but this not work either... I dont see any wrong logic in my code... But Cypress dont want to pass this variable :(
describe("test", () => {
let links = document.querySelectorAll("a");
let linksLength = links.length;
before(() => {
cy.visit("https://web-page");
})
for (let i = 0; i < linksLength; i++) {
it(`tag <a> index ${i}`, () => {
cy.get("a").not("[href='']").not("[href='#']").eq(i).should("have.attr", "title");
})
}
})
Upvotes: 1
Views: 3308
Reputation:
The problem is the for loop is getting evaluated before any testing starts. You can think of it as a two-pass process, the first pass loads the command queue and the second runs the commands.
Best I can find is to split the logging and the testing by using two sequential .then()
clauses.
Test
it('finds external links', () => {
cy.visit("https://web-page");
cy.get("a").not("[href='']").not("[href='#']")
.then($list => {
// Get the titles
const titles = [...$list].map((el) => Cypress.$(el).attr('title') )
// Log all their values
titles.forEach((value, index) => {
cy.log(`tag <a> index ${index} - title is ${value}`)
})
// Pass on to next then()
return cy.wrap(titles)
})
.then(titles => {
// Test the titles
expect(titles.every(title => title)).to.equal(true, 'All titles are defined')
})
})
Result
log tag <a> index 0 - title is 1
log tag <a> index 1 - title is undefined
log tag <a> index 2 - title is 3
AssertionError All titles are defined: expected false to equal true
HTML fragment tested
<div>
<a href="link1" title="1">1</a> // ok
<a href="link2">2</a> // fails
<a href="link4" title="3">3</a> // ok
<a href="">4</a> // ignored
<a href="#">5</a> // ignored
</div>
Upvotes: 2