Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add testing utility for generating session cookies [SDK-3569] #816

Merged
merged 5 commits into from
Sep 12, 2022

Conversation

Widcket
Copy link
Contributor

@Widcket Widcket commented Sep 10, 2022

  • All new/changed/fixed functionality is covered by tests (or N/A)
  • I have added documentation for all new/changed functionality (or N/A)

📋 Changes

This PR adds a the generateSessionCookie helper function for generating session cookies, which can be used to mock the Auth0 authentication flow in e2e tests.

Cypress Example

generateSessionCookie can only run on Node.js, not on the browser, so it must be wrapped in a Cypress task:

/// <reference types="cypress" />

import { Session } from '@auth0/nextjs-auth0';
import { generateSessionCookie, GenerateSessionCookieConfig } from '@auth0/nextjs-auth0/testing';

module.exports = (on: any) => {
  on('task', {
    getSessionCookie(params: { session: Session; config: GenerateSessionCookieConfig }) {
      const { session, config } = params;
      return generateSessionCookie(session, config);
    }
  });
};

That task can be invoked from a custom command:

/// <reference types="cypress" />

const cookieName = 'appSession';

Cypress.Commands.add('login', (email: string, password: string) => {
  const tokenEndpoint = `${Cypress.env('AUTH0_ISSUER_BASE_URL')}oauth/token`;
  const clientId = Cypress.env('AUTH0_CLIENT_ID');
  const clientSecret = Cypress.env('AUTH0_CLIENT_SECRET');
  const audience = Cypress.env('AUTH0_AUDIENCE');
  const scope = Cypress.env('AUTH0_SCOPE');
  const cookieSecret = Cypress.env('AUTH0_SECRET');

  const options = {
    body: {
      client_id: clientId,
      client_secret: clientSecret,
      audience: audience,
      scope,
      username: email,
      password,
      grant_type: 'http:https://auth0.com/oauth/grant-type/password-realm',
      realm: 'Username-Password-Authentication'
    },
    headers: {
      'Content-Type': 'application/json'
    },
    method: 'POST',
    url: tokenEndpoint
  };

  // Use the Resource Owner Password Flow to get the test user's access token
  cy.request(options).then(async ({ body }) => {
    const { access_token: accessToken } = body;

    // Invoke the task
    cy.task('getSessionCookie', {
      session: { accessToken, user: { email } },
      config: { secret: cookieSecret }
    }).then((cookie) => {
      // Set the cookie
      cy.setCookie(cookieName, cookie as string);
    });
  });
});

Cypress.Commands.add('logout', () => {
  cy.clearCookie(cookieName);
});

Then, this custom command can be used on test suites to log the test user in:

before(() => {
  cy.login(EMAIL, PASSWORD);
  cy.visit('/');
});

after(() => {
  cy.logout();
});

📎 References

Fixes #335 #548

🎯 Testing

Besides adding unit tests, the changes were tested manually on the sample app:

Screen Shot 2022-09-10 at 02 37 38

@Widcket Widcket added the review:small Small review label Sep 10, 2022
@Widcket Widcket requested a review from a team as a code owner September 10, 2022 05:43
@vercel
Copy link

vercel bot commented Sep 10, 2022

The latest updates on your projects. Learn more about Vercel for Git ↗︎

1 Ignored Deployment
Name Status Preview Updated
nextjs-auth0 ⬜️ Ignored (Inspect) Sep 10, 2022 at 5:43AM (UTC)

@adamjmcgrath adamjmcgrath merged commit a4606ea into vNext Sep 12, 2022
@adamjmcgrath adamjmcgrath deleted the feature/testing-helper branch September 12, 2022 09:57
@adamjmcgrath adamjmcgrath mentioned this pull request Nov 30, 2022
@adamjmcgrath adamjmcgrath mentioned this pull request Dec 20, 2022
4 tasks
@tgallimore
Copy link

tgallimore commented Feb 7, 2024

For anyone arriving here and using this method to sign in inside Cypress, but sees an error when getAccessToken() is called

[AccessTokenError: Expiration information for the access token is not available. The user will need to sign in again.] {
  code: 'ERR_EXPIRED_ACCESS_TOKEN',
  cause: undefined,
  status: undefined
}

add accessTokenExpiresAt to the session object passed to getSessionCookie, like this

cy.request(options).then(async ({ body }) => {
    const { access_token: accessToken } = body;
    cy.task('getSessionCookie', {
      session: {
        accessToken,
        user: { email },
        accessTokenExpiresAt: addDays(new Date(), 1) // add this (choose your own expiry time)
      },
      config: { secret: cookieSecret }
    }).then((cookie) => {
      cy.setCookie(COOKIE_NAME, cookie);
    });
  });

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
review:small Small review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants