Summary
BrowserPage.type() changes an input's value attribute but does not focus the control or dispatch keyboard and input events. Reactive forms therefore do not observe typing, even though the DOM value appears to change.
This differs from real user input and from Playwright's input APIs.
Reproduction
import { Browser } from 'very-happy-dom'
const page = new Browser().newPage()
page.content = '<body><input id="name"></body>'
const input = page.mainFrame.document.querySelector('#name')!
let inputEvents = 0
let changeEvents = 0
input.addEventListener('input', () => inputEvents++)
input.addEventListener('change', () => changeEvents++)
await page.type('#name', 'Ada')
console.log((input as HTMLInputElement).value) // Ada
console.log(inputEvents) // 0
console.log(changeEvents) // 0
console.log(page.mainFrame.document.activeElement === input) // falseConfirmed against main at 59d2e7c3 with Bun 1.4.1.
Expected behavior
type() should focus the target and dispatch a browser-like event sequence for each character, including keyboard events and an input event after the value changes. A separate fill() API would be useful for the faster Playwright behavior of focusing, replacing the value, and firing input once.
At minimum:
- The element becomes
document.activeElement. - Controlled/reactive forms receive
inputevents. - Keyboard handlers receive useful
keydown/keyupdata. - Disabled/read-only/non-editable targets fail clearly.
- Existing text selection/value behavior is defined.
Playwright distinguishes fill() from character-by-character keyboard input and documents the expected event-oriented behavior here: https://playwright.dev/docs/input
Related inconsistency
page.keyboard.press() dispatches events on document, not the focused element, and creates a generic Event with an assigned key. Bringing type(), keyboard.press(), and focus tracking under one interaction path would avoid divergent behavior.
Why this matters
Frameworks normally update state from input/keyboard events, not by polling attributes. Current tests can pass while the same form fails under real browser automation, which is exactly the class of false confidence a Playwright-compatible interaction layer should prevent.