diff --git a/addons/web_tour/static/src/tour_service/tour_pointer_state.js b/addons/web_tour/static/src/tour_service/tour_pointer_state.js index 7e9c0305b93..50e169fe36e 100644 --- a/addons/web_tour/static/src/tour_service/tour_pointer_state.js +++ b/addons/web_tour/static/src/tour_service/tour_pointer_state.js @@ -121,6 +121,7 @@ export function createPointerState() { default: { const onClick = () => { anchor.scrollIntoView({ behavior: "smooth", block: "nearest" }); + hide(); }; const scrollParent = getScrollParent(anchor); diff --git a/addons/web_tour/static/tests/tour_service_tests.js b/addons/web_tour/static/tests/tour_service_tests.js index 4f4fb1eb8c5..cda8479ee46 100644 --- a/addons/web_tour/static/tests/tour_service_tests.js +++ b/addons/web_tour/static/tests/tour_service_tests.js @@ -135,6 +135,93 @@ QUnit.module("Tour service", (hooks) => { assert.strictEqual(target.querySelector("span.value").textContent, "1"); }); + QUnit.test("scroller pointer to reach next step", async function (assert) { + patchWithCleanup(Element.prototype, { + scrollIntoView(options) { + super.scrollIntoView({ ...options, behavior: "instant" }); + }, + }); + + // The fixture should be shown for this test + target.style.position = "fixed"; + target.style.top = "200px"; + target.style.left = "50px"; + + registry.category("web_tour.tours").add("tour1", { + sequence: 10, + steps: () => [{ trigger: "button.inc", content: "Click to increment" }], + }); + const env = await makeTestEnv({}); + + const { Component: OverlayContainer, props: overlayContainerProps } = registry + .category("main_components") + .get("OverlayContainer"); + + class Root extends Component { + static components = { OverlayContainer, Counter }; + static template = xml/*html*/ ` +
+
+ + +
+
+ `; + } + + await mount(Root, target, { env, props: { overlayContainerProps } }); + env.services.tour_service.startTour("tour1", { mode: "manual" }); + await mock.advanceTime(100); // awaits the macro engine + + // Even if this seems weird, it should show the initial pointer. + // This is due to the fact the intersection observer has just been started and + // the pointer did not have the observations yet when the pointTo method was called. + // This is a bit tricky to change for now because the synchronism of the pointTo method + // is what permits to avoid multiple pointer to be shown at the same time + assert.containsOnce(document.body, ".o_tour_pointer"); + assert.equal( + document.body.querySelector(".o_tour_pointer").textContent, + "Click to increment" + ); + + await mock.advanceTime(100); // awaits for the macro engine next check cycle + // now the scroller pointer should be shown + assert.containsOnce(document.body, ".o_tour_pointer"); + assert.equal( + document.body.querySelector(".o_tour_pointer").textContent, + "Scroll down to reach the next step." + ); + + // awaiting the click here permits to the intersection observer to update + await click(document.body, ".o_tour_pointer"); + assert.containsNone(document.body, ".o_tour_pointer"); + await mock.advanceTime(100); // awaits for the macro engine next check cycle + assert.containsOnce(document.body, ".o_tour_pointer"); + assert.equal( + document.body.querySelector(".o_tour_pointer").textContent, + "Click to increment" + ); + + document.querySelector(".scrollable-parent").scrollTop = 1000; + await nextTick(); // awaits the intersection observer to update after the scroll + await mock.advanceTime(100); // awaits for the macro engine next check cycle + assert.containsOnce(document.body, ".o_tour_pointer"); + assert.equal( + document.body.querySelector(".o_tour_pointer").textContent, + "Scroll up to reach the next step." + ); + + // awaiting the click here permits to the intersection observer to update + await click(document.body, ".o_tour_pointer"); + assert.containsNone(document.body, ".o_tour_pointer"); + await mock.advanceTime(100); // awaits for the macro engine next check cycle + assert.containsOnce(document.body, ".o_tour_pointer"); + assert.equal( + document.body.querySelector(".o_tour_pointer").textContent, + "Click to increment" + ); + }); + QUnit.test("perform edit on next step", async function (assert) { registry.category("web_tour.tours").add("tour1", { sequence: 10,