Copy-paste, keyboard shortcuts, right-click context menus, double-click to edit, Ctrl+Click to multi-select. Real users do not just click buttons and fill forms. They use the keyboard and mouse in complex ways. Playwright gives you full control over both.
import { test, expect } from '@playwright/test';
test('keyboard shortcuts', async ({ page }) => {
await page.goto('/topics/forms');
const textbox = page.getByRole('textbox', { name: 'Notes' });
await textbox.click();
// Type text character by character (triggers keydown/keyup events)
await page.keyboard.type('Hello World');
// Select all with Ctrl+A (Cmd+A on Mac)
await page.keyboard.press('Control+a');
// Copy with Ctrl+C
await page.keyboard.press('Control+c');
// Move to another field and paste
await page.getByRole('textbox', { name: 'Summary' }).click();
await page.keyboard.press('Control+v');
await expect(page.getByRole('textbox', { name: 'Summary' })).toHaveValue('Hello World');
});
test('pressing individual keys', async ({ page }) => {
await page.goto('/topics/forms');
// Press Enter to submit
await page.getByLabel('Search').fill('playwright');
await page.keyboard.press('Enter');
// Press Escape to close a modal
await page.keyboard.press('Escape');
// Press Tab to move focus
await page.keyboard.press('Tab');
// Press arrow keys for navigation
await page.keyboard.press('ArrowDown');
await page.keyboard.press('ArrowDown');
await page.keyboard.press('Enter');
});import { test, expect } from '@playwright/test';
test('modifier key combinations', async ({ page }) => {
await page.goto('/topics/tables');
// Shift+Click to select a range
await page.getByRole('row').nth(1).click();
await page.getByRole('row').nth(5).click({ modifiers: ['Shift'] });
// Ctrl+Click to multi-select (Cmd+Click on Mac)
await page.getByRole('row').nth(3).click({ modifiers: ['Control'] });
await page.getByRole('row').nth(7).click({ modifiers: ['Control'] });
// Alt+Click for special behavior
await page.getByRole('cell', { name: 'Details' }).click({ modifiers: ['Alt'] });
});import { test, expect } from '@playwright/test';
test('right-click context menu', async ({ page }) => {
await page.goto('/topics/tables');
// Right-click to open context menu
await page.getByRole('row').nth(1).click({ button: 'right' });
// Interact with context menu
await expect(page.getByRole('menu')).toBeVisible();
await page.getByRole('menuitem', { name: 'Edit' }).click();
});
test('double-click to edit', async ({ page }) => {
await page.goto('/topics/tables');
// Double-click a cell to make it editable
await page.getByRole('cell', { name: 'John Doe' }).dblclick();
// Now the cell is an input -- type new value
await page.getByRole('cell', { name: 'John Doe' }).getByRole('textbox').fill('Jane Doe');
await page.keyboard.press('Enter');
await expect(page.getByRole('cell', { name: 'Jane Doe' })).toBeVisible();
});
test('click at specific coordinates', async ({ page }) => {
await page.goto('/topics/canvas');
const canvas = page.locator('canvas');
const box = await canvas.boundingBox();
if (!box) throw new Error('Canvas not found');
// Click at specific position relative to the element
await canvas.click({ position: { x: 100, y: 50 } });
// Or use absolute coordinates
await page.mouse.click(box.x + 100, box.y + 50);
});| Action | Code | Use Case |
|---|---|---|
| Type text | keyboard.type('text') | Simulates keystrokes, triggers events |
| Press key | keyboard.press('Enter') | Submit forms, close modals |
| Key combination | keyboard.press('Control+a') | Select all, copy, paste, undo |
| Hold key down | keyboard.down('Shift') | Hold modifier while clicking |
| Release key | keyboard.up('Shift') | Release held modifier |
| Right-click | click({ button: 'right' }) | Open context menus |
| Double-click | dblclick() | Edit cells, select words |
| Click with modifier | click({ modifiers: ['Control'] }) | Multi-select, open in new tab |
| Click at position | click({ position: { x, y } }) | Canvas, maps, charts |
On macOS, use 'Meta' instead of 'Control' for Cmd key. But in most tests, just use 'Control' -- Playwright automatically maps it to Cmd on Mac. Exception: if your app explicitly checks for Meta vs Control, use 'Meta' for macOS-specific shortcuts.
Q: How do you simulate keyboard shortcuts in Playwright?
A: I use page.keyboard.press() with key combinations like 'Control+a', 'Control+c', 'Control+v'. For individual keys, keyboard.press('Enter'), keyboard.press('Escape'), keyboard.press('Tab'). For typing text character by character (needed for auto-suggest), I use keyboard.type(). For modifier clicks, I pass modifiers to the click method: click({ modifiers: ['Shift'] }). For right-click, click({ button: 'right' }). For double-click, dblclick(). The key difference between keyboard.type() and fill(): type() triggers individual key events, fill() sets the value instantly.
Key Point: keyboard.press() for shortcuts, keyboard.type() for character-by-character input, click({ button: 'right' }) for context menus, dblclick() for double-click. Use fill() for regular form input.