DEV Community

Cover image for Cypress next-auth mail authentication
pcreem
pcreem

Posted on • Updated on

Cypress next-auth mail authentication

Authentication with email could simplify the signup process and prevent password mistakes. In the topic, we will use next-auth default email authentication method and test the workflow via cypress.

For quick start: repo

point check before cypress testing, make sure you can get the following results

  • after signup with an email, a notification on the webpage homepage
  • an email notification in Mailtrap inbox Mailtrap inbox
  • webpage turn to login state with httpOnly cookie login

cypress authentication work flow

Aim to solve the following test:

  • send an email after a user signup
  • check the email has been received
  • make sure the email contains the link to the homepage
  • click the link in email redirect to the homepage
  • make sure the page turn to login state
  • keep user login after page refresh

Setting up

  • npx yarn add cypress
  • optional npx yarn add faker
  • A user signup with an email code .\cypress\integration\sample_spec.js
const faker = require('faker');
const randomEmail = faker.internet.email().toLowerCase();

describe('Login Test', () => {

    it('Visits the test page', () => {
      cy.visit('http://localhost:3000')
      cy.contains('Sign in').click()
      cy.url().should('include', '/api/auth/signin')

      cy.get('#input-email-for-email-provider')
        .type(randomEmail)
        .should('have.value', randomEmail)

        cy.contains('Sign in with Email').click()
        cy.contains('Check your email')

    });

    it('should send an email containing a verification link', () => {
        const inboxUrl = Cypress.env('inboxUrl')
        const token  = Cypress.env('Api-Token')

        cy.getLastEmail().then(html => {

          const link = html.match(/href="([^"]*)/)[1]
          cy.expect(link).to.contains('/api/auth/callback/email')
          cy.visit(link);
          cy.contains(`Signed in as ${randomEmail}`)
          cy.reload()
          cy.contains(`Signed in as ${randomEmail}`)
          //delete all mail
          cy.request({
            method: 'PATCH',
            url: `${inboxUrl}/clean`,
            headers: {
                'Api-Token': token,
                }
            });
        });
      });
  })


  • API interacts with Mailtrap to get last mail code .\cypress\support\commands.js
const inboxUrl = Cypress.env('inboxUrl')
const token  = Cypress.env('Api-Token')

Cypress.Commands.add('getLastEmail', () => {
    function requestEmail() {
      return cy
        .request({
          method: 'GET',
          url: `${inboxUrl}/messages`,
          headers: {
            'Api-Token': token,
          },
          json: true,
        })
        .then(({ body }) => {

          if (body) {

            let msgId = body[0].id
            cy.request({
            method: 'GET',
            url: `${inboxUrl}/messages/${msgId}/body.html`,
            headers: {
                'Api-Token': token,
            },
            json: true,
            }).then(({ body }) => { 
                if (body) { return body }

                cy.wait(1000);  
                return requestEmail();
            })
          }
        });
    }

    return requestEmail();
  });

configuration
  • code cypress.json
  • there could have network problems during the test, use "retries" to retry the test will save your time, visit cypress page for more info
{
    "retries": 3 
}
  • code cypress.env.json
{
    "inboxUrl":"Your Mailtrap Inbox url with inboxId",
    "Api-Token":"Your Mailtrap API token"
}
  • npx cypress open
  • run sample_spec.js test

the result should like this
cypress open

make a automatical process

  • npx yarn add start-server-and-test
  • npx start-server-and-test 'next dev' 3000 'cypress run' cypress run

Top comments (0)