[Bug]: methods fill()/press()/type() doesn't wait element to be focusable, when element inside inert container
Author: msgoloborodovCreated Sep 28, 2026Updated Sep 28, 2026
Version
1.60.0
Steps to reproduce
import { expect, test } from '@playwright/test';
test.describe('locator.fill() silently does nothing inside [inert] container', () => {
test.beforeEach(async ({ page }) => {
await page.setContent(`
<div inert id="locker">
<input id="target">
</div>
<input id="outside">
`);
});
test('fill() resolves successfully but the input stays empty', async ({ page }) => {
const target = page.locator('#target');
// All fill() actionability checks pass although the element is inert:
// visible / enabled / editable do not consider the inert attribute
// (aria-disabled="true" on the container would make "enabled" fail).
await expect(target).toBeVisible();
await expect(target).toBeEnabled();
await expect(target).toBeEditable();
// This resolves WITHOUT any error...
await target.fill('hello');
// ...but the value is silently dropped: injected fill does
// input.focus() (silently fails inside inert subtree), then
// Input.insertText goes to the actual focused element (<body>),
// and dom.ts returns 'done' without verifying element.value.
await expect(target).toHaveValue('');
});
test('contrast: click() on the same element waits and times out', async ({ page }) => {
const target = page.locator('#target');
// click() is properly blocked: the browser hit-testing skips inert
// subtrees, so the hit-target check keeps failing.
await expect(target.click({ timeout: 3_000 })).rejects.toThrow(/timeout/i);
});
test('contrast: press() sends keystrokes to an unrelated focused element', async ({ page }) => {
const target = page.locator('#target');
const outside = page.locator('#outside');
await outside.focus();
// press() = actionability checks + focus() + key press.
// The focus() call silently fails (inert), so the keystroke
// lands in whatever was focused before — a field outside the locker.
await target.press('a');
await expect(target).toHaveValue('');
await expect(outside).toHaveValue('a');
});
test('contrast: the same input inside [aria-disabled] container is properly waited on', async ({ page }) => {
await page.setContent(`
<div aria-disabled="true" id="locker">Source: microsoft/playwright