End-to-end and integration tests need to synchronize with asynchronous work such as UI updates, network requests, or background jobs. Pausing for a
fixed amount of time using framework APIs like Cypress' cy.wait(<number>) or page.waitForTimeout(<number>) in
Playwright and legacy Puppeteer releases before v22.0.0 is a brittle way to do this:
Each modern end-to-end framework ships dedicated synchronization primitives that wait for an observable condition instead of a duration. Replace the fixed wait with one of these primitives so the test moves on as soon as the application is ready, and fails quickly when it is not.
cy.intercept(…).as(name) and wait on the alias, or assert on the resulting DOM state with
retry-able queries such as cy.contains(…).should('be.visible').expect(locator).toBeVisible() or
expect(locator).toHaveText(…), or page.waitForResponse / page.waitForURL when the synchronization point is a
network event.page.waitForSelector, page.waitForFunction, or page.waitForResponse.
page.waitForTimeout was deprecated in v16.1.1 (2022-08-16) and removed in v22.0.0 (2024-02-05).
// Cypress
it('saves a user', () => {
cy.get('button.save').click();
cy.wait(1000); // Noncompliant: fixed wait
cy.contains('Saved').should('be.visible');
});
// Cypress
it('saves a user', () => {
cy.intercept('POST', '/users').as('saveUser');
cy.get('button.save').click();
cy.wait('@saveUser');
cy.contains('Saved').should('be.visible');
});
// Playwright
test('saves a user', async ({ page }) => {
await page.getByRole('button', { name: 'Save' }).click();
await page.waitForTimeout(1000); // Noncompliant: fixed wait
await expect(page.getByText('Saved')).toBeVisible();
});
// Playwright
test('saves a user', async ({ page }) => {
await page.getByRole('button', { name: 'Save' }).click();
await expect(page.getByText('Saved')).toBeVisible();
});
// Puppeteer (<22.0.0)
test('saves a user', async () => {
await page.click('button.save');
await page.waitForTimeout(1000); // Noncompliant: fixed wait
expect(await page.$('.toast')).not.toBeNull();
});
// Puppeteer
test('saves a user', async () => {
await page.click('button.save');
await page.waitForSelector('.toast');
expect(await page.$eval('.toast', node => node.textContent)).toContain('Saved');
});