JWT Auth Testing
JWT apps often store access tokens in localStorage or memory. Playwright tests can obtain tokens via API and inject them before navigation using addInitScript or storageState.
JWT Setup Patterns Preferred: POST to /auth/login with request, save response tokens into storageState-compatible localStorage via setup script.
Alternative: page.addInitScript(({ token }) => localStorage.setItem('access_token', token), { token }) before goto.
test.beforeEach(async ({ page, request }) => {
const res = await request.post('/api/auth/login', {
data: { email: 'test@example.com', password: 'pass' },
});
const { accessToken } = await res.json();
await page.addInitScript(token => {
localStorage.setItem('access_token', token);
}, accessToken);
await page.goto('/dashboard');
}); addInitScript runs before page scripts on each navigation.
API Authorization Header test.use({
extraHTTPHeaders: {
Authorization: `Bearer ${process.env.TEST_JWT}`,
},
}); extraHTTPHeaders apply to page navigation and request fixture. Test expired token by mocking time or using short TTL test JWT. Refresh token flows may need route mock for /auth/refresh. Never embed long-lived prod JWT in repo. JWT Testing Recipes Common JWT patterns.
Pattern Method Token in localStorage addInitScript + goto Bearer header only extraHTTPHeaders in config API gets token request.post login Expired token Inject expired JWT, expect logout Invalid signature Malformed token → 401 UI Refresh flow Mock refresh endpoint
storageState with JWT in localStorage // After UI or API login that writes localStorage:
await page.context().storageState({ path: '.auth/jwt-user.json' }); Common Mistakes Setting localStorage after goto — app already redirected to login. Hardcoded JWT that expires mid-suite in CI. Not testing token refresh or 401 handling. Confusing cookie session apps with JWT localStorage apps. Key Takeaways Obtain JWT via API; inject before navigation. addInitScript seeds localStorage reliably. Test expired and invalid token UX. Use env vars for signing secrets in test token generation.
Pro Tip
Ask backend for a /test/session endpoint (dev-only) that returns valid JWT — cleaner than parsing login HTML in E2E.
Storage State Go to next item