At work, I’ve been migrating us over from Cypress to Playwright for end-to-end tests. In that time, we’ve enabled two-factor authentication functionality in our application for security.
These TOTP tokens are great for security but provide an additional challenge for testing.
While Playwright supports saving state, our application tokens have a short expiry. I needed to log in to our application, enter a one-time password, and test.
The logging-in part was easy. We created development environment credentials. But because 2fa is enabled in all environments, we still had the issue of needing a TOTP token.
Well, there is a way to use a Node.js package for generating tokens: Totp Generator. All you need is your private seed key to generate token values and pass it to the package to generate a valid TOTP token.
My global setup file looks like this:
import { chromium, FullConfig } from '@playwright/test'; import totp from 'totp-generator'; const token = totp('JVGEGDFGDBFSDFDHHGVCHGHDASDRWERRTY'); async function globalSetup(config: FullConfig) { const { baseURL, storageState } = config.projects[0].use; const browser = await chromium.launch(); const page = await browser.newPage(); await page.goto(baseURL!); await page.locator('input[name="loginEmail"]').fill('someemail@gmail.com'); await page.locator('input[name="loginPassword"]').fill('password!'); await page.locator('text=Sign In').click(); const twoFactorField = await page.locator('input[placeholder="Enter the 6-digit Code"]'); if (twoFactorField.isVisible()) { await twoFactorField.fill(token); await page.locator('button[name="loginButton"]').click(); } await page.context().storageState({ path: storageState as string }); await browser.close(); } export default globalSetup;
In this logic, we determine if we require an OTP, and if we do, we generate a token value to log in and perform our test. Most of the logic is the totp
import at the top and the function call.