Logto authentication in Cypress

This guide will show you how to authenticate with Logto in your Single Page Application (SPA) tests.
Simeng
SimengDeveloper
September 25, 20234 min read
Logto authentication in Cypress

Introduction

Authentication is a crucial part of any web application, and it's essential to ensure that authentication guards work as expected in Single Page Applications (SPAs). In this guide, we'll walk you through the process of authenticating with Logto in your Cypress tests, allowing you to effectively test your SPA's authentication flow.

Prerequisites

Before diving in, ensure you have the following ready:

  • A Logto account. If you don't have one, you can sign up Logto cloud for free.

  • A Single Page Application (SPA) that integrate with Logto for authentication. If you don't have one, please follow our create-and-integrate-the-first-app guide, create and register a new application in Logto.

    create_application
  • Integrate Logto with your SPA application using our out-of-box SDK. e.g. React SDK

  • You may follow our sign-in experience guide to customize the sign-in experience for your own SPA application. Simulate the sign-in flow in your Cypress tests accordingly.

    sign-in-experience
  • Complete the Cypress installation and configuration. This guide assumes you have a well setup Cypress environment and you are able to run your Cypress tests already.

  • Bring up your Logto service and the client application.


We will use our React SPA Sample application as an example in this guide. You can find the source code here.It's a simple React application that integrate with Logto using Logto React SDK for authentication.

  • Logto sign-in url: http://localhost:3001/sign-in
  • React SPA application domain: http://localhost:3000
  • Logto sign-in experience settings: username/password

Write a custom Cypress command to authenticate with Logto

Let's write a custom Cypress command to authenticate with Logto in your Cypress tests. Using the custom command, you can easily authenticate with Logto in any of your Cypress tests.

Step 1: Initiate the sign-in flow

Visit your client application sign-in page in Cypress test, and init the sign-in flow by clicking on the sign-in button.

cy.visit('http://localhost:3000');
cy.get('button:contains("Sign In")').click();
home

Step 2: Fill in the sign-in form and submit

Navigate to the Logto sign-in page, and fill in the username and password to sign in.

Logto sign-in page is hosted on a different domain (http://localhost:3001/sign-in in this example). You will need to authenticate by visiting a different domain with cy.origin.

In normal use, a single Cypress test may only run commands in a single origin, a limitation determined by standard web security features of the browser. The cy.origin() command allows your tests to bypass this limitation.

cy.origin('http://localhost:3001', { args: { username, password } }, ({ username, password }) => {
  cy.url().should('include', 'sign-in');
  cy.get('input[name="identifier"]').type(username);
  cy.get('input[name="password"]').type(password);
  cy.get('button:contains("Sign in")').click();
});
  1. Assert the current url is the Logto sign-in page. sign-in
  2. Identify the username and password input fields and fill in the username and password. submit
  3. Click on the sign-in button to sign in.
You may rewrite the above form filling logic based on your sign-in experience settings.

Step 3: Successful authenticated and redirect back to your client application

After a successful sign-in, you should be able to redirect back to your client application.

cy.contains('Logto React Sample').should('be.visible');
callback

Step 4: Wrap up the entire sign-in flow as a custom Cypress command

Wrap up the entire sign-in flow as a custom Cypress command. cy.signIn in this example.

function signIn(username: string, password: string) {
  cy.visit('http://localhost:3000');
  cy.get('button:contains("Sign In")').click();

  cy.origin('http://localhost:3001', { args: { username, password } }, ({ username, password }) => {
    cy.url().should('include', 'sign-in');
    cy.get('input[name="identifier"]').type(username);
    cy.get('input[name="password"]').type(password);
    cy.get('button:contains("Sign in")').click();
  });

  Cypress.Commands.add('signIn', (username: string, password: string) => {
    const log = Cypress.log({
      displayName: 'SignIn',
      message: [`Sign in with: ${username}`],
      autoEnd: false,
    });
    log.snapshot('before');

    signIn(username, password);

    log.snapshot('after');
    log.end();
  });
}

Use the custom Cypress command to authenticate your application

In any of your Cypress tests, you can use the custom Cypress command to authenticate with Logto.

describe('authentication', () => {
  beforeAll(() => {
    cy.signIn('username', 'password');
  });

  it('should be authenticated', () => {
    cy.contains('Sign Out').should('be.visible');
  });
});

Congratulations! You have successfully authenticated with Logto in your Cypress tests. You can now focus on testing your SPA application without worrying about the authentication flow.