diff --git a/addons/website/static/src/snippets/s_popup/000.js b/addons/website/static/src/snippets/s_popup/000.js index 99b628d987b..c3013ccced2 100644 --- a/addons/website/static/src/snippets/s_popup/000.js +++ b/addons/website/static/src/snippets/s_popup/000.js @@ -4,7 +4,7 @@ import config from "web.config"; import publicWidget from "web.public.widget"; import {getCookie, setCookie} from "web.utils.cookies"; import dom from "web.dom"; -import throttleForAnimation from "@web/core/utils/timing"; +import {throttleForAnimation} from "@web/core/utils/timing"; // TODO In master, export this class too or merge it with PopupWidget const SharedPopupWidget = publicWidget.Widget.extend({ diff --git a/addons/website/static/tests/tours/snippet_popup_and_animations.js b/addons/website/static/tests/tours/snippet_popup_and_animations.js new file mode 100644 index 00000000000..6c99fed4345 --- /dev/null +++ b/addons/website/static/tests/tours/snippet_popup_and_animations.js @@ -0,0 +1,118 @@ +/** @odoo-module */ + +import wTourUtils from "website.tour_utils"; + +const snippets = [ + { + id: "s_popup", + name: "Popup", + }, + { + id: "s_media_list", + name: "Media List", + }, + { + id: "s_three_columns", + name: "Columns", + }, +]; + +const setOnScrollAnim = function () { + return [ + wTourUtils.changeOption("WebsiteAnimate", 'we-select[data-is-animation-type-selection="true"] we-toggler'), + wTourUtils.changeOption("WebsiteAnimate", 'we-button[data-animation-mode="onScroll"]'), + wTourUtils.changeOption("WebsiteAnimate", 'we-select[data-name="animation_effect_opt"] we-toggler'), + wTourUtils.changeOption("WebsiteAnimate", 'we-button[data-name="o_anim_slide_in_opt"]'), + ]; +}; + +wTourUtils.registerWebsitePreviewTour("snippet_popup_and_animations", { + test: true, + url: "/", + edition: true, +}, [ + wTourUtils.dragNDrop(snippets[1]), // Media List + wTourUtils.dragNDrop(snippets[1]), // Media List + wTourUtils.dragNDrop(snippets[2]), // Columns + wTourUtils.clickOnElement("3rd columns", "iframe .s_three_columns .row > :last-child"), + ...setOnScrollAnim(), + { + content: "Open the Cookies Bar.", + trigger: ".o_we_invisible_el_panel .o_we_invisible_entry", + }, + { + content: "Scroll to top", + trigger: "iframe #wrapwrap", + extra_trigger: "iframe #website_cookies_bar:not(.d-none)", + run: function () { + const animatedColumnEl = this.$anchor[0].querySelector(".s_three_columns .row > :last-child"); + // When the animated element is fully visible, its animation delay + // should be rounded to -1 in the following condition. + if (Math.round(parseFloat(animatedColumnEl.style.animationDelay)) !== -1) { + console.error("The scroll animation in the page did not start properly with the cookies bar open."); + } + this.$anchor[0].scrollTo({ + top: 0, + left: 0, + behavior: 'smooth' + }); + }, + }, + { + content: "Wait for the page to be scrolled to the top.", + trigger: "iframe .s_three_columns .row > :last-child:not(.o_animating)", + extra_trigger: "iframe header#top:not(.o_header_affixed)", + run: function () { + // If the column has been animated successfully, the animation delay + // should be set to approximately zero when it is not visible. + // The main goal of the following condition is to verify if the + // animation delay is being updated as expected. + if (Math.round(parseFloat(this.$anchor[0].style.animationDelay)) !== 0) { + console.error("The scroll animation in the page did not end properly with the cookies bar open."); + } + }, + }, + { + content: "Close the Cookies Bar.", + trigger: ".o_we_invisible_el_panel .o_we_invisible_entry", + run: "click", + }, + wTourUtils.dragNDrop(snippets[0]), // Popup + wTourUtils.dragNDrop(snippets[1]), // Media List + { + content: "Drag the Columns building block and drop it at the bottom of the popup.", + trigger: '#oe_snippets .oe_snippet[name="Columns"] .oe_snippet_thumbnail:not(.o_we_already_dragging)', + extra_trigger: ".o_website_preview.editor_enable.editor_has_snippets", + run: "drag_and_drop iframe #wrapwrap .modal-content .s_media_list .container > .row > :last-child", + }, + wTourUtils.clickOnElement("3rd columns", "iframe .s_popup .s_three_columns .row > :last-child"), + ...setOnScrollAnim(), + { + content: "Verify the animation delay of the animated element in the popup at the beginning", + trigger: "iframe .s_popup .modal", + run: function () { + const animatedColumnEl = this.$anchor[0].querySelector(".s_three_columns .row > :last-child"); + // When the animated element is fully visible, its animation delay + // should be rounded to -1 in the following condition. + if (Math.round(parseFloat(animatedColumnEl.style.animationDelay)) !== -1) { + console.error("The scroll animation in the modal did not start properly."); + } + this.$anchor[0].closest(".modal").scrollTo({ + top: 0, + left: 0, + behavior: 'smooth' + }); + }, + }, + { + content: "Wait until the column is no longer animated/visible.", + trigger: "iframe .s_popup .s_three_columns .row > :last-child:not(.o_animating)", + run: function () { + // If the column has been animated successfully, the animation delay + // should be set to approximately zero when it is not visible. + if (Math.round(parseFloat(this.$anchor[0].style.animationDelay)) !== 0) { + console.error("The scroll animation in the modal did not end properly."); + } + }, + }, +]); diff --git a/addons/website/static/tests/tours/snippet_popup_and_scrollbar.js b/addons/website/static/tests/tours/snippet_popup_and_scrollbar.js new file mode 100644 index 00000000000..b81a4693592 --- /dev/null +++ b/addons/website/static/tests/tours/snippet_popup_and_scrollbar.js @@ -0,0 +1,133 @@ +/** @odoo-module */ + +import wTourUtils from "website.tour_utils"; + +const snippets = [ + { + id: "s_popup", + name: "Popup", + }, + { + id: "s_media_list", + name: "Media List", + }, +]; + +const checkScrollbar = function (hasScrollbar) { + return { + content: `Check that the #wrapwrap ${hasScrollbar ? "has" : "does not have"} a vertical scrollbar.`, + trigger: `iframe ${hasScrollbar ? "body:not(.modal-open)" : "body.modal-open"}`, + run: function () { + const wrapwrapEl = this.$anchor[0].querySelector("#wrapwrap"); + const wrapwrapStyle = window.getComputedStyle(wrapwrapEl); + if (!hasScrollbar && (wrapwrapStyle.overflow !== "hidden" || parseFloat(wrapwrapStyle.paddingRight) < 1)) { + console.error("error The #wrapwrap vertical scrollbar should be hidden"); + } else if (hasScrollbar && (wrapwrapStyle.overflow === "hidden" || parseFloat(wrapwrapStyle.paddingRight) > 0)) { + console.error("error The #wrapwrap vertical scrollbar should be displayed"); + } + }, + }; +}; + +const toggleBackdrop = function () { + return wTourUtils.changeOption('SnippetPopup', 'we-button[data-name="popup_backdrop_opt"] we-checkbox', 'backdrop'); +}; + +wTourUtils.registerWebsitePreviewTour("snippet_popup_and_scrollbar", { + test: true, + url: "/", + edition: true, +}, [ + wTourUtils.dragNDrop(snippets[1]), // Media List + wTourUtils.dragNDrop(snippets[0]), // Popup + checkScrollbar(false), + { + content: 'Click on the s_popup snippet', + in_modal: false, + trigger: 'iframe .s_popup .modal', + }, + toggleBackdrop(), // hide Popup backdrop + checkScrollbar(true), + wTourUtils.goBackToBlocks(), + { + content: "Drag the Media List block and drop it in the popup.", + trigger: "#oe_snippets .oe_snippet:has(> [data-snippet='s_media_list']) .oe_snippet_thumbnail", + run: "drag_and_drop iframe #wrap .s_popup .modal-content.oe_structure", + }, + checkScrollbar(false), + { + content: "Select the Media List snippet in the Popup.", + trigger: "iframe #wrap .s_popup .modal-content .s_media_list", + }, + { + content: "Remove the Media List snippet in the Popup.", + trigger: "iframe .oe_overlay.oe_active .oe_snippet_remove", + }, + checkScrollbar(true), + toggleBackdrop(), // show Popup backdrop + checkScrollbar(false), + { + content: "Close the Popup.", + trigger: ".o_we_invisible_el_panel .o_we_invisible_entry", + }, + checkScrollbar(true), + { + content: "Open the Cookies Bar.", + trigger: ".o_we_invisible_el_panel .o_we_invisible_entry:last-child", + }, + checkScrollbar(true), + toggleBackdrop(), // show Cookies Bar backdrop + checkScrollbar(false), + toggleBackdrop(), // hide Cookies Bar backdrop + checkScrollbar(true), + { + content: "Open the Popup.", + trigger: ".o_we_invisible_el_panel .o_we_invisible_entry", + }, + checkScrollbar(false), + wTourUtils.goBackToBlocks(), + { + content: "Drag the Media List block and drop it in the popup.", + trigger: "#oe_snippets .oe_snippet:has(> [data-snippet='s_media_list']) .oe_snippet_thumbnail", + run: "drag_and_drop iframe #wrap .s_popup .modal-content.oe_structure", + }, + checkScrollbar(false), + { + content: 'Click on the s_popup snippet', + in_modal: false, + trigger: 'iframe .s_popup .modal', + }, + { + content: "Remove the s_popup snippet", + trigger: ".o_we_customize_panel we-customizeblock-options:contains('Popup') we-button.oe_snippet_remove:first", + in_modal: false, + run: "click", + }, + checkScrollbar(true), + wTourUtils.goBackToBlocks(), + { + content: "Drag a Media List snippet and drop it in the Cookies Bar.", + trigger: "#oe_snippets .oe_snippet:has(> [data-snippet='s_media_list']) .oe_snippet_thumbnail", + run: "drag_and_drop iframe #website_cookies_bar .modal-content.oe_structure", + }, + { + content: "Select the Media List snippet in the Cookies Bar.", + trigger: "iframe #website_cookies_bar .modal-content .s_media_list", + }, + { + content: "Duplicate the Media List snippet", + trigger: ".o_we_customize_panel we-customizeblock-options:contains('Media List') we-button.oe_snippet_clone:first", + in_modal: false, + run: "click", + }, + checkScrollbar(false), + { + content: "Remove the first Media List snippet in the Cookies Bar.", + trigger: "iframe .oe_overlay.oe_active .oe_snippet_remove", + }, + { + content: "Remove the second Media List snippet in the Cookies Bar.", + trigger: "iframe .oe_overlay.oe_active .oe_snippet_remove", + }, + checkScrollbar(true), +]); diff --git a/addons/website/tests/test_snippets.py b/addons/website/tests/test_snippets.py index 715a034b758..c4de1db2b8e 100644 --- a/addons/website/tests/test_snippets.py +++ b/addons/website/tests/test_snippets.py @@ -80,3 +80,9 @@ class TestSnippets(HttpCase): def test_12_snippet_images_wall(self): self.start_tour('/', 'snippet_images_wall', login='admin') + + def test_snippet_popup_with_scrollbar_and_animations(self): + website = self.env.ref('website.default_website') + website.cookies_bar = True + self.start_tour(self.env['website'].get_client_action_url('/'), 'snippet_popup_and_scrollbar', login='admin') + self.start_tour(self.env['website'].get_client_action_url('/'), 'snippet_popup_and_animations', login='admin')