diff --git a/addons/web/static/src/core/tooltip/tooltip_service.js b/addons/web/static/src/core/tooltip/tooltip_service.js index f4cf156bbc0..dea57c09cb5 100644 --- a/addons/web/static/src/core/tooltip/tooltip_service.js +++ b/addons/web/static/src/core/tooltip/tooltip_service.js @@ -104,14 +104,17 @@ export const tooltipService = { } openTooltipTimeout = browser.setTimeout(() => { - closeTooltip = popover.add( - target, - Tooltip, - { tooltip, template, info }, - { position } - ); - // Prevent title from showing on a parent at the same time - target.title = ""; + // verify that the element is still in the DOM + if (target.isConnected) { + closeTooltip = popover.add( + target, + Tooltip, + { tooltip, template, info }, + { position } + ); + // Prevent title from showing on a parent at the same time + target.title = ""; + } }, delay); } diff --git a/addons/web/static/tests/core/tooltip/tooltip_service_tests.js b/addons/web/static/tests/core/tooltip/tooltip_service_tests.js index e50cd584d04..54ab588edb4 100644 --- a/addons/web/static/tests/core/tooltip/tooltip_service_tests.js +++ b/addons/web/static/tests/core/tooltip/tooltip_service_tests.js @@ -424,4 +424,28 @@ QUnit.module("Tooltip service", (hooks) => { await triggerEvent(target, "button[data-tooltip]", "touchstart"); assert.containsNone(target, ".o_popover_container .o_popover"); }); + + QUnit.test("tooltip does not crash with disappearing target", async (assert) => { + class MyComponent extends Component {} + MyComponent.template = xml``; + let simulateTimeout; + const mockSetTimeout = async (fn) => { + simulateTimeout = fn; + }; + await makeParent(MyComponent, { mockSetTimeout }); + + assert.containsNone(target, ".o_popover_container .o_popover"); + target.querySelector(".mybtn").dispatchEvent(new Event("mouseenter")); + await nextTick(); + assert.containsNone(target, ".o_popover_container .o_popover"); + + // the element disappeared from the DOM during the setTimeout + target.querySelector(".mybtn").remove(); + + simulateTimeout(); + await nextTick(); + + // tooltip did not crash and is not shown + assert.containsNone(target, ".o_popover_container .o_popover"); + }); });