4

I have a regular single page application (Vue), which authenticate via auth0 and generates a token which is validated by the backend on API calls.

I would like to test the vue application using cypress.

There are various "official" strategies (i.e. log in for every call or using a session and logging in once).

https://auth0.com/blog/end-to-end-testing-with-cypress-and-auth0/ https://docs.cypress.io/guides/testing-strategies/auth0-authentication

I could find only one resource about stubbing the auth0, instead of actually sending requests for tokens - https://github.com/auth0/auth0-spa-js/issues/210 .

I reached the above link by following another Stackoverflow post - How to test single page application with Cypress and Auth0 .

I have only little experience, but the stubbing solution seems closer to the best practices of test driven development.

I wanted to ask why it seems much less popular and if I miss the actual reasons behind the "actual auth0 call" options.

Thank you!

shaolintl
  • 43
  • 5
  • 1
    Why do you think this is stubbing (or even "stabbing")? All methods have the same pattern - obtain a genuine token and save it to appropriate storage. You have no choice in the matter since authentication is designed to avoid spoofing. If you can stub it in a test, don't use - it's no good. – Dizzy Al Feb 12 '22 at 09:08
  • Thank you for your reply. I am not planning on using the "fake" token to actually access the API. The idea is to use cypress to intercept auth0 authentication so we can simulate the user logging in. Then intercept (using the user token) API calls. – shaolintl Feb 12 '22 at 16:34
  • Ok, I was fooled by the word "mock" in the title, and the word "stabbing" which I thought was a mis-type of the word "stubbing". – Dizzy Al Feb 12 '22 at 19:22

1 Answers1

0

This is how I solved that in React:

1 - Create a command to log in:

// cypress/support/commands.js

Cypress.Commands.add('A0login', () => {
  Cypress.log({
    name: 'loginViaAuth0',
  })
  const audience = Cypress.env('auth_audience')
  const client_id = Cypress.env('auth_client_id')
  const scope = 'openid email profile offline_access'

  const options = {
    method: 'POST',
    url: Cypress.env('auth_url'),
    body: {
      grant_type: 'http://auth0.com/oauth/grant-type/password-realm',
      realm: 'Username-Password-Authentication',
      username: Cypress.env('DEFAULT_USER'),
      password: Cypress.env('DEFAULT_PASSWORD'),
      audience,
      scope,
      client_id,
      client_secret: Cypress.env('auth_client_secret'),
    },
  }

  cy.request(options).then(({ body }) => {
    const claims = jwt.decode(body.id_token)
    const { nickname, name, picture, updated_at, sub, exp } = claims
    const { access_token, id_token, token_type, expires_in, refresh_token } =
      body

    const item = {
      body: {
        access_token,
        audience,
        client_id,
        id_token,
        oauthTokenScope: scope,
        expires_in,
        refresh_token,
        scope,
        token_type,
        decodedToken: {
          claims,
          user: {
            nickname,
            name,
            picture,
            updated_at,
            sub,
          },
        },
      },
      expiresAt: exp,
    }

    window.localStorage.setItem(
      `@@auth0spajs@@::${Cypress.env('auth_client_id')}::${Cypress.env(
        'auth_audience',
      )}::openid email profile offline_access`,
      JSON.stringify(item),
    )
  })
})

This command makes a request to get a token, which is later decoded and stored in localstorage.

2 - You need to have Auth0 cache location set to 'localstorage' 3 - Just execute login before each test suit and persist the localStorage:

  before(() => {
    cy.A0login()
    cy.visit('/')
    cy.saveLocalStorage()
  })

  beforeEach(() => {
    cy.restoreLocalStorage()
  })

  afterEach(() => {
    cy.saveLocalStorage()
  })

In my case cy.saveLocalStorage() and cy.restoreLocalStorage() are both custom commands.

The only problem you might find is that this authentication is via 'username-password', but thats not a big issue If you just want to test functionality of your app and components.

Javier
  • 428
  • 5
  • 12
  • 2
    This looks like the "actually use Auth0" method, rather than the requested "intercept auth0 authentication so we can simulate the user logging in" method. Am I wrong? – Jonathan Tuzman Mar 17 '23 at 16:29