Keyboard Testing Guide
How to Test Linear Keyboard Shortcuts with Playwright: Complete 2026 Guide
A scenario-by-scenario walkthrough of testing Linear's keyboard shortcuts with Playwright. Command palette (Cmd+K), focus traps, issue creation shortcuts, view switching, bulk actions, and the pitfalls that break real keyboard navigation test suites.
“Linear is used by over 10,000 companies including Vercel, Coinbase, and Ramp, and keyboard-first navigation is a core design principle that drives the majority of power user workflows.”
Linear Command Palette Interaction Flow
1. Why Testing Linear Keyboard Shortcuts Is Harder Than It Looks
Linear built its interface around keyboard-first navigation. Every major action, from creating an issue to switching views to moving issues across statuses, has a dedicated keyboard shortcut. The command palette alone surfaces hundreds of actions behind a single Cmd+K (or Ctrl+K on Windows/Linux) binding. This design philosophy makes Linear extraordinarily productive for power users, but it creates a testing surface that goes far beyond simple click-based flows.
The first structural challenge is focus management. Linear uses focus traps extensively: when you open the command palette, a modal, or the issue creation dialog, keyboard events are captured by that overlay and prevented from reaching the underlying page. Your Playwright test must verify that focus moves into the trap when the overlay opens and returns to the correct element when the overlay closes. If your test sends a keystroke while focus is in the wrong container, the shortcut silently does nothing and your assertion fails with no useful error message.
The second challenge is sequential key bindings. Linear uses two-key sequences for navigation: pressing G then I navigates to the inbox, G then V goes to views, G then M opens my issues. These are not simultaneous modifier combinations; they are sequential keystrokes with a timing window. If your test sends both keys in the same event or waits too long between them, the sequence fails. Playwright's keyboard.press API handles single keys well, but sequential shortcuts require careful ordering and timing.
The third challenge is animation and transition state. Linear uses smooth animations for palette open/close, view transitions, and panel slides. A shortcut that triggers a view change may take 200 to 400 milliseconds to complete its animation before the target content is interactive. Asserting too early catches the animation mid-flight; asserting too late wastes CI time. The fourth challenge is context sensitivity: the same key does different things depending on what is focused. Pressing Enter on an issue list item opens that issue; pressing Enter inside the command palette executes the selected command; pressing Enter in a text field inserts a newline. Your tests must account for this context dependency explicitly.
Why Keyboard Shortcut Testing Is Complex
Focus Context
Which element is focused?
Key Dispatch
Browser fires keydown event
Event Capture
Focus trap intercepts?
Shortcut Match
Single key or sequence?
Animation
200-400ms transition
State Change
DOM updates after animation
2. Setting Up Your Linear Test Environment
Before writing keyboard shortcut tests, you need a reproducible Linear workspace with predictable data. Linear offers a robust API that lets you create and tear down test data programmatically. The goal is to start each test run with a known set of teams, projects, issues, and views so that keyboard navigation lands on predictable targets.
Environment Variables
The API key should belong to a dedicated test user account in a sandbox workspace. Never run keyboard shortcut tests against your production workspace; the bulk selection and issue creation scenarios will generate real issues and status changes.
Playwright Configuration
Setting fullyParallel: false is important for keyboard shortcut tests. Many shortcuts change application state (creating issues, switching views) and running them in parallel leads to unpredictable focus contexts. Run them sequentially within the keyboard-shortcuts project and parallelize at the project level instead.
Authentication Setup
Test Environment Setup Flow
Install Browsers
npx playwright install
Authenticate
Save session state
Seed Data
Create issues via API
Run Tests
Keyboard shortcut suite
Teardown
Delete test issues
Command Palette (Cmd+K) Search and Execute
Complex3. Command Palette (Cmd+K) Search and Execute
The command palette is Linear's most powerful keyboard feature. Pressing Cmd+K (or Ctrl+K) opens a search overlay that filters across issues, projects, views, teams, and actions as you type. The palette uses a focus trap: once open, all keyboard input goes to the palette search field. Arrow keys navigate the result list, Enter executes the selected result, and Escape closes the palette. Testing this flow requires verifying the focus trap activates on open, search filtering works correctly, keyboard navigation within results is functional, and focus returns to the previous element on close.
The critical assertion here is the focus trap verification. When the palette opens, searchInput must be focused immediately. If your test sends keystrokes before the focus trap activates, those keystrokes go to the underlying page and trigger unintended shortcuts. The toHaveAttribute('aria-selected', 'true') check on arrow navigation confirms that Linear's listbox correctly tracks the active descendant as the user navigates with arrow keys.
Command Palette: Playwright vs Assrt
import { test, expect } from '@playwright/test';
test('Cmd+K palette search', async ({ page }) => {
await page.goto('/');
await page.waitForLoadState('networkidle');
await page.keyboard.press('Meta+k');
const palette = page.getByRole('dialog').filter({
has: page.getByPlaceholder(/search/i),
});
await expect(palette).toBeVisible();
const input = palette.getByRole('combobox');
await expect(input).toBeFocused();
await input.fill('Create issue');
const results = palette.getByRole('option');
await expect(results.first()).toContainText(/create/i);
await page.keyboard.press('ArrowDown');
await page.keyboard.press('Enter');
await expect(palette).not.toBeVisible();
});Quick Issue Creation with C Shortcut
Moderate4. Quick Issue Creation with C Shortcut
Pressing C anywhere in Linear (when not inside a text field) opens the new issue creation dialog. This is a modal with a focus trap: the title field receives immediate focus, Tab cycles through the form fields (description, assignee, priority, status, labels), and Cmd+Enter submits the issue. The challenge for testing is ensuring the C key triggers the dialog only when focus is not inside an input or textarea. If your test sends C while an issue title is focused, it types the letter “c” instead of opening the creation dialog.
The second test is just as important as the first. It validates that Linear correctly distinguishes between a shortcut keystroke and a text input keystroke. This context-sensitivity is one of the most common sources of flaky keyboard tests. If your test framework does not properly clear focus between scenarios, a stale text input focus can cause the C shortcut to fail silently.
Issue Creation: Playwright vs Assrt
test('C shortcut creates issue', async ({ page }) => {
await page.goto('/');
await page.waitForLoadState('networkidle');
await page.getByRole('main').click();
await page.keyboard.press('c');
const dialog = page.getByRole('dialog').filter({
has: page.getByPlaceholder(/issue title/i),
});
await expect(dialog).toBeVisible();
const titleInput = dialog.getByPlaceholder(/issue title/i);
await expect(titleInput).toBeFocused();
await titleInput.fill('Test issue from Playwright');
await page.keyboard.press('Meta+Enter');
await expect(dialog).not.toBeVisible();
});View Switching with Number Keys
Moderate5. View Switching with Number Keys
Linear assigns number keys 1 through 5 to switch between issue grouping and sorting views within the current list. Pressing 1 shows the default grouping, 2 switches to grouping by assignee, 3 groups by priority, and so on. These shortcuts only work when focus is on the issue list, not inside a modal or text input. The testing challenge is verifying that the view actually changes after the keypress, which requires waiting for the DOM to re-render with the new grouping structure.
The waitForTimeout(400) call handles the view transition animation. In production tests, you should replace this with a more robust wait condition, such as waiting for the new group headers to appear. The timeout approach works for initial development but becomes a source of flakiness in CI environments with variable performance. A better pattern is to use expect().toBeVisible() with a sufficient timeout, letting Playwright auto-retry until the element appears.
Focus Trap Navigation in Modals and Panels
Complex6. Focus Trap Navigation in Modals and Panels
Linear uses focus traps in multiple contexts: the command palette, issue creation dialog, issue detail side panel, settings modals, and filter dropdowns. A focus trap captures Tab and Shift+Tab keystrokes to cycle focus within the trapped container, preventing keyboard users from accidentally interacting with elements behind the overlay. Testing focus traps requires three distinct verifications: (1) focus enters the trap when the container opens, (2) Tab cycles within the trap boundaries without escaping, and (3) focus returns to the trigger element when the container closes.
The focus cycling test is the most important verification. A broken focus trap lets keyboard users escape the modal and interact with hidden content, which is both an accessibility violation (WCAG 2.4.3) and a functional bug. The page.evaluateapproach to check focus containment is necessary because Playwright's toBeFocused() only checks a single known element, while the focus trap test needs to verify that focus remains within a container regardless of which specific element is focused.
Bulk Selection with Shift and X Shortcuts
Moderate7. Bulk Selection with Shift and X Shortcuts
Linear supports selecting multiple issues for bulk operations. Pressing X on a focused issue toggles its selection. Holding Shift and clicking (or pressing Shift+ArrowDown) extends the selection range. Once multiple issues are selected, a bulk action toolbar appears at the bottom of the screen, offering status changes, assignee updates, label additions, and deletion. Testing this requires verifying selection state across multiple list items and confirming the toolbar appears with the correct count.
Bulk selection tests are particularly sensitive to list ordering. If your test data is not seeded with deterministic sort order, ArrowDown may land on different issues between runs. Always seed your test workspace with issues that have explicit priority and creation timestamps so the default sort order is predictable.
9. Common Pitfalls That Break Keyboard Shortcut Tests
Keyboard shortcut testing in browser automation has well-documented failure modes. These pitfalls come from real issue trackers, community forums, and the Playwright GitHub repository. Each one has caused production test suites to fail intermittently or pass falsely.
Pitfalls to Watch For
- Sending shortcuts before the page is fully interactive. Linear's JavaScript must finish hydrating before keyboard event listeners are registered. Use waitForLoadState('networkidle') or wait for a specific interactive element.
- Forgetting to clear focus from text inputs before testing single-key shortcuts. Pressing C while a textarea is focused types the letter instead of opening the issue dialog. Always click on a non-input element first.
- Using page.keyboard.type() for shortcuts instead of page.keyboard.press(). The type() method simulates typing each character sequentially, which does not trigger modifier-based shortcuts like Cmd+K correctly. Always use press() for shortcuts.
- Testing sequential shortcuts (G then I) with page.keyboard.press('g+i') as a single combination. These are two separate key events, not a simultaneous combination. Send them as separate press() calls with a small delay between.
- Asserting DOM state during view transition animations. Linear animates view changes over 200 to 400 milliseconds. Asserting during the animation catches stale or transitional DOM. Use Playwright's auto-retry assertions with appropriate timeouts.
- Running keyboard shortcut tests in parallel. Shortcuts change global application state (navigation, issue creation, view switching). Parallel execution means one test's state change affects another test's focus context. Use fullyParallel: false.
- Not verifying focus restoration after modal close. When a dialog closes, focus should return to the element that triggered it. If focus lands on document.body, subsequent shortcut tests will fail because the keyboard context is undefined.
- Hardcoding waitForTimeout instead of using auto-retry assertions. Fixed delays make tests slow in fast environments and flaky in slow ones. Replace waitForTimeout(500) with expect(element).toBeVisible({ timeout: 2000 }) wherever possible.
The focus management pitfalls (items 2 and 7) are the most frequently reported issues in keyboard shortcut test suites. When a test fails with “element not found” or “action not triggered,” the root cause is almost always that focus was in an unexpected location. Adding a page.evaluate(() => document.activeElement) debug log before each shortcut press reveals the focus context and makes these failures immediately diagnosable.
Pre-flight Checklist for Each Test
- Verify the page has finished loading (networkidle or specific element visible)
- Confirm focus is not inside a text input or textarea
- Check that no modal or overlay is blocking keyboard events
- Ensure the test user has the correct workspace permissions
- Validate that test seed data (issues, views) exists before asserting navigation targets
- Use Meta+k (not Control+k) on macOS, or parameterize the modifier key per platform
10. Writing These Scenarios in Plain English with Assrt
Every scenario above required careful attention to focus context, timing, animation delays, and DOM structure. Assrt lets you express the same test intent in plain English. The compiler handles focus management, wait conditions, and selector strategies automatically. Here is the command palette scenario from Section 3 and the navigation shortcut from Section 8 expressed as an Assrt file:
Assrt compiles each scenario block into the same Playwright TypeScript you saw in the preceding sections. The compiled output is committed to your repository as real test files you can read, run, and modify. When Linear updates its UI (renaming buttons, changing dialog structure, or adjusting animation timings), Assrt detects the failure, analyzes the new DOM, and opens a pull request with updated locators and wait conditions. Your scenario files stay untouched.
Start with the command palette test. Once it passes in your CI, add the issue creation shortcut, then the view switching tests, then navigation sequences, then bulk selection, then focus trap verification. In a single afternoon you can have comprehensive keyboard shortcut coverage that most Linear integrations never achieve by hand.
Related Guides
How to Test Airtable Form Embed
Step-by-step guide to testing embedded Airtable forms with Playwright. Covers iframe...
How to Test Copy Button
Step-by-step guide to testing code block copy buttons with Playwright. Clipboard API...
How to Test Combobox Multiselect
A practical guide to testing combobox multiselect components with Playwright. Covers...
Ready to automate your testing?
Assrt discovers test scenarios, writes Playwright tests from plain English, and self-heals when your UI changes.