diff --git a/packages/playwright-core/src/server/injected/highlight.ts b/packages/playwright-core/src/server/injected/highlight.ts index c85216e106..602ae4379e 100644 --- a/packages/playwright-core/src/server/injected/highlight.ts +++ b/packages/playwright-core/src/server/injected/highlight.ts @@ -42,6 +42,7 @@ export type HighlightOptions = { export class Highlight { private _glassPaneElement: HTMLElement; private _glassPaneShadow: ShadowRoot; + private _glassPaneMutationObserver: MutationObserver | undefined; private _highlightEntries: HighlightEntry[] = []; private _highlightOptions: HighlightOptions = {}; private _actionPointElement: HTMLElement; @@ -91,6 +92,15 @@ export class Highlight { install() { this._injectedScript.document.documentElement.appendChild(this._glassPaneElement); + + // JS frameworks like React erase the entire DOM upon hydration, so we need to recreate it + this._glassPaneMutationObserver = new MutationObserver(mutations => mutations.forEach(mutation => { + for (const removedNode of mutation.removedNodes) { + if (removedNode === this._glassPaneElement) + this._injectedScript.document.documentElement.appendChild(this._glassPaneElement); + } + })); + this._glassPaneMutationObserver.observe(this._glassPaneElement); } setLanguage(language: Language) { @@ -107,6 +117,7 @@ export class Highlight { uninstall() { if (this._rafRequest) cancelAnimationFrame(this._rafRequest); + this._glassPaneMutationObserver?.disconnect(); this._glassPaneElement.remove(); }