Playwright: Using Cognito to Log In for Your E2E Tests

Some time ago, I started looking for a better way to handle login in my E2E tests using Playwright.

At the time, I was using a setup test that executed a basic login flow (opening the app and entering a username and password). After that, I’d save the…


This content originally appeared on DEV Community and was authored by Renato O. Nunes

Some time ago, I started looking for a better way to handle login in my E2E tests using Playwright.

At the time, I was using a setup test that executed a basic login flow (opening the app and entering a username and password). After that, I’d save the storageState to a .json file and use it in my tests like this:

test.use({ storageState: './storage/userStorageState.json' });

There’s nothing particularly special about this setup. It's actually one of the recommended approaches in the Playwright documentation.

The issue I ran into was that, even though this login test only ran once at the start of the test suite, it still took some time. Since I have several tests that require different users, this delay became a bit annoying.

Another problem was that occasionally the storageState would become invalid, and I’d have to run the setup again.

At other companies, I used to handle this more efficiently: just make an API request, get the auth token, inject it into the session, and start testing. But in this case, the application needed a lot more than just a token, and some of it came from Cognito, and the rest had to be pulled from my backend.

So, if your app also uses Cognito and you're facing similar issues, the example below might be helpful:

After these changes, our login execution time dropped from over a minute to just 9 seconds. We had 8 users that needed to be authenticated before running the tests.

require('dotenv').config();
const { Auth } = require('aws-amplify');
const fs = require('fs');
const path = require('path');
const axios = require('axios');
const { getBaseURL } = require('./env-config');
const { getCognitoConfig } = require('./cognito-pull-config');
const users = require('./users-config');

async function loginCognitoSetup() {
  const { appURL, apiURL } = getBaseURL();

  const {user_pool_id, frontend_client_id} = getCognitoConfig();

  const awsconfig = {
    aws_user_pools_id: user_pool_id,
    aws_user_pools_web_client_id: frontend_client_id,
  };

  Auth.configure(awsconfig);

  const makeKey = (cognitoUser, name) =>
    `CognitoIdentityServiceProvider.${cognitoUser.pool.clientId}.${cognitoUser.username}.${name}`;

  for (const [key, { username, password }] of Object.entries(users)) {
    try {
      const cognitoUser = await Auth.signIn(username, password);

      const { data: cognitoMonolithUser } = await axios.get(
        `${apiURL}/api/cognitouser`,
        {
          headers: {
            Authorization: `Bearer ${cognitoUser.signInUserSession.idToken.jwtToken}`,
          },
        }
      );

      const storageState = {
        cookies: [],
        origins: [
          {
            origin: appURL,
            localStorage: [
              {
                name: makeKey(cognitoUser, 'idToken'),
                value: cognitoUser.signInUserSession.idToken.jwtToken,
              },
              {
                name: 'user',
                value: JSON.stringify(cognitoMonolithUser),
              },
              {
                name: 'isAuth',
                value: 'true',
              },
              {
                name: 'company',
                value: JSON.stringify(cognitoMonolithUser.company),
              },
              {
                name: 'tokens',
                value: JSON.stringify(cognitoUser.signInUserSession),
              },
              {
                name: makeKey(cognitoUser, 'refreshToken'),
                value: cognitoUser.signInUserSession.refreshToken.token,
              },
              {
                name: makeKey(cognitoUser, 'clockDrift'),
                value: '0',
              },
              {
                name: 'amplify-signin-with-hostedUI',
                value: 'false',
              },
              {
                name: makeKey(cognitoUser, 'accessToken'),
                value: cognitoUser.signInUserSession.accessToken.jwtToken,
              },
              {
                name: `CognitoIdentityServiceProvider.${cognitoUser.pool.clientId}.LastAuthUser`,
                value: cognitoUser.username,
              },
              {
                name: makeKey(cognitoUser, 'userData'),
                value: JSON.stringify(cognitoUser.attributes),
              },
            ],
          },
        ],
      };

      const fileName = `${key}StorageState.json`;

      const filePath = path.resolve(__dirname, '..', 'storage' , fileName);

      fs.writeFileSync(filePath, JSON.stringify(storageState, null, 2));
      console.log(`Storage created to ${key} (${username}) → ${fileName}`);
    } catch (error) {
      console.error(`Error to create the user ${username}:`, error.message);
    }
  }
}

module.exports = loginCognitoSetup;

⚠️ The attributes used in the code above were required for the specific app I was working with. That doesn't mean you'll need all of them, and depending on your setup, you might even need additional ones. That’s why it's crucial to understand exactly how your app manages authentication.

You’ll notice the code above expects some values from files, like appURL, apiURL, username, password, etc.

That’s because, in addition to handling Cognito logins, I also needed the project to support multiple environments. It might not be the most elegant solution out there, but it works and it’s fairly organized. ;)

At the ./config level, create a file called users-config.js, and inside it, add:

require('dotenv').config();

module.exports = {
  admin: {
    username: process.env.MY_USER,
    password: process.env.MY_PASS,
  }
};

Create another file in the same directory called env-config.js:

const environments = {
  automation: {
    app: 'https://localhost.com',
    api: 'https://api.locahost.com',
  }
};

function getBaseURL() {
  const ENV = process.env.NODE_ENV || 'dev';
  const config = environments[ENV];

  if (!config) {
    console.error(`Environment '${ENV}' not found!`);
    process.exit(1);
  }

  return {
    ENV,
    appURL: config.app,
    apiURL: config.api, 
  };
}

module.exports = { getBaseURL };

Once that's done, you just need to add the login-cognito-setup.js file as the setup script for your tests.

In your playwright.config.js file, add this line:

 {
   name: 'setup',
   testMatch: '**/*.cognito.js',
 },
 {
   name: 'e2e-tests',
   testMatch: '**/*.spec.js',
   dependencies: ['setup'],
 },

🔖 One thing to note: we didn’t need to change the test.use calls in our test files. That’s because we’re saving the new storageState to the same location as before, so everything continues to work as expected.

To run just the login setup:

 "test:login-setup": "NODE_ENV=local playwright test --project=setup --config=playwright.config.js"

To run login + tests:

 "test:local": "NODE_ENV=local playwright test --project=e2e-tests --config=playwright.config.js"


This content originally appeared on DEV Community and was authored by Renato O. Nunes


Print Share Comment Cite Upload Translate Updates
APA

Renato O. Nunes | Sciencx (2025-06-26T13:21:37+00:00) Playwright: Using Cognito to Log In for Your E2E Tests. Retrieved from https://www.scien.cx/2025/06/26/playwright-using-cognito-to-log-in-for-your-e2e-tests/

MLA
" » Playwright: Using Cognito to Log In for Your E2E Tests." Renato O. Nunes | Sciencx - Thursday June 26, 2025, https://www.scien.cx/2025/06/26/playwright-using-cognito-to-log-in-for-your-e2e-tests/
HARVARD
Renato O. Nunes | Sciencx Thursday June 26, 2025 » Playwright: Using Cognito to Log In for Your E2E Tests., viewed ,<https://www.scien.cx/2025/06/26/playwright-using-cognito-to-log-in-for-your-e2e-tests/>
VANCOUVER
Renato O. Nunes | Sciencx - » Playwright: Using Cognito to Log In for Your E2E Tests. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2025/06/26/playwright-using-cognito-to-log-in-for-your-e2e-tests/
CHICAGO
" » Playwright: Using Cognito to Log In for Your E2E Tests." Renato O. Nunes | Sciencx - Accessed . https://www.scien.cx/2025/06/26/playwright-using-cognito-to-log-in-for-your-e2e-tests/
IEEE
" » Playwright: Using Cognito to Log In for Your E2E Tests." Renato O. Nunes | Sciencx [Online]. Available: https://www.scien.cx/2025/06/26/playwright-using-cognito-to-log-in-for-your-e2e-tests/. [Accessed: ]
rf:citation
» Playwright: Using Cognito to Log In for Your E2E Tests | Renato O. Nunes | Sciencx | https://www.scien.cx/2025/06/26/playwright-using-cognito-to-log-in-for-your-e2e-tests/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.