summaryrefslogtreecommitdiff
path: root/addons/website/static/tests
diff options
context:
space:
mode:
authorstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
committerstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
commit3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch)
treea44932296ef4a9b71d5f010906253d8c53727726 /addons/website/static/tests
parent0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff)
initial commit 2
Diffstat (limited to 'addons/website/static/tests')
-rw-r--r--addons/website/static/tests/dashboard_tests.js67
-rw-r--r--addons/website/static/tests/tours/dashboard_tour.js22
-rw-r--r--addons/website/static/tests/tours/html_editor.js140
-rw-r--r--addons/website/static/tests/tours/public_user_editor.js31
-rw-r--r--addons/website/static/tests/tours/reset_password.js30
-rw-r--r--addons/website/static/tests/tours/restricted_editor.js17
-rw-r--r--addons/website/static/tests/tours/rte.js194
-rw-r--r--addons/website/static/tests/tours/snippet_empty_parent_autoremove.js75
-rw-r--r--addons/website/static/tests/tours/snippet_version.js67
-rw-r--r--addons/website/static/tests/tours/specific_website_editor.js29
-rw-r--r--addons/website/static/tests/tours/website_navbar_menu.js20
-rw-r--r--addons/website/static/tests/tours/website_style_edition.js34
-rw-r--r--addons/website/static/tests/website_tests.js73
13 files changed, 799 insertions, 0 deletions
diff --git a/addons/website/static/tests/dashboard_tests.js b/addons/website/static/tests/dashboard_tests.js
new file mode 100644
index 00000000..37ee6b24
--- /dev/null
+++ b/addons/website/static/tests/dashboard_tests.js
@@ -0,0 +1,67 @@
+odoo.define('website/static/tests/dashboard_tests', function (require) {
+"use strict";
+
+const ControlPanel = require('web.ControlPanel');
+const Dashboard = require('website.backend.dashboard');
+const testUtils = require("web.test_utils");
+
+const { createParent, nextTick, prepareTarget } = testUtils;
+
+QUnit.module('Website Backend Dashboard', {
+}, function () {
+ QUnit.test("mounted is called once for the dashboarrd's ControlPanel", async function (assert) {
+ // This test can be removed as soon as we don't mix legacy and owl layers anymore.
+ assert.expect(5);
+
+ ControlPanel.patch('test.ControlPanel', T => {
+ class ControlPanelPatchTest extends T {
+ mounted() {
+ assert.step('mounted');
+ super.mounted(...arguments);
+ }
+ willUnmount() {
+ assert.step('willUnmount');
+ super.mounted(...arguments);
+ }
+ }
+ return ControlPanelPatchTest;
+ });
+
+ const params = {
+ mockRPC: (route) => {
+ if (route === '/website/fetch_dashboard_data') {
+ return Promise.resolve({
+ dashboards: {
+ visits: {},
+ sales: { summary: {} },
+ },
+ groups: { system: true, website_designer: true },
+ websites: [
+ {id: 1, name: "My Website", domain: "", selected: true},
+ ],
+ });
+ }
+ return this._super(...arguments);
+ },
+ };
+ const parent = await createParent(params);
+ const dashboard = new Dashboard(parent, {});
+ await dashboard.appendTo(document.createDocumentFragment());
+
+ assert.verifySteps([]);
+
+ dashboard.$el.appendTo(prepareTarget());
+ dashboard.on_attach_callback();
+
+ await nextTick();
+
+ assert.verifySteps(['mounted']);
+
+ dashboard.destroy();
+ assert.verifySteps(['willUnmount']);
+
+ ControlPanel.unpatch('test.ControlPanel');
+ });
+});
+
+});
diff --git a/addons/website/static/tests/tours/dashboard_tour.js b/addons/website/static/tests/tours/dashboard_tour.js
new file mode 100644
index 00000000..de1a5f10
--- /dev/null
+++ b/addons/website/static/tests/tours/dashboard_tour.js
@@ -0,0 +1,22 @@
+odoo.define("website.tour.backend_dashboard", function (require) {
+"use strict";
+
+var tour = require("web_tour.tour");
+
+tour.register("backend_dashboard", {
+ test: true,
+ url: "/web",
+}, [tour.stepUtils.showAppsMenuItem(),
+ {
+ trigger: 'a[data-menu-xmlid="website.menu_website_configuration"]',
+}, {
+ trigger: '.dropdown-toggle[data-menu-xmlid="website.menu_dashboard"]',
+}, {
+ trigger: '.dropdown-item[data-menu-xmlid="website.menu_website_google_analytics"]',
+}, {
+ // Visits section should always be present even when empty / not hooked to anything
+ trigger: 'h2:contains("Visits")',
+ content: "Check if dashboard loads",
+ run: function () {}
+}]);
+});
diff --git a/addons/website/static/tests/tours/html_editor.js b/addons/website/static/tests/tours/html_editor.js
new file mode 100644
index 00000000..281b53b8
--- /dev/null
+++ b/addons/website/static/tests/tours/html_editor.js
@@ -0,0 +1,140 @@
+odoo.define('website.test.html_editor', function (require) {
+'use strict';
+
+var tour = require('web_tour.tour');
+
+tour.register('html_editor_multiple_templates', {
+ test: true,
+ url: '/generic',
+},
+ [
+ // 1. Edit the page through Edit Mode, it will COW the view
+ {
+ content: "enter edit mode",
+ trigger: 'a[data-action=edit]',
+ },
+ {
+ content: "drop a snippet",
+ trigger: '#oe_snippets .oe_snippet:has(.s_cover) .oe_snippet_thumbnail',
+ // id starting by 'oe_structure..' will actually create an inherited view
+ run: "drag_and_drop #oe_structure_test_ui",
+ },
+ {
+ content: "save the page",
+ extra_trigger: '#oe_structure_test_ui.o_dirty',
+ trigger: "button[data-action=save]",
+ },
+ // 2. Edit generic view
+ {
+ content: "open customize menu",
+ extra_trigger: "body:not(.editor_enable)",
+ trigger: '#customize-menu > a',
+ },
+ {
+ content: "open html editor",
+ trigger: '#html_editor',
+ },
+ {
+ content: "add something in the generic view",
+ trigger: 'div.ace_line .ace_xml:contains("Generic")',
+ run: function () {
+ ace.edit('ace-view-editor').getSession().insert({row: 3, column: 1}, '<p>somenewcontent</p>\n');
+ },
+ },
+ // 3. Edit oe_structure specific view
+ {
+ content: "select oe_structure specific view",
+ trigger: 'div.ace_line .ace_xml:contains("somenewcontent")',
+ run: function () {
+ var viewId = $('#ace-view-list option:contains("oe_structure_test_ui")').val();
+ $('#ace-view-list').val(viewId).trigger('change');
+ },
+ },
+ {
+ content: "add something in the oe_structure specific view",
+ extra_trigger: '#ace-view-id:contains("test.generic_view_oe_structure_test_ui")', // If no xml_id it should show key
+ trigger: 'div.ace_line .ace_xml:contains("s_cover")',
+ run: function () {
+ ace.edit('ace-view-editor').getSession().insert({row: 2, column: 1}, '<p>anothernewcontent</p>\n');
+ },
+ },
+ {
+ content: "save the html editor",
+ extra_trigger: 'div.ace_line .ace_xml:contains("anothernewcontent")',
+ trigger: ".o_ace_view_editor button[data-action=save]",
+ },
+ {
+ content: "check that the page has both modification",
+ extra_trigger: '#wrapwrap:contains("anothernewcontent")',
+ trigger: '#wrapwrap:contains("somenewcontent")',
+ run: function () {}, // it's a check
+ },
+ ]
+);
+
+tour.register('test_html_editor_scss', {
+ test: true,
+ url: '/contactus',
+},
+ [
+ // 1. Open Html Editor and select a scss file
+ {
+ content: "open customize menu",
+ extra_trigger: '#wrap:visible', // ensure state for later
+ trigger: '#customize-menu > a',
+ },
+ {
+ content: "open html editor",
+ trigger: '#html_editor',
+ },
+ {
+ content: "open type switcher",
+ trigger: '.o_ace_type_switcher button',
+ },
+ {
+ content: "select scss files",
+ trigger: '.o_ace_type_switcher_choice[data-type="scss"]',
+ },
+ {
+ content: "select 'user_custom_rules'",
+ trigger: 'body:has(#ace-scss-list option:contains("user_custom_rules"))',
+ run: function () {
+ var scssId = $('#ace-scss-list option:contains("user_custom_rules")').val();
+ $('#ace-scss-list').val(scssId).trigger('change');
+ },
+ },
+ // 2. Edit that file and ensure it was saved then reset it
+ {
+ content: "add some scss content in the file",
+ trigger: 'div.ace_line .ace_comment:contains("footer {")',
+ run: function () {
+ ace.edit('ace-view-editor').getSession().insert({row: 2, column: 0}, '#wrap {display: none;}\n');
+ },
+ },
+ {
+ content: "save the html editor",
+ extra_trigger: 'div.ace_line:contains("#wrap {display: none;}")',
+ trigger: ".o_ace_view_editor button[data-action=save]",
+ },
+ {
+ content: "check that the scss modification got applied",
+ trigger: 'body:has(#wrap:hidden)',
+ run: function () {}, // it's a check
+ },
+ {
+ content: "reset view (after reload, html editor should have been reopened where it was)",
+ trigger: '#ace-view-id button[data-action="reset"]',
+ },
+ {
+ content: "confirm reset warning",
+ trigger: '.modal-footer .btn-primary',
+ },
+ {
+ content: "check that the scss file was reset correctly, wrap content should now be visible again",
+ trigger: '#wrap:visible',
+ run: function () {}, // it's a check
+ },
+ ]
+);
+
+});
diff --git a/addons/website/static/tests/tours/public_user_editor.js b/addons/website/static/tests/tours/public_user_editor.js
new file mode 100644
index 00000000..7b3449e1
--- /dev/null
+++ b/addons/website/static/tests/tours/public_user_editor.js
@@ -0,0 +1,31 @@
+odoo.define('website.tour.public_user_editor_dep_widget', function (require) {
+'use strict';
+
+const publicWidget = require('web.public.widget');
+const wysiwygLoader = require('web_editor.loader');
+
+publicWidget.registry['public_user_editor_test'] = publicWidget.Widget.extend({
+ selector: 'textarea.o_public_user_editor_test_textarea',
+
+ /**
+ * @override
+ */
+ start: async function () {
+ await this._super(...arguments);
+ await wysiwygLoader.load(this, this.el, {});
+ },
+});
+});
+
+odoo.define('website.tour.public_user_editor', function (require) {
+'use strict';
+
+const tour = require('web_tour.tour');
+
+tour.register('public_user_editor', {
+ test: true,
+}, [{
+ trigger: 'odoo-wysiwyg-container:has(> .o_public_user_editor_test_textarea:first-child)',
+ run: function () {}, // Simple check
+}]);
+});
diff --git a/addons/website/static/tests/tours/reset_password.js b/addons/website/static/tests/tours/reset_password.js
new file mode 100644
index 00000000..0f7eee7c
--- /dev/null
+++ b/addons/website/static/tests/tours/reset_password.js
@@ -0,0 +1,30 @@
+odoo.define('website.tour_reset_password', function (require) {
+'use strict';
+
+var tour = require('web_tour.tour');
+require('web.dom_ready');
+
+tour.register('website_reset_password', {
+ test: true,
+}, [
+ {
+ content: "fill new password",
+ trigger: '.oe_reset_password_form input[name="password"]',
+ run: "text adminadmin"
+ },
+ {
+ content: "fill confirm password",
+ trigger: '.oe_reset_password_form input[name="confirm_password"]',
+ run: "text adminadmin"
+ },
+ {
+ content: "submit reset password form",
+ trigger: '.oe_reset_password_form button[type="submit"]',
+ },
+ {
+ content: "check that we're logged in",
+ trigger: '.oe_topbar_name:contains("The King")',
+ run: function () {}
+ },
+]);
+});
diff --git a/addons/website/static/tests/tours/restricted_editor.js b/addons/website/static/tests/tours/restricted_editor.js
new file mode 100644
index 00000000..10f24291
--- /dev/null
+++ b/addons/website/static/tests/tours/restricted_editor.js
@@ -0,0 +1,17 @@
+odoo.define("website.tour.restricted_editor", function (require) {
+"use strict";
+
+var tour = require("web_tour.tour");
+
+tour.register("restricted_editor", {
+ test: true,
+ url: "/",
+}, [{
+ trigger: 'a[data-action=edit]',
+ content: "Click \"EDIT\" button of website as Restricted Editor",
+ extra_trigger: ".homepage",
+}, {
+ trigger: '#oe_snippets.o_loaded',
+ content: "Check that the snippets loaded properly",
+}]);
+});
diff --git a/addons/website/static/tests/tours/rte.js b/addons/website/static/tests/tours/rte.js
new file mode 100644
index 00000000..5a8f9022
--- /dev/null
+++ b/addons/website/static/tests/tours/rte.js
@@ -0,0 +1,194 @@
+odoo.define('website.tour.rte', function (require) {
+'use strict';
+
+var ajax = require('web.ajax');
+var session = require('web.session');
+var tour = require('web_tour.tour');
+var Wysiwyg = require('web_editor.wysiwyg.root');
+
+var domReady = new Promise(function (resolve) {
+ $(resolve);
+});
+var ready = Promise.all([domReady, session.is_bound, ajax.loadXML()]);
+
+tour.register('rte_translator', {
+ test: true,
+ url: '/fr_BE',
+ wait_for: ready,
+}, [{
+ content : "click language dropdown",
+ trigger : '.js_language_selector .dropdown-toggle',
+}, {
+ content: "go to english version",
+ trigger: '.js_language_selector a[data-url_code="en"]',
+ extra_trigger: 'html[lang*="fr"]',
+}, {
+ content: "Open new page menu",
+ trigger: '#new-content-menu > a',
+ extra_trigger: 'a[data-action="edit"]',
+}, {
+ content: "click on new page",
+ trigger: 'a[data-action="new_page"]',
+}, {
+ content: "insert page name",
+ trigger: '#editor_new_page input[type="text"]',
+ run: 'text rte_translator',
+}, {
+ content: "create page",
+ trigger: 'button.btn-continue',
+ extra_trigger: 'input[type="text"]:propValue(rte_translator)',
+}, {
+ content: "drop a snippet",
+ trigger: "#snippet_structure .oe_snippet:eq(1) .oe_snippet_thumbnail",
+ run: 'drag_and_drop #wrap',
+}, {
+ content: "change content",
+ trigger: '#wrap',
+ run: function () {
+ $("#wrap p:first").replaceWith('<p>Write one or <font style="background-color: yellow;">two paragraphs <b>describing</b></font> your product or\
+ <font style="color: rgb(255, 0, 0);">services</font>. To be successful your content needs to be\
+ useful to your <a href="/999">readers</a>.</p> <input placeholder="test translate placeholder"/>\
+ <p>&lt;b&gt;&lt;/b&gt; is an HTML&nbsp;tag &amp; is empty</p>');
+ $("#wrap img").attr("title", "test translate image title");
+ }
+}, {
+ content: "save",
+ trigger: 'button[data-action=save]',
+ extra_trigger: '#wrap p:first b',
+}, {
+ content : "click language dropdown",
+ trigger : '.js_language_selector .dropdown-toggle',
+ extra_trigger: 'body:not(.o_wait_reload):not(:has(.note-editor)) a[data-action="edit"]',
+}, {
+ content: "click on french version",
+ trigger: '.js_language_selector a[data-url_code="fr_BE"]',
+ extra_trigger: 'html[lang*="en"]:not(:has(button[data-action=save]))',
+}, {
+ content: "translate",
+ trigger: 'html:not(:has(#wrap p span)) .o_menu_systray a[data-action="translate"]',
+}, {
+ content: "close modal",
+ trigger: '.modal-footer .btn-secondary',
+}, {
+ content: "check if translation is activate",
+ trigger: '[data-oe-translation-id]',
+}, {
+ content: "translate text",
+ trigger: '#wrap p font:first',
+ run: function (action_helper) {
+ action_helper.text('translated french text');
+ Wysiwyg.setRange(this.$anchor.contents()[0], 22);
+ this.$anchor.trigger($.Event( "keyup", {key: '_', keyCode: 95}));
+ this.$anchor.trigger('input');
+ },
+}, {
+ content: "translate text with special char",
+ trigger: '#wrap input + p span:first',
+ run: function (action_helper) {
+ action_helper.click();
+ this.$anchor.prepend('&lt;{translated}&gt;');
+ Wysiwyg.setRange(this.$anchor.contents()[0], 0);
+ this.$anchor.trigger($.Event( "keyup", {key: '_', keyCode: 95}));
+ this.$anchor.trigger('input');
+ },
+}, {
+ content: "click on input",
+ trigger: '#wrap input:first',
+ extra_trigger: '#wrap .o_dirty font:first:contains(translated french text)',
+ run: 'click',
+}, {
+ content: "translate placeholder",
+ trigger: 'input:first',
+ run: 'text test french placeholder',
+}, {
+ content: "close modal",
+ trigger: '.modal-footer .btn-primary',
+ extra_trigger: '.modal input:propValue(test french placeholder)',
+}, {
+ content: "save translation",
+ trigger: 'button[data-action=save]',
+}, {
+ content: "check: content is translated",
+ trigger: '#wrap p font:first:contains(translated french text)',
+ extra_trigger: 'body:not(.o_wait_reload):not(:has(.note-editor)) a[data-action="edit_master"]',
+ run: function () {}, // it's a check
+}, {
+ content: "check: content with special char is translated",
+ trigger: "#wrap input + p:contains(<{translated}><b></b> is an HTML\xa0tag & )",
+ run: function () {}, // it's a check
+
+}, {
+ content: "check: placeholder translation",
+ trigger: 'input[placeholder="test french placeholder"]',
+ run: function () {}, // it's a check
+
+}, {
+ content: "open language selector",
+ trigger: '.js_language_selector button:first',
+ extra_trigger: 'html[lang*="fr"]:not(:has(#wrap p span))',
+}, {
+ content: "return to english version",
+ trigger: '.js_language_selector a[data-url_code="en"]',
+}, {
+ content: "edit english version",
+ trigger: 'a[data-action=edit]',
+ extra_trigger: 'body:not(:has(#wrap p font:first:containsExact(paragraphs <b>describing</b>)))',
+}, {
+ content: "select text",
+ extra_trigger: '#oe_snippets.o_loaded',
+ trigger: '#wrap p',
+ run: function (action_helper) {
+ action_helper.click();
+ var el = this.$anchor[0];
+ var mousedown = document.createEvent('MouseEvents');
+ mousedown.initMouseEvent('mousedown', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, el);
+ el.dispatchEvent(mousedown);
+ var mouseup = document.createEvent('MouseEvents');
+ Wysiwyg.setRange(el.childNodes[2], 6, el.childNodes[2], 13);
+ mouseup.initMouseEvent('mouseup', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, el);
+ el.dispatchEvent(mouseup);
+ },
+}, {
+ content: "underline",
+ trigger: '.note-air-popover button[data-event="underline"]',
+}, {
+ content: "save new change",
+ trigger: 'button[data-action=save]',
+ extra_trigger: '#wrap.o_dirty p u',
+
+ }, {
+ content : "click language dropdown",
+ trigger : '.js_language_selector .dropdown-toggle',
+ extra_trigger: 'body:not(.o_wait_reload):not(:has(.note-editor)) a[data-action="edit"]',
+}, {
+ content: "return in french",
+ trigger : 'html[lang="en-US"] .js_language_selector .js_change_lang[data-url_code="fr_BE"]',
+}, {
+ content: "check bis: content is translated",
+ trigger: '#wrap p font:first:contains(translated french text)',
+ extra_trigger: 'html[lang*="fr"] body:not(:has(button[data-action=save]))',
+}, {
+ content: "check bis: placeholder translation",
+ trigger: 'input[placeholder="test french placeholder"]',
+}, {
+ content: "Open customize menu",
+ trigger: "#customize-menu > .dropdown-toggle",
+}, {
+ content: "Open HTML editor",
+ trigger: "[data-action='ace']",
+}, {
+ content: "Check that the editor is not showing translated content (1)",
+ trigger: '.ace_text-layer .ace_line:contains("an HTML")',
+ run: function (actions) {
+ var lineEscapedText = $(this.$anchor.text()).text();
+ if (lineEscapedText !== "&lt;b&gt;&lt;/b&gt; is an HTML&nbsp;tag &amp; is empty") {
+ console.error('The HTML editor should display the correct untranslated content');
+ $('body').addClass('rte_translator_error');
+ }
+ },
+}, {
+ content: "Check that the editor is not showing translated content (2)",
+ trigger: 'body:not(.rte_translator_error)',
+ run: function () {},
+}]);
+});
diff --git a/addons/website/static/tests/tours/snippet_empty_parent_autoremove.js b/addons/website/static/tests/tours/snippet_empty_parent_autoremove.js
new file mode 100644
index 00000000..719d112f
--- /dev/null
+++ b/addons/website/static/tests/tours/snippet_empty_parent_autoremove.js
@@ -0,0 +1,75 @@
+odoo.define("website.tour.snippet_empty_parent_autoremove", function (require) {
+"use strict";
+
+const tour = require('web_tour.tour');
+const wTourUtils = require('website.tour_utils');
+
+function removeSelectedBlock() {
+ return {
+ content: "Remove selected block",
+ trigger: '#oe_snippets we-customizeblock-options:last-child .oe_snippet_remove',
+ };
+}
+
+tour.register('snippet_empty_parent_autoremove', {
+ test: true,
+ url: '/?enable_editor=1',
+}, [
+ // Base case: remove both columns from text - image
+ wTourUtils.dragNDrop({
+ id: 's_text_image',
+ name: 'Text - Image',
+ }),
+ {
+ content: "Click on second column",
+ trigger: '#wrap .s_text_image .row > :nth-child(2)',
+ },
+ removeSelectedBlock(),
+ {
+ content: "Click on first column",
+ trigger: '#wrap .s_text_image .row > :first-child',
+ },
+ removeSelectedBlock(),
+ {
+ content: "Check that #wrap is empty",
+ trigger: '#wrap:empty',
+ },
+
+ // Banner: test that parallax, bg-filter and shape are not treated as content
+ wTourUtils.dragNDrop({
+ id: 's_banner',
+ name: 'Banner',
+ }),
+ wTourUtils.clickOnSnippet({
+ id: 's_banner',
+ name: 'Banner',
+ }),
+ {
+ content: "Check that parallax is present",
+ trigger: '#wrap .s_banner .s_parallax_bg',
+ run: () => null,
+ },
+ wTourUtils.changeOption('ColoredLevelBackground', 'Shape'),
+ {
+ content: "Check that shape is present",
+ trigger: '#wrap .s_banner .o_we_shape',
+ run: () => null,
+ },
+ wTourUtils.changeOption('ColoredLevelBackground', 'Filter'),
+ {
+ content: "Check that background-filter is present",
+ trigger: '#wrap .s_banner .o_we_bg_filter',
+ run: () => null,
+ },
+ {
+ content: "Click on first column",
+ trigger: '#wrap .s_banner .row > :first-child',
+ },
+ removeSelectedBlock(),
+ {
+ content: "Check that #wrap is empty",
+ trigger: '#wrap:empty',
+ run: () => null,
+ },
+]);
+});
diff --git a/addons/website/static/tests/tours/snippet_version.js b/addons/website/static/tests/tours/snippet_version.js
new file mode 100644
index 00000000..0e106753
--- /dev/null
+++ b/addons/website/static/tests/tours/snippet_version.js
@@ -0,0 +1,67 @@
+odoo.define("website.tour.snippet_version", function (require) {
+"use strict";
+
+var tour = require("web_tour.tour");
+
+tour.register("snippet_version", {
+ test: true,
+ url: "/",
+}, [{
+ content: "Enter edit mode",
+ trigger: 'a[data-action=edit]',
+}, {
+ content: "Drop s_test_snip snippet",
+ trigger: '#oe_snippets .oe_snippet:has(.s_test_snip) .oe_snippet_thumbnail',
+ run: "drag_and_drop #wrap",
+}, {
+ content: "Drop s_text_image snippet",
+ trigger: '#oe_snippets .oe_snippet:has(.s_text_image) .oe_snippet_thumbnail:not(.o_we_already_dragging)',
+ run: "drag_and_drop #wrap",
+}, {
+ content: "Test t-snippet and t-snippet-call: snippets have data-snippet set",
+ trigger: '#oe_snippets .o_panel_body > .oe_snippet.ui-draggable',
+ run: function () {
+ // Tests done here as all these are not visible on the page
+ const draggableSnippets = document.querySelectorAll('#oe_snippets .o_panel_body > .oe_snippet.ui-draggable > :nth-child(2)');
+ if (![...draggableSnippets].every(el => el.dataset.snippet)) {
+ console.error("error Some t-snippet are missing their template name");
+ }
+ if (!document.querySelector('#oe_snippets [data-snippet="s_test_snip"] [data-snippet="s_share"]')) {
+ console.error("error s_share t-called inside s_test_snip is missing template name");
+ }
+ if (!document.querySelector('#wrap [data-snippet="s_test_snip"] [data-snippet="s_share"]')) {
+ console.error("error Dropped a s_test_snip snippet but missing s_share template name in it");
+ }
+ },
+}, {
+ content: "Enter edit mode",
+ trigger: 'button[data-action="save"]',
+}, {
+ content: "Enter edit mode",
+ extra_trigger: 'body:not(.editor_enable)',
+ trigger: 'a[data-action=edit]',
+}, {
+ content: "Modify the version of snippets",
+ trigger: '#oe_snippets .o_panel_body > .oe_snippet',
+ run: function () {
+ document.querySelector('#oe_snippets .oe_snippet > [data-snippet="s_test_snip"]').dataset.vjs = '999';
+ document.querySelector('#oe_snippets .oe_snippet > [data-snippet="s_share"]').dataset.vcss = '999';
+ document.querySelector('#oe_snippets .oe_snippet > [data-snippet="s_text_image"]').dataset.vxml = '999';
+ },
+}, {
+ content: "Edit s_test_snip",
+ trigger: '#wrap.o_editable .s_test_snip',
+}, {
+ content: "Edit text_image",
+ extra_trigger: 'we-customizeblock-options:contains(Test snip) .snippet-option-VersionControl > we-alert',
+ trigger: '#wrap.o_editable .s_text_image',
+}, {
+ content: "Edit s_share",
+ extra_trigger: 'we-customizeblock-options:contains(Text - Image) .snippet-option-VersionControl > we-alert',
+ trigger: '#wrap.o_editable .s_share',
+}, {
+ content: "s_share is outdated",
+ extra_trigger: 'we-customizeblock-options:contains(Share) .snippet-option-VersionControl > we-alert',
+ trigger: 'body',
+}]);
+});
diff --git a/addons/website/static/tests/tours/specific_website_editor.js b/addons/website/static/tests/tours/specific_website_editor.js
new file mode 100644
index 00000000..b5125667
--- /dev/null
+++ b/addons/website/static/tests/tours/specific_website_editor.js
@@ -0,0 +1,29 @@
+odoo.define('website.tour.specific_website_editor', function (require) {
+'use strict';
+
+var tour = require('web_tour.tour');
+
+tour.register('generic_website_editor', {
+ test: true,
+}, [{
+ trigger: 'a[data-action=edit]',
+ content: 'Click edit button',
+}, {
+ trigger: 'body:not([data-hello="world"])',
+ extra_trigger: '#oe_snippets.o_loaded',
+ content: 'Check that the editor DOM matches its website-generic features',
+ run: function () {}, // Simple check
+}]);
+
+tour.register('specific_website_editor', {
+ test: true,
+}, [{
+ trigger: 'a[data-action=edit]',
+ content: 'Click edit button',
+}, {
+ trigger: 'body[data-hello="world"]',
+ extra_trigger: '#oe_snippets.o_loaded',
+ content: 'Check that the editor DOM matches its website-specific features',
+ run: function () {}, // Simple check
+}]);
+});
diff --git a/addons/website/static/tests/tours/website_navbar_menu.js b/addons/website/static/tests/tours/website_navbar_menu.js
new file mode 100644
index 00000000..e3523f69
--- /dev/null
+++ b/addons/website/static/tests/tours/website_navbar_menu.js
@@ -0,0 +1,20 @@
+odoo.define("website.tour.website_navbar_menu", function (require) {
+"use strict";
+
+var tour = require("web_tour.tour");
+
+tour.register("website_navbar_menu", {
+ test: true,
+ url: "/",
+}, [
+ {
+ content: "Ensure menus are in DOM",
+ trigger: '#top_menu .nav-item a:contains("Test Tour Menu")',
+ run: function () {}, // it's a check
+ }, {
+ content: "Ensure menus loading is done (so they are actually visible)",
+ trigger: 'body:not(:has(.o_menu_loading))',
+ run: function () {}, // it's a check
+ }
+]);
+});
diff --git a/addons/website/static/tests/tours/website_style_edition.js b/addons/website/static/tests/tours/website_style_edition.js
new file mode 100644
index 00000000..1f4033eb
--- /dev/null
+++ b/addons/website/static/tests/tours/website_style_edition.js
@@ -0,0 +1,34 @@
+odoo.define("website.tour.website_style_edition", function (require) {
+"use strict";
+
+const tour = require("web_tour.tour");
+
+const TARGET_FONT_SIZE = 30;
+
+tour.register("website_style_edition", {
+ test: true,
+ url: "/",
+}, [{
+ content: "Enter edit mode",
+ trigger: 'a[data-action=edit]',
+}, {
+ content: "Go to theme options",
+ trigger: '.o_we_customize_theme_btn',
+}, {
+ content: "Change font size",
+ trigger: '[data-variable="font-size-base"] input',
+ run: `text_blur ${TARGET_FONT_SIZE}`,
+}, {
+ content: "Save",
+ trigger: '[data-action="save"]',
+}, {
+ content: "Check the font size was properly adapted",
+ trigger: 'body:not(.editor_enable) #wrapwrap',
+ run: function (actions) {
+ const style = window.getComputedStyle(this.$anchor[0]);
+ if (style.fontSize !== `${TARGET_FONT_SIZE}px`) {
+ console.error(`Expected the font-size to be equal to ${TARGET_FONT_SIZE}px but found ${style.fontSize} instead`);
+ }
+ },
+}]);
+});
diff --git a/addons/website/static/tests/website_tests.js b/addons/website/static/tests/website_tests.js
new file mode 100644
index 00000000..8d43100b
--- /dev/null
+++ b/addons/website/static/tests/website_tests.js
@@ -0,0 +1,73 @@
+odoo.define('website.tests', function (require) {
+"use strict";
+
+var FormView = require('web.FormView');
+var testUtils = require("web.test_utils");
+
+var createView = testUtils.createView;
+
+QUnit.module('website', {
+ before: function () {
+ this.data = {
+ blog_post: {
+ fields: {
+ website_published: {string: "Available on the Website", type: "boolean"},
+ },
+ records: [{
+ id: 1,
+ website_published: false,
+ }, {
+ id: 2,
+ website_published: true,
+ }]
+ }
+ };
+ },
+}, function () {
+ QUnit.test("widget website button: display false value", async function (assert) {
+ assert.expect(2);
+
+ var form = await createView({
+ View: FormView,
+ model: 'blog_post',
+ data: this.data,
+ arch: '<form>' +
+ '<sheet>' +
+ '<div class="oe_button_box" name="button_box">' +
+ '<field name="website_published" widget="website_redirect_button"/>' +
+ '</div>' +
+ '</sheet>' +
+ '</form>',
+ res_id: 1,
+ });
+ var selector = '.oe_button_box .oe_stat_button[name="website_published"] .o_stat_text';
+ assert.containsN(form, selector, 1, "there should be one text displayed");
+ selector = '.oe_button_box .oe_stat_button[name="website_published"] .o_button_icon.fa-globe.text-danger';
+ assert.containsOnce(form, selector, "there should be one icon in red");
+ form.destroy();
+ });
+ QUnit.test("widget website button: display true value", async function (assert) {
+ assert.expect(2);
+
+ var form = await createView({
+ View: FormView,
+ model: 'blog_post',
+ data: this.data,
+ arch: '<form>' +
+ '<sheet>' +
+ '<div class="oe_button_box" name="button_box">' +
+ '<field name="website_published" widget="website_redirect_button"/>' +
+ '</div>' +
+ '</sheet>' +
+ '</form>',
+ res_id: 2,
+ });
+ var selector = '.oe_button_box .oe_stat_button[name="website_published"] .o_stat_text';
+ assert.containsN(form, selector, 1, "should be one text displayed");
+ selector = '.oe_button_box .oe_stat_button[name="website_published"] .o_button_icon.fa-globe.text-success';
+ assert.containsOnce(form, selector, "there should be one text in green");
+ form.destroy();
+ });
+});
+
+});