Reputation: 21
I'm new in e2e testing with Cypress and I have a question.
I wrote a test and I want not to use Cypress wait() command in it.
it('Should modify checkbox state', () => {
login();
cy.visit(TabsSettings.SIZE_FORMATS).then(() => {
cy.xpath('(//div[@data-qa="sizeFormats"]//*[4]//*//*[1]//*//*//*)[1]', { timeout: 10000 }).click().then(() => {
expect(
cy.xpath('(//input[@type="checkbox"])[1]')
.then(checkbox => checkbox).should('be.checked')
);
});
cy.get('span').contains('Change').click().then(() => {
cy.get('li').contains('Disable').click().then({ timeout: 5000 }, () => {
cy.wait(500);
cy.xpath('(//div[@data-qa="sizeFormats"]//*[4]//*//*[1]//*//*//*)[1]').click().then(() => {
expect(
cy.xpath('(//input[@type="checkbox"])[1]')
.then(checkbox => checkbox[0]).should('be.checked')
);
});
cy.xpath('(//div[@data-qa="sizeFormats"]//*[4]//*//*[1]//*//*//*)[18]').click().then(() => {
expect(
cy.xpath('(//input[@type="checkbox"])[2]')
.then(checkbox => checkbox[3]).should('not.checked')
);
});
});
cy.xpath('//span[contains(text(), "Disable Selected")]').click().then(() => {
cy.get('li').contains('Enable').click().then(() => {
expect(
cy.get('input[type=checkbox]')
.then(checkbox => checkbox).should('not.checked')
);
});
});
cy.get('input[type=checkbox]').then(el => el[0].click()).then(() => {
expect(
cy.get('input[type=checkbox]')
.then(checkbox => checkbox).should('be.checked')
);
}).then(() => {
cy.xpath('//i').then(x => x[1].click());
cy.get('input[type=checkbox]').should('not.checked');
});
cy.get('div[data-main-select=true]').then(list => list[1].click()).then(() => {
cy.xpath('(//li[contains(text(), "50")])[1]').click().then(() => {
cy.get('input[type=checkbox]').should(checkboxes => {
expect(checkboxes).to.have.length(51);
});
});
});
cy.xpath('(//div[@data-qa="sizeFormats"]//*[4]//*//*[1]//*//*//*)[1]').click().then(() => {
cy.wait(150);
expect(
cy.get('input[type=checkbox]')
.then(checkbox => checkbox).should('be.checked')
);
});
});
});
});
My problem is that if I not use that cy.wait(500) command, the test fails. I googled a lot but I cannot find an answer for my problem. The project is an React project, using Hooks. What may be caused the problem is that my component renders multiple times after that click() event. The page does not reload, but the main component rerenders several times. If this is the problem, how can I wait for finishing all renderings, and just after that continue the test, without using the wait function ?
Upvotes: 1
Views: 1664
Reputation: 23483
Looking at it a bit further, you seem to be using a promise-style syntax unnecessarily.
Because Cypress has automatic retry on (most) commands, you can just call the commands sequentially without awaiting the result with .then(...
constructs.
As an example, your code might be revised to something like this,
it('Should modify checkbox state', () => {
login();
cy.visit(TabsSettings.SIZE_FORMATS);
cy.xpath('(//div[@data-qa="sizeFormats"]//*[4]//*//*[1]//*//*//*)[1]', {timeout: 10000 }).click();
// cy.xpath('(//input[@type="checkbox"])[1]').then(checkbox => checkbox).should('be.checked')
cy.get('input[@type="checkbox"]).eq(0).should('be.checked'); // NB eq() has zero-based indexing.
cy.get('span').contains('Change').click();
cy.get('li').contains('Disable').click();
// OR if you have to wait for the Disable button/link to appear, use this
cy.contains('li', 'Disable').click();
cy.xpath('(//div[@data-qa="sizeFormats"]//*[4]//*//*[1]//*//*//*)[1]').click();
cy.get('input[@type="checkbox"]).eq(0).should('be.checked');
...
I'm not familiar with xpath syntax, so the translation is a guess, but it seems Cypress' commands are a little more readable, have a flatter layout, PLUS you get auto-retry built in, which removes the need to wait for specific periods.
If you want to add to your question a pseudocode translation of the xpath expressions, I'll give you the equivalent Cypress commands.
Upvotes: 4
Reputation: 2038
You shouldn't need to use wait
with time, but sometimes you may need to wait for a certain request to finish. I find it's the case with some AJAX requests. You can get it to wait for a specific request to finish using route definitions:
cy.server()
cy.route('activities/*', 'fixture:activities').as('getActivities')
cy.route('messages/*', 'fixture:messages').as('getMessages')
// visit the dashboard, which should make requests that match
// the two routes above
cy.visit('http://localhost:8888/dashboard')
// pass an array of Route Aliases that forces Cypress to wait
// until it sees a response for each request that matches
// each of these aliases
cy.wait(['@getActivities', '@getMessages'])
// these commands will not run until the wait command resolves above
cy.get('h1').should('contain', 'Dashboard')
Read more here: https://docs.cypress.io/guides/guides/network-requests.html#Waiting
Upvotes: 2