Reputation: 15627
I have a React app with infinite scrolling, so when the user scrolls to the bottom of the page, ajax request is made to retrieve more results. I have been struggling to test this code and below is what I was able to get working based on google / Stackoverflow searches. I am not clear on what Cypress.$
does, or how its different to say Cy.*
commands.
I feel, I am not clear on how to get the logic to work with the async nature of Cypress. The following code is commented to explain my thinking.
it("should scroll to bottom, retrieve & display next results", () => {
// wait because some ajax request takes longer upon page load
cy.wait(500);
let initialCount = null;
// store the length of elements in variable
initialCount = Cypress.$("div.experienceThumbnail").length;
// scroll down to bottom
cy.scrollTo("bottom", { duration: 1000 });
// wait because an ajax request is made for the pagination
cy.wait(1111);
// get the same elements again
cy.get("div.experienceThumbnail")
.its("length")
// compare the new count to prev. count we stored above in initialCount var
.should("be.gt", initialCount);
});
My main question is what is the proper way of testing something like above.
Upvotes: 1
Views: 2307
Reputation: 396
In my opinion one of the disadvantages with Cypress (as compared to other test-automation tools). Before and after comparisons. Either you have such a nested function which can only used in this one specific location or you store the variable in aliases. Both are not satisfying. Since Toteff did not write the alias version, my attempt (also without verifying the code), but works in similar situation:
const initialCount = Cypress.$("div.experienceThumbnail").length;
cy.wrap(initialCount).as('before');
cy.scrollTo("bottom", { duration: 1000 });
const afterCount = Cypress.$("div.experienceThumbnail").length;
cy.wrap(afterCount).as('after');
this.compareAliasNumbers('after', 'before', 'After <= Before');
Then this util function:
compareAliasNumbers(smaller: string, bigger: string, message: string) {
cy.get(`@${bigger}`).then((a1) => {
const biggerNr = parseInt(a1 as unknown as string, 10) + 1; // plus one = greater than or equal
cy.get(`@${smaller}`).then((a2) => {
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
const smallerNr = parseInt(a2 as unknown as string, 10);
expect(initialCount <= biggerNr).to.be.true
});
});
}
In my opinion: both version (the nested by Toteff or this via alias creation) are difficult to read. Code reuse is only possible in the latter, but I also dont like it (coming from another automatic testing tool). Are there other solutions?
Upvotes: 0
Reputation: 2207
In Cypress
one has to learn to live with nested Promises
if you want a fine control over assertions.
I haven't tested the next two suggestions, but at least one of them should work:
it("should scroll to bottom, retrieve & display next results", () => {
const selector = "div.experienceThumbnail"
cy.wait(500);
cy.get(selector).then($els => {
const initialCount = $els.length
cy.scrollTo("bottom", { duration: 1000 });
cy.wait(1111);
cy.get(selector)
.its("length")
.should("be.gt", initialCount);
})
});
it("should scroll to bottom, retrieve & display next results", () => {
const selector = "div.experienceThumbnail"
cy.wait(500);
cy.get(selector).then($els => {
const initialCount = $els.length
cy.scrollTo("bottom", { duration: 1000 });
cy.wait(1111);
cy.get(selector).then($els2 => {
const currentCount = $els2.length
expect(initialCount <= currentCount).to.be.true
})
})
});
Upvotes: 1