Search code examples
async-awaitnext.jscypresssettimeoutuse-context

Cypress Testing Async Await Functions with useContext and Next.js


I am looking to ensure a notification appears within a Cypress integration test, with the correct message. I've created an async await function that has a try/catch block for the user to login, displaying different messages throughout their progress.

Stages of notification status attribute:

  1. Before the try/catch block - status = "info"
  2. At the end of try block - status = "success"
  3. At the end of the catch block - status = "error"

Example:

  async function signIn(event) {
    notificationCtx.showNotification({
      message: "Logging in now",
      status: "info",
    });
    try {...

Cypress Test:

   it.only("case 'The InvalidParameterException shows a suitable  error'", () => {
      onFormLayoutsPage.testPlainTextInput("email", "team");
      onFormLayoutsPage.testPlainTextInput("password", "8s8d7fds!!");
      cy.get('[data-cy="login"]').click();
      cy.get('[data-cy="notification"]').should(
        "have.attr",
        "status",
        "error"
      );
    });

Problem:

The notification appears, but then disappears because of setTimeout(), before the cy.get() has a chance of seeing the component. The specific error is Timed out retrying after 20000ms: Expected to find element: [data-cy="notification"], but never found it.

Component:

<Snackbar open={true} onClose={notificationCtx.hideNotification}>
  <Alert
    data-cy="notification"
    onClose={notificationCtx.hideNotification}
    severity={status}
    sx={{ width: "100%" }}
  >
    {message}
  </Alert>
</Snackbar>

Solution

  • You can control the setTimeout() using Cypress cy.clock() and cy.tick() commands.

    it("case 'The InvalidParameterException shows a suitable  error'", () => {
    
      cy.clock()                        // take control of when setTimeout() finishes
    
      onFormLayoutsPage.testPlainTextInput("email", "team");
      onFormLayoutsPage.testPlainTextInput("password", "8s8d7fds!!");
      cy.get('[data-cy="login"]').click();
      cy.get('[data-cy="notification"]').should("have.attr", "status", "error");
    
      cy.tick(3000)                     // allow time to pass & setTimeout to complete
    
      cy.get('[data-cy="notification"]').should('not.exist')
    });