fix(type): focus switch between contenteditables in shadow dom (#13510)
Firefox has a bug: calling `node.focus()` does make the node focused, but some internal "current contenteditable node" is not changed. Blurring the previous one and focusing the new one helps.
This commit is contained in:
parent
ae4d2e75aa
commit
7a5b070e95
|
|
@ -663,7 +663,14 @@ export class InjectedScript {
|
||||||
return 'error:notconnected';
|
return 'error:notconnected';
|
||||||
if (node.nodeType !== Node.ELEMENT_NODE)
|
if (node.nodeType !== Node.ELEMENT_NODE)
|
||||||
throw this.createStacklessError('Node is not an element');
|
throw this.createStacklessError('Node is not an element');
|
||||||
const wasFocused = (node.getRootNode() as (Document | ShadowRoot)).activeElement === node && node.ownerDocument && node.ownerDocument.hasFocus();
|
|
||||||
|
const activeElement = (node.getRootNode() as (Document | ShadowRoot)).activeElement;
|
||||||
|
const wasFocused = activeElement === node && node.ownerDocument && node.ownerDocument.hasFocus();
|
||||||
|
if (!wasFocused && activeElement && (activeElement as HTMLElement | SVGElement).blur) {
|
||||||
|
// Workaround the Firefox bug where focusing the element does not switch current
|
||||||
|
// contenteditable to the new element. However, blurring the previous one helps.
|
||||||
|
(activeElement as HTMLElement | SVGElement).blur();
|
||||||
|
}
|
||||||
(node as HTMLElement | SVGElement).focus();
|
(node as HTMLElement | SVGElement).focus();
|
||||||
|
|
||||||
if (resetSelectionIfNotFocused && !wasFocused && node.nodeName.toLowerCase() === 'input') {
|
if (resetSelectionIfNotFocused && !wasFocused && node.nodeName.toLowerCase() === 'input') {
|
||||||
|
|
|
||||||
|
|
@ -476,6 +476,48 @@ it('should support simple copy-pasting', async ({ page, isMac, browserName }) =>
|
||||||
expect(await page.evaluate(() => document.querySelector('div').textContent)).toBe('123123');
|
expect(await page.evaluate(() => document.querySelector('div').textContent)).toBe('123123');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should type repeatedly in contenteditable in shadow dom', async ({ page }) => {
|
||||||
|
it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/12941' });
|
||||||
|
|
||||||
|
await page.setContent(`
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<shadow-element></shadow-element>
|
||||||
|
<script>
|
||||||
|
customElements.define('shadow-element', class extends HTMLElement {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.attachShadow({ mode: 'open' });
|
||||||
|
}
|
||||||
|
|
||||||
|
connectedCallback() {
|
||||||
|
this.shadowRoot.innerHTML = \`
|
||||||
|
<style>
|
||||||
|
.editor { padding: 1rem; margin: 1rem; border: 1px solid #ccc; }
|
||||||
|
</style>
|
||||||
|
<div class=editor contenteditable id=foo></div>
|
||||||
|
<hr>
|
||||||
|
<section>
|
||||||
|
<div class=editor contenteditable id=bar></div>
|
||||||
|
</section>
|
||||||
|
\`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`);
|
||||||
|
|
||||||
|
const editor = page.locator('shadow-element > .editor').first();
|
||||||
|
await editor.type('This is the first box.');
|
||||||
|
|
||||||
|
const sectionEditor = page.locator('section .editor');
|
||||||
|
await sectionEditor.type('This is the second box.');
|
||||||
|
|
||||||
|
expect(await editor.textContent()).toBe('This is the first box.');
|
||||||
|
expect(await sectionEditor.textContent()).toBe('This is the second box.');
|
||||||
|
});
|
||||||
|
|
||||||
async function captureLastKeydown(page) {
|
async function captureLastKeydown(page) {
|
||||||
const lastEvent = await page.evaluateHandle(() => {
|
const lastEvent = await page.evaluateHandle(() => {
|
||||||
const lastEvent = {
|
const lastEvent = {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue