From e160d7b33d75b70fbb190ebfaed6a51169b3b78c Mon Sep 17 00:00:00 2001 From: fdardenne Date: Wed, 22 Feb 2023 09:42:03 +0000 Subject: [PATCH] [FIX] web: popover service: prevent the crash when undefined target Steps to reproduce: - In debug mode - Go to a cancelled invoice in Accounting - Click to the "Reset to draft" button in a fast timing (before the `PopoverContainer` is mounted). When hovering an element, a tooltip appears. If the target element disappears before the `onMounted` of the `PopoverContainer`, then the popover causes a crash because the target element does not exists anymore. This fix makes the `tooltip_service` verify that the target still exists before adding the popover. closes odoo/odoo#113406 X-original-commit: 589acab37a4c1b68876386b752a91c3412dc4569 Signed-off-by: Aaron Bohy (aab) Signed-off-by: Dardenne Florent (dafl) --- .../src/core/tooltip/tooltip_service.js | 19 ++++++++------- .../core/tooltip/tooltip_service_tests.js | 24 +++++++++++++++++++ 2 files changed, 35 insertions(+), 8 deletions(-) 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"); + }); });