diff --git a/packages/playwright-core/src/server/injected/injectedScript.ts b/packages/playwright-core/src/server/injected/injectedScript.ts index d1bd83b1cf..24d0b4f699 100644 --- a/packages/playwright-core/src/server/injected/injectedScript.ts +++ b/packages/playwright-core/src/server/injected/injectedScript.ts @@ -663,7 +663,14 @@ export class InjectedScript { return 'error:notconnected'; if (node.nodeType !== Node.ELEMENT_NODE) 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(); if (resetSelectionIfNotFocused && !wasFocused && node.nodeName.toLowerCase() === 'input') { diff --git a/tests/page/page-keyboard.spec.ts b/tests/page/page-keyboard.spec.ts index 5866118ead..e0f45dd23d 100644 --- a/tests/page/page-keyboard.spec.ts +++ b/tests/page/page-keyboard.spec.ts @@ -476,6 +476,48 @@ it('should support simple copy-pasting', async ({ page, isMac, browserName }) => 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(` + +
+