Odoo18-Base/addons/web_tour/static/tests/tour_manager_tests.js

250 lines
9.8 KiB
JavaScript
Raw Permalink Normal View History

2025-03-10 11:12:23 +07:00
odoo.define('web_tour.tour_manager_tests', async function (require) {
"use strict";
const core = require("web.core");
const KanbanView = require('web.KanbanView');
const TourManager = require('web_tour.TourManager');
const testUtils = require('web.test_utils');
const createView = testUtils.createView;
/**
* Create a widget and a TourManager instance with a list of given Tour objects.
* @see `TourManager.register()` for more details on the Tours registry system.
* @param {Object} params aside from the parameters defined below, passed
* to {@see addMockEnvironment}.
* @param {string[]} [params.consumed_tours]
* @param {boolean} [params.debug] also passed along
* @param {boolean} [params.disabled]
* @param {string} params.template inner HTML content of the widget
* @param {Object[]} params.tours { {string} name, {Object} option, {Object[]} steps }
*/
async function createTourManager({ consumed_tours, disabled, template, tours, ...params }) {
const parent = await testUtils.createParent(params);
const tourManager = new TourManager(parent, consumed_tours, disabled);
tourManager.running_step_delay = 0;
for (const { name, options, steps } of tours) {
tourManager.register(name, options, steps);
}
const _destroy = tourManager.destroy;
tourManager.destroy = function () {
tourManager.destroy = _destroy;
parent.destroy();
};
await parent.prependTo(testUtils.prepareTarget(params.debug));
parent.el.innerHTML = template;
await tourManager._register_all(true);
// Wait for possible tooltips to be loaded and appended.
await testUtils.nextTick();
return tourManager;
}
QUnit.module("Tours", function () {
QUnit.module("Tour manager");
QUnit.test("Tours sequence", async function (assert) {
assert.expect(2);
const tourManager = await createTourManager({
template: `
<button class="btn anchor">Anchor</button>`,
tours: [
{ name: "Tour 1", options: { sequence: 10 }, steps: [{ trigger: '.anchor' }] },
{ name: "Tour 2", options: {}, steps: [{ trigger: '.anchor' }] },
{ name: "Tour 3", options: { sequence: 5 }, steps: [{ trigger: '.anchor', content: "Oui" }] },
],
// Use this test in "debug" mode because the tips need to be in
// the viewport to be able to test their normal content
// (otherwise, the tips would indicate to the users that they
// have to scroll).
debug: true,
});
assert.containsOnce(document.body, '.o_tooltip:visible');
assert.strictEqual($('.o_tooltip_content:visible').text(), "Oui",
"content should be that of the third tour");
tourManager.destroy();
});
QUnit.test("Displays a rainbow man by default at the end of tours", async function (assert) {
assert.expect(3);
function onShowEffect(params) {
assert.deepEqual(params, {
fadeout: "medium",
message: owl.markup("<strong><b>Good job!</b> You went through all steps of this tour.</strong>"),
type: "rainbow_man"
});
}
core.bus.on("show-effect", null, onShowEffect);
const tourManager = await createTourManager({
data: { 'web_tour.tour': { fields: {}, consume() {} } },
template: `<button class="btn anchor">Anchor</button>`,
tours: [{
name: "Some tour",
options: {},
steps: [{ trigger: '.anchor', content: "anchor" }],
}],
// Use this test in "debug" mode because the tips need to be in
// the viewport to be able to test their normal content
// (otherwise, the tips would indicate to the users that they
// have to scroll).
debug: true,
});
assert.containsOnce(document.body, '.o_tooltip');
await testUtils.dom.click($('.anchor'));
assert.containsNone(document.body, '.o_tooltip');
tourManager.destroy();
core.bus.off("show-effect", onShowEffect);
});
QUnit.test("Click on invisible tip consumes it", async function (assert) {
assert.expect(5);
const tourManager = await createTourManager({
data: { 'web_tour.tour': { fields: {}, consume() {} } },
template: `
<button class="btn anchor1">Anchor</button>
<button class="btn anchor2">Anchor</button>
`,
tours: [{
name: "Tour 1",
options: { rainbowMan: false, sequence: 10 },
steps: [{ trigger: '.anchor1', content: "1" }],
}, {
name: "Tour 2",
options: { rainbowMan: false, sequence: 5 },
steps: [{ trigger: '.anchor2', content: "2" }],
}],
// Use this test in "debug" mode because the tips need to be in
// the viewport to be able to test their normal content
// (otherwise, the tips would indicate to the users that they
// have to scroll).
debug: true,
});
assert.containsN(document.body, '.o_tooltip', 2);
assert.strictEqual($('.o_tooltip_content:visible').text(), "2");
await testUtils.dom.click($('.anchor1'));
assert.containsOnce(document.body, '.o_tooltip');
assert.strictEqual($('.o_tooltip_content:visible').text(), "2");
await testUtils.dom.click($('.anchor2'));
assert.containsNone(document.body, '.o_tooltip');
tourManager.destroy();
});
QUnit.test("Step anchor replaced", async function (assert) {
assert.expect(3);
const tourManager = await createTourManager({
observe: true,
template: `<input class="anchor"/>`,
tours: [{
name: "Tour",
options: { rainbowMan: false },
steps: [{ trigger: "input.anchor" }],
}],
});
assert.containsOnce(document.body, '.o_tooltip:visible');
const $anchor = $(".anchor");
const $parent = $anchor.parent();
$parent.empty();
$parent.append($anchor);
// Simulates the observer picking up the mutation and triggering an update
tourManager.update();
await testUtils.nextTick();
assert.containsOnce(document.body, '.o_tooltip:visible');
await testUtils.fields.editInput($('.anchor'), "AAA");
assert.containsNone(document.body, '.o_tooltip:visible');
tourManager.destroy();
});
QUnit.test("kanban quick create VS tour tooltips", async function (assert) {
assert.expect(3);
const kanban = await createView({
View: KanbanView,
model: 'partner',
data: {
partner: {
fields: {
foo: {string: "Foo", type: "char"},
bar: {string: "Bar", type: "boolean"},
},
records: [
{id: 1, bar: true, foo: "yop"},
]
}
},
arch: `<kanban>
<field name="bar"/>
<templates><t t-name="kanban-box">
<div><field name="foo"/></div>
</t></templates>
</kanban>`,
groupBy: ['bar'],
});
// click to add an element
await testUtils.dom.click(kanban.$('.o_kanban_header .o_kanban_quick_add i').first());
assert.containsOnce(kanban, '.o_kanban_quick_create',
"should have open the quick create widget");
// create tour manager targeting the kanban quick create in its steps
const tourManager = await createTourManager({
observe: true,
template: kanban.$el.html(),
tours: [{
name: "Tour",
options: { rainbowMan: false },
steps: [{ trigger: "input[name='display_name']" }],
}],
});
assert.containsOnce(document.body, '.o_tooltip:visible');
await testUtils.dom.click($('.o_tooltip:visible'));
assert.containsOnce(kanban, '.o_kanban_quick_create',
"the quick create should not have been destroyed when tooltip is clicked");
kanban.destroy();
tourManager.destroy();
});
QUnit.test("Automatic tour disabling", async function (assert) {
assert.expect(2);
const options = {
template: `<button class="btn anchor">Anchor</button>`,
tours: [{ name: "Tour", options: {}, steps: [{ trigger: '.anchor' }] }],
};
const enabledTM = await createTourManager({ disabled: false, ...options });
assert.containsOnce(document.body, '.o_tooltip:visible');
enabledTM.destroy();
const disabledTM = await createTourManager({ disabled: true, ...options });
assert.containsNone(document.body, '.o_tooltip:visible');
disabledTM.destroy();
});
});
});