DEV Community

Lynn Romich
Lynn Romich

Posted on • Originally published at lynn.zone

E2E Testing an App with Clerk Authentication in Cypress

Background: Clerk is a hosted authentication and user management product.


I recently started writing E2E tests in Cypress for an app that uses Clerk for authentication, and there wasn’t anything out there to guide me, so here’s what I ended up with after fiddling with it for a bit.

(Note: In my case, this is a Next.js app using Clerk’s Next.js SDK, but my understanding is that this code will work everywhere, because their client SDKs all ultimately use ClerkJS under the hood.)

I wrote a custom Cypress command that waits for Clerk to load, signs the user out if they aren’t signed out already, and then signs in with test credentials (see here for how you can set these so that they’re accessible via Cypress.env()).

Cypress.Commands.add(`initializeAuth`, () => {
  cy.log(`Initializing auth state.`)

  cy.visit(`/`)

  cy.window()
    .should(window => {
      expect(window).to.not.have.property(`Clerk`, undefined)
      expect(window.Clerk.isReady()).to.eq(true)
    })
    .then(async window => {
      await window.Clerk.signOut()
      await window.Clerk.client.signIn.create({
        identifier: Cypress.env(`TEST_USER_IDENTIFIER`),
        password: Cypress.env(`TEST_USER_PASSWORD`),
      })
    })
})
Enter fullscreen mode Exit fullscreen mode

If you’re using TypeScript to write your tests (which I recommend!), you’ll also want to add this command to your custom command types.

declare global {
  namespace Cypress {
    interface Chainable {
      /**
       * Initialize auth to a state where you're logged in as the test user.
       * @example cy.initializeAuth()
       */
      initializeAuth(): Chainable<void>
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Ultimately, you’ll probably want to use this command in a before or beforeEach hook to reset the auth state before every test, like so:

describe(`Test Page`, () => {
  beforeEach(() => {
    cy.resetDatabase() // another custom command
    cy.initializeAuth()
  })

  // ... tests go here
})
Enter fullscreen mode Exit fullscreen mode

Happy testing! Please let me know if you run into problems with this approach.

Discussion (0)