O Playwright tem uma API direta para cookies via objeto context, mas o localStorage exige page.evaluate(() => localStorage.getItem('key')) porque não existe um método no estilo de locator para storage. Os dois importam para testes de autenticação: storageState captura cookies e localStorage juntos em um arquivo para que cada teste possa começar já logado sem tocar na UI de login.
Lendo cookies
import { test, expect } from '@playwright/test';
test('login define cookie de sessão', async ({ page, context }) => {
await page.goto('/login');
await page.getByLabel('Email').fill('user@example.com');
await page.getByLabel('Password').fill('password123');
await page.getByRole('button', { name: 'Log in' }).click();
await expect(page).toHaveURL('/dashboard');
// Lê todos os cookies da página atual
const cookies = await context.cookies();
const sessionCookie = cookies.find(c => c.name === 'session_token');
expect(sessionCookie).toBeDefined();
expect(sessionCookie!.httpOnly).toBe(true); // Não pode ser lido por JS — bom
expect(sessionCookie!.secure).toBe(true); // Só enviado via HTTPS
expect(sessionCookie!.sameSite).toBe('Strict');
});context.cookies() retorna todos os cookies de todas as páginas no contexto atual. Filtre por name, domain ou path conforme necessário.
Definindo cookies
Pré-popule cookies antes de navegar: útil para testar estados autenticados sem passar pelo fluxo de login.
test('usuário autenticado vê o dashboard', async ({ page, context }) => {
// Define o cookie de auth diretamente — pula a UI de login
await context.addCookies([{
name: 'session_token',
value: 'valid-test-token-abc123',
domain: 'localhost',
path: '/',
httpOnly: true,
secure: false, // false para localhost
sameSite: 'Lax',
}]);
await page.goto('/dashboard');
await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();
});storageState — captura cookies E localStorage em um único arquivo. A injeção manual de cookies é útil quando você precisa de controle preciso sobre atributos individuais do cookie.Limpando cookies
// Limpa todos os cookies do contexto
await context.clearCookies();
// Para limpar um cookie específico, a maioria dos apps tem um endpoint /logout
// que limpa o cookie de sessão no servidor
await page.goto('/logout');Testando comportamento de expiração de cookie
test('sessão expirada redireciona para login', async ({ page, context }) => {
// Define um cookie expirado
const ontem = new Date(Date.now() - 86400000);
await context.addCookies([{
name: 'session_token',
value: 'expired-token',
domain: 'localhost',
path: '/',
expires: ontem.getTime() / 1000, // Unix timestamp em segundos
}]);
await page.goto('/dashboard');
await expect(page).toHaveURL('/login');
});Trabalhando com localStorage
O Playwright não tem uma API direta para localStorage: você acessa via page.evaluate().
// Ler localStorage
const theme = await page.evaluate(() => localStorage.getItem('theme'));
expect(theme).toBe('dark');
// Definir localStorage antes da interação com a página
await page.evaluate(() => {
localStorage.setItem('theme', 'dark');
localStorage.setItem('user_preferences', JSON.stringify({ fontSize: 'large' }));
});
// Limpar uma chave específica
await page.evaluate(() => localStorage.removeItem('theme'));
// Limpar todo o localStorage
await page.evaluate(() => localStorage.clear());Testando que o localStorage persiste preferências
test('preferência de modo escuro persiste após reload', async ({ page }) => {
await page.goto('/settings');
await page.getByRole('switch', { name: 'Dark mode' }).click();
// Verifica se foi armazenado
const stored = await page.evaluate(() => localStorage.getItem('theme'));
expect(stored).toBe('dark');
// Recarrega a página
await page.reload();
// Verifica se a preferência foi restaurada do localStorage
await expect(page.locator('html')).toHaveAttribute('data-theme', 'dark');
});Pré-populando localStorage
test('usuário com preferência de fonte grande vê texto maior', async ({ page }) => {
await page.goto('/'); // Navega primeiro para definir o domínio
await page.evaluate(() => {
localStorage.setItem('fontSize', 'large');
});
await page.reload(); // Recarrega para o app ler a preferência
const body = await page.locator('body');
await expect(body).toHaveCSS('font-size', '18px');
});sessionStorage
Mesma API do localStorage, escopo diferente: o sessionStorage é limpo quando a aba fecha.
// Ler sessionStorage
const cartItems = await page.evaluate(() => sessionStorage.getItem('cart'));
// Definir sessionStorage
await page.evaluate(() => {
sessionStorage.setItem('cart', JSON.stringify([{ id: 1, qty: 2 }]));
});Salvando e restaurando o estado completo do navegador
Para testes de autenticação em escala, capture todo o estado de storage (cookies + localStorage) em um arquivo:
// global-setup.ts — roda uma vez antes de todos os testes
import { chromium } from '@playwright/test';
async function globalSetup() {
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('http://localhost:3000/login');
await page.getByLabel('Email').fill('testuser@example.com');
await page.getByLabel('Password').fill('password123');
await page.getByRole('button', { name: 'Log in' }).click();
await page.waitForURL('/dashboard');
// Salva cookies + localStorage em arquivo
await page.context().storageState({ path: 'playwright/.auth/user.json' });
await browser.close();
}
export default globalSetup;Depois reutilize nos testes sem precisar logar:
// playwright.config.ts
projects: [{
name: 'authenticated',
use: { storageState: 'playwright/.auth/user.json' },
}],Esse é o padrão recomendado para suites de testes autenticados: mais rápido, mais confiável, e não depende da UI de login estar funcionando.
→ Veja também: Autenticação no Playwright com storageState (Sem Login em Cada Teste) | Isolamento de Testes: Por que Cada Teste Playwright Deve Ser sem Estado | Configuração e Limpeza Global no Playwright