# Reuse auth state across tests

Playwright executes tests in isolated environments called browser contexts. Because each test case runs in a new browser context, the user session is not shared between test cases by default. However, tests can load existing authenticated state.

This guide demonstrates how to save the auth state globally and load it in your test cases, eliminating the need to authenticate in every test and speeding up test execution. Visit the [Playwright docs about authentication](https://playwright.dev/docs/auth) for more information.

> See the [demo repo](https://github.com/clerk/clerk-playwright-nextjs) that demonstrates testing a Clerk-powered application using [Testing Tokens](https://clerk.com/docs/guides/development/testing/overview.md#testing-tokens). To run the tests, you'll need dev instance Clerk API keys and have **Email** and **Password** authentication enabled in the Clerk Dashboard. A test user is created automatically during setup.

1. ## Create a storage directory

   Create a `playwright/.clerk` directory and add it to your `.gitignore`. Once the auth state is generated, it will be stored to a file in this directory. Later on, tests will reuse this state and start already authenticated.

   filename: terminal

   ```sh
   mkdir -p playwright/.clerk
   echo $'\nplaywright/.clerk' >> .gitignore
   ```
2. ## Prepare auth state for your tests

   Authenticate and save the auth state in your [global setup file](https://playwright.dev/docs/test-global-setup-teardown).

   This file:

   - Is executed before all projects.
   - Calls [`clerkSetup()`](https://clerk.com/docs/guides/development/testing/playwright/overview.md#configure-playwright-with-clerk) to configure Playwright with Clerk.
   - Calls `clerk.signIn()` with the `emailAddress` parameter to sign in a test user. This approach uses a server-side token and works regardless of your instance's verification or MFA settings. See the [reference](https://clerk.com/docs/guides/development/testing/playwright/test-helpers.md#clerk-sign-in) for more information about the different parameters you can pass.
   - Checks if the user can access a protected page to ensure the user is successfully authenticated.
   - Stores the auth state in the storage file.

   filename: global.setup.ts

   ```tsx
   import { clerk, clerkSetup } from '@clerk/testing/playwright'
   import { test as setup } from '@playwright/test'
   import path from 'path'

   // Setup must be run serially
   setup.describe.configure({ mode: 'serial' })

   // Configure Playwright with Clerk
   setup('global setup', async ({}) => {
     await clerkSetup()
   })

   // Define the path to the storage file, which is `user.json`
   const authFile = path.join(__dirname, '../playwright/.clerk/user.json')

   setup('authenticate and save state to storage', async ({ page }) => {
     // Sign in using the emailAddress parameter, which creates a
     // server-side token and bypasses all verification steps
     await page.goto('/')
     await clerk.signIn({
       page,
       emailAddress: process.env.E2E_CLERK_USER_EMAIL!,
     })
     await page.goto('/protected')
     // Ensure the user has successfully accessed the protected page
     // by checking an element on the page that only the authenticated user can access
     await page.waitForSelector("h1:has-text('This is a PROTECTED page')")

     await page.context().storageState({ path: authFile })
   })
   ```

   > Use a `+clerk_test` email address for your test user (e.g., `e2e+clerk_test@example.com`) so Clerk suppresses all email delivery, including verification codes and "new device" sign-in notifications. The [demo repo](https://github.com/clerk/clerk-playwright-nextjs) demonstrates auto-creating a test user with this pattern in global setup.
3. ## Load the stored auth state in your tests

   You can either load the stored auth state [in the config](#in-the-config) or directly [in a test file](#in-a-test-file). Loading in the config is useful if you want to authenticate once and reuse the same auth state for all tests or groups of tests. Loading in a test file is useful if you want to authenticate for a specific test case.
4. ### In the config

   In your `playwright.config.ts`, create a `global setup` project and declare it as a [dependency](https://playwright.dev/docs/test-projects#dependencies) for all your testing projects. This means that the `global setup` project will always run before all the tests, and because it's where you prepared auth state, it will authenticate before all the tests. All testing projects should use the authenticated state as `storageState`.

   filename: playwright.config.ts

   ```tsx
   // ...
   projects: [
     {
       name: 'global setup',
       testMatch: /global\.setup\.ts/,
     },
     {
       name: 'Main tests',
       testMatch: /.*app.spec.ts/,
       use: {
         ...devices['Desktop Chrome'],
       },
       dependencies: ['global setup'],
     },
     {
       name: 'Authenticated tests',
       testMatch: /.*authenticated.spec.ts/,
       use: {
         ...devices['Desktop Chrome'],

         // Use prepared Clerk auth state
         storageState: 'playwright/.clerk/user.json',
       },
       dependencies: ['global setup'],
     },
   ]
   ```
5. ### In a test file

   To use the stored auth state in a test file, see the following example:

   filename: authenticated.spec.ts

   ```tsx
   import { test } from '@playwright/test'

   // Use prepared Clerk auth state
   test.use({ storageState: 'playwright/.clerk/user.json' })

   test('user test', async ({ page }) => {
     // page is authenticated
   })
   ```

For more information, feedback, or issues, visit the [`@clerk/testing`](https://github.com/clerk/javascript/tree/main/packages/testing) package.

---

## Sitemap

[Overview of all docs pages](https://clerk.com/docs/llms.txt)
