A maioria dos testes Playwright não precisa de nada além de click() e fill(). Mas dropdowns ativados por hover, multi-seleção com Ctrl+click e implementações de drag que rastreiam eventos mousemove ao longo do caminho requerem as APIs de nível mais baixo keyboard e mouse. page.keyboard.type() dispara eventos keydown, keypress, keyup e input por caractere, o que importa para autocomplete e validação em tempo real que fill() ignora.
Eventos de teclado
Pressionamentos básicos de teclas
// Pressiona uma tecla
await page.keyboard.press('Enter');
await page.keyboard.press('Tab');
await page.keyboard.press('Escape');
await page.keyboard.press('ArrowDown');
// Combinações de modificador + tecla
await page.keyboard.press('Control+a'); // Selecionar tudo
await page.keyboard.press('Control+c'); // Copiar
await page.keyboard.press('Control+v'); // Colar
await page.keyboard.press('Shift+Tab'); // Tab reverso
await page.keyboard.press('Meta+k'); // Cmd+K no MacOs nomes das teclas seguem a especificação KeyboardEvent.key. Os mais comuns: 'Enter', 'Tab', 'Escape', 'Backspace', 'Delete', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Home', 'End', 'PageUp', 'PageDown', 'F1'–'F12'.
Digitando texto
// Digita no elemento com foco
await page.getByRole('searchbox').focus();
await page.keyboard.type('playwright testing');
// Digita com delay entre teclas (simula digitação real)
await page.keyboard.type('digitação lenta', { delay: 50 });keyboard.type() dispara eventos keydown, keypress, keyup e input para cada caractere. Isso importa para aplicações que lidam com teclas individuais (autocomplete, validação em tempo real, editores de texto rico).
Segurando teclas modificadoras
// Shift + click para selecionar um intervalo
await page.keyboard.down('Shift');
await page.getByRole('row').nth(5).click();
await page.keyboard.up('Shift');Testando navegação por teclado
Testar que seu app é acessível por teclado é tanto um requisito de acessibilidade quanto uma preocupação de QA:
test('modal fecha com Escape', async ({ page }) => {
await page.getByRole('button', { name: 'Open modal' }).click();
await expect(page.getByRole('dialog')).toBeVisible();
await page.keyboard.press('Escape');
await expect(page.getByRole('dialog')).not.toBeVisible();
});
test('dropdown navega com teclas de seta', async ({ page }) => {
await page.getByRole('combobox', { name: 'País' }).focus();
await page.keyboard.press('ArrowDown'); // Abre dropdown, seleciona primeiro
await page.keyboard.press('ArrowDown'); // Seleciona segundo
await page.keyboard.press('Enter'); // Confirma a seleção
await expect(page.getByRole('combobox', { name: 'País' })).toHaveValue('Brasil');
});Eventos de mouse
Variantes de clique
// Duplo clique
await page.getByRole('row').first().dblclick();
// Clique direito (menu de contexto)
await page.getByText('Documento.pdf').click({ button: 'right' });
await expect(page.getByRole('menuitem', { name: 'Download' })).toBeVisible();
// Clique em coordenadas específicas relativas ao elemento
await page.getByRole('slider').click({ position: { x: 10, y: 0 } });
// Clique segurando tecla modificadora
await page.getByRole('checkbox', { name: 'Item 3' }).click({ modifiers: ['Shift'] });Hover
// Hover para revelar tooltip ou dropdown
await page.getByRole('button', { name: 'Ajuda' }).hover();
await expect(page.getByRole('tooltip')).toBeVisible();
await expect(page.getByRole('tooltip')).toHaveText('Clique para documentação');
// Hover para revelar botão de ação oculto em linha de tabela
await page.getByRole('row', { name: 'Alice Johnson' }).hover();
await page.getByRole('button', { name: 'Editar' }).click();Movimento do mouse
// Move o mouse para coordenadas absolutas da página
await page.mouse.move(100, 200);
// Arrasta de uma posição para outra
await page.mouse.move(100, 200);
await page.mouse.down();
await page.mouse.move(300, 200, { steps: 10 }); // steps deixa mais suave
await page.mouse.up();O parâmetro steps em mouse.move() divide o movimento em pontos intermediários, o que importa para implementações de drag-and-drop que rastreiam eventos mousemove ao longo do caminho.
Drag-and-drop
Para drag-and-drop HTML5 padrão:
// Usando dragTo — abordagem mais simples
await page.getByText('Card A').dragTo(page.getByText('Coluna B'));
// Com posição específica dentro do alvo
await page.getByText('Arquivo.pdf').dragTo(page.locator('.upload-zone'), {
targetPosition: { x: 50, y: 50 },
});Para implementações customizadas de drag que usam eventos mousedown/mousemove/mouseup:
const source = page.getByTestId('draggable-card');
const target = page.getByTestId('drop-zone');
const sourceBounds = await source.boundingBox();
const targetBounds = await target.boundingBox();
await page.mouse.move(sourceBounds!.x + sourceBounds!.width / 2, sourceBounds!.y + sourceBounds!.height / 2);
await page.mouse.down();
await page.mouse.move(targetBounds!.x + targetBounds!.width / 2, targetBounds!.y + targetBounds!.height / 2, { steps: 20 });
await page.mouse.up();Scroll
// Rola a página
await page.mouse.wheel(0, 500); // Rola 500px para baixo
// Rola dentro de um elemento específico
await page.getByRole('log').hover();
await page.mouse.wheel(0, 300);
// Rola até o elemento (use antes de interagir com elementos fora da tela)
await page.getByTestId('submit-section').scrollIntoViewIfNeeded();Combinando teclado e mouse
Os padrões de interação mais realistas combinam os dois:
test('multi-seleciona itens com Ctrl+click', async ({ page }) => {
await page.goto('/files');
// Seleciona o primeiro item
await page.getByRole('row').nth(0).click();
// Ctrl+click para adicionar à seleção
await page.getByRole('row').nth(2).click({ modifiers: ['Control'] });
await page.getByRole('row').nth(4).click({ modifiers: ['Control'] });
// Deleta os itens selecionados
await page.keyboard.press('Delete');
await expect(page.getByRole('row')).toHaveCount(7); // Começou com 10, deletou 3
});Quando usar essas APIs
A maioria dos seus testes deve usar métodos de locator de alto nível (click(), fill(), selectOption()). Use as APIs de teclado e mouse quando:
- Testando atalhos de teclado ou acessibilidade
- Testando elementos de UI ativados por hover
- Testando interações de drag-and-drop
- Testando menus de contexto
- Testando editores de texto rico
- Simulando interações complexas de múltiplos steps
Eventos diretos de teclado e mouse são mais lentos e frágeis do que ações de alto nível. Use-os apenas quando a API de alto nível não conseguir expressar o que você precisa.
→ Veja também: Locators do Playwright: getByRole, getByLabel, getByText, getByTestId Comparados | Testes de Acessibilidade com Playwright: Verificações a11y Automatizadas | Upload e Download de Arquivos em Testes Playwright