[FIX] web_tour: ensure tours are run only once

Before this commit, tours could be resumed AND started in the same
sequence, causing object mismatches in the tour service internals and
resulting in multiple tooltips being displayed at the same time.

This commit ensures that a tour instance can only be run once at a time.

closes odoo/odoo#140664

Signed-off-by: Mathieu Duckerts-Antoine (dam) <dam@odoo.com>
This commit is contained in:
Julien Mougenot
2023-11-03 16:43:34 +00:00
parent 2e254f07c2
commit 210c03fde0
2 changed files with 24 additions and 5 deletions
@@ -66,14 +66,13 @@ export const tourService = {
tours[name] = {
name: tour.saveAs || name,
get steps() {
if(typeof tour.steps === "function") {
if (typeof tour.steps === "function") {
return tour.steps().map((step) => {
step.shadow_dom = step.shadow_dom ?? tour.shadow_dom;
return step;
});
}
else {
throw new Error(`tour.steps has to be a function that returns TourStep[]`)
} else {
throw new Error(`tour.steps has to be a function that returns TourStep[]`);
}
},
shadow_dom: tour.shadow_dom,
@@ -106,6 +105,8 @@ export const tourService = {
const consumedTours = new Set(session.web_tours);
const pointers = reactive({});
/** @type {Set<string>} */
const runningTours = new Set();
function createPointer(tourName, config) {
const { state: pointerState, methods } = createPointerState();
@@ -214,6 +215,7 @@ export const tourService = {
pointer.stop();
// Used to signal the python test runner that the tour finished without error.
browser.console.log("test successful");
runningTours.delete(name);
},
});
}
@@ -259,6 +261,10 @@ export const tourService = {
}
function startTour(tourName, options = {}) {
if (runningTours.has(tourName)) {
return;
}
runningTours.add(tourName);
const defaultOptions = {
stepDelay: 0,
keepWatchBrowser: false,
@@ -303,6 +309,10 @@ export const tourService = {
}
function resumeTour(tourName) {
if (runningTours.has(tourName)) {
return;
}
runningTours.add(tourName);
const tour = tours[tourName];
const stepDelay = tourState.get(tourName, "stepDelay");
const keepWatchBrowser = tourState.get(tourName, "keepWatchBrowser");
@@ -365,7 +365,7 @@ QUnit.module("Tour service", (hooks) => {
QUnit.test("perform edit on next step", async function (assert) {
registry.category("web_tour.tours").add("tour1", {
sequence: 10,
steps:() => [
steps: () => [
{
trigger: ".interval input",
},
@@ -435,6 +435,15 @@ QUnit.module("Tour service", (hooks) => {
});
QUnit.test("should show only 1 pointer at a time", async function (assert) {
const storage = new Map();
patchWithCleanup(browser.localStorage, {
getItem: (key) => storage.get(key),
setItem: (key, value) => storage.set(key, value),
removeItem: (key) => storage.delete(key),
tour__tour1__sequence: 0,
tour__tour2__sequence: 0,
});
registry.category("web_tour.tours").add("tour1", {
sequence: 10,
steps: () => [