Setup test user and environment
Testing
Testing authenticated features efficiently requires a different approach than testing authentication flows. Instead of signing in for every test, you can authenticate once, save the authentication state, and reuse it across multiple tests. This significantly speeds up your test suite while maintaining test isolation.
Most browser automation tools support saving browser state (cookies, localStorage, sessionStorage) after authentication:
cy.session() to cache authentication statestorageState to save and restore browser context stateOnce saved, authentication state can be restored before each test:
This approach provides:
Use authenticated feature testing when:
The typical pattern for testing authenticated features follows these steps:
Authenticate once and save the state:
Cypress pattern:
Cypress.Commands.add('login', () => { cy.session('user', () => { // Perform authentication cy.visit('/') cy.get('[data-testid="sign-in-button"]').click() // ... complete sign-in flow })})Playwright pattern:
// Setup project runs oncesetup('authenticate', async ({ page }) => { await page.goto('/') await page.click('[data-testid="sign-in-button"]') // ... complete sign-in flow await page.context().storageState({ path: 'auth/user.json' })})Restore the saved state before each test:
Cypress:
beforeEach(() => { cy.login() // Restores cached session})Playwright:
// Configured in playwright.config.tsuse: { storageState: 'auth/user.json'}Write tests that assume authentication is already complete:
it('user can view dashboard', () => { cy.visit('/dashboard') // No login required - already authenticated cy.get('[data-testid="dashboard-content"]').should('be.visible')})Use one test user for all authenticated feature tests:
// Setup oncebeforeEach(() => { cy.login() // Uses same user for all tests})
// All tests use the same authenticated userit('can view dashboard', () => { /* ... */ })it('can update profile', () => { /* ... */ })Use different users for different test scenarios:
// Different users for different rolesbeforeEach(() => { cy.login('admin') // or cy.login('user')})
it('admin can access admin panel', () => { /* ... */ })Authenticate only when needed:
it('public page works without auth', () => { cy.visit('/public') // No authentication needed})
it('protected page requires auth', () => { cy.login() cy.visit('/dashboard') // Authentication required})data-testid attributes on HTML elements instead of CSS classescy.origin() in Cypress or handle redirects properly in PlaywrightTest authenticated features with: