Broken keyboard input implementation
If you do await page.keyboard.down("Alt"), then this keydown listener will fire:
document.addEventListener("keydown", (event) => {
console.log("keydown:");
console.log(event.key);
});
Incorrectly however, event.key will be "".
At this point, because there was not yet await page.keyboard.up("Alt"), when you do .click() on an element in the page, the click event property altKey should be true. But, incorrectly it's false.
This test passes when using Puppeteer:
https://github.com/jaydenseric/ruck/blob/aa068afa7f0630c4e3e8617b2936210c14815964/useOnClickRouteLink.test.mjs#L121-L126
Here is the source code being tested:
https://github.com/jaydenseric/ruck/blob/aa068afa7f0630c4e3e8617b2936210c14815964/useOnClickRouteLink.mjs#L31
But with Astral, the test incorrectly fails when it should pass.
Here is the relevant code in Astral vs Puppeteer:
https://github.com/lino-levan/astral/blob/0a4ed055bb33984e1efdc7d540f65735383ea434/src/keyboard.ts#L278-L287
https://github.com/puppeteer/puppeteer/blob/83449567c7013ae1c87c54e42501aa74575640d0/packages/puppeteer-core/src/cdp/Input.ts#L55-L82
@lino-levan what is a realistic expectation for when this bug might be resolved?
I can try to prioritize working on this today. Planning to take some time off work to get Astral into much better shape, both in terms of fixing issues and documentation.
Unfortunately, my test suit that passes with Puppeteer still doesn't pass with Astral v0.5.2:
// Test holding the alt key when clicking the link prevents a
// client side navigation…
await page.keyboard.down("Alt");
await page.locator('a[href="/b"]').click();
await page.keyboard.up("Alt");
assertStrictEquals(await browserPageUrl(page), urlPageA);
The assertion fails that a navigation did occur.
Do you think it's a bug with Astral, or do I need to use different capitalisation with "Alt" or something Astral specific?
Is there some way for you to write a keyboard testcase that I can work on passing?
Here's an example of a testcase in the codebase
Deno.test("Keyboard - tab navigation", async () => {
const browser = await launch();
const page = await browser.newPage();
await page.setContent(`
<!DOCTYPE html>
<html>
<body>
<input id="first" type="text" placeholder="First input">
<input id="second" type="text" placeholder="Second input">
<button id="button">Click me</button>
<textarea id="textarea">Text area</textarea>
<div id="focused"></div>
<script>
const focused = document.getElementById('focused');
document.addEventListener('focusin', (e) => {
if (e.target.id) {
focused.textContent = (focused.textContent || '') + e.target.id + ',';
}
});
</script>
</body>
</html>
`);
// Start with first input focused
const firstInput = await page.$("input#first");
assertExists(firstInput);
await firstInput.click();
// Press tab multiple times to move through elements
await page.keyboard.press("Tab");
await page.keyboard.press("Tab");
await page.keyboard.press("Tab");
// Check the focus order
const focusOrder = await page.evaluate(() =>
document.getElementById("focused")?.textContent || ""
);
assertEquals(focusOrder, "first,second,button,textarea,");
await browser.close();
});
Would also be good for regression testing.
I think the thing to test is that mouse events like click have event.altKey etc. working. Searching the codebase for dispatchMouseEvent:
https://github.com/search?q=repo%3Alino-levan%2Fastral%20dispatchMouseEvent&type=code
It seems none of the event details include the keyboard modifier properties like altKey, etc:
https://github.com/lino-levan/astral/blob/348dda34a0abe8c5719349f3a5a3c4d70bf18a31/src/mouse.ts#L47-L53
Right, didn't even know that was in there. Great callout.
Yes:
https://chromedevtools.github.io/devtools-protocol/tot/Input/#method-dispatchMouseEvent
I wonder if touch events, and other input events, need attention too.
Very likely the case, this'll be fun to work through.