diff --git a/addons/html_editor/static/src/main/font/color_plugin.js b/addons/html_editor/static/src/main/font/color_plugin.js index 0bbf47b67ca7d..a9704117a4d12 100644 --- a/addons/html_editor/static/src/main/font/color_plugin.js +++ b/addons/html_editor/static/src/main/font/color_plugin.js @@ -21,8 +21,8 @@ import { isCSSColor, RGBA_REGEX, rgbaToHex, - COLOR_COMBINATION_CLASSES_REGEX, } from "@web/core/utils/colors"; +import { COLOR_COMBINATION_CLASSES_REGEX } from "@html_editor/utils/color"; import { ColorSelector } from "./color_selector"; const RGBA_OPACITY = 0.6; diff --git a/addons/web/static/src/core/color_picker/color_picker.scss b/addons/web/static/src/core/color_picker/color_picker.scss index 26c802ca0820a..160288d6aaf79 100644 --- a/addons/web/static/src/core/color_picker/color_picker.scss +++ b/addons/web/static/src/core/color_picker/color_picker.scss @@ -60,9 +60,12 @@ margin-left: 2px; } -.o_font_color_selector .o_color_button.selected { +.o_font_color_selector { // todo: check web_editor - border: 3px solid $o-enterprise-action-color; + .o_color_button.selected, + .o_custom_gradient_button.selected { + border: 3px solid $o-enterprise-action-color !important; + } } // custom gradients .custom-gradient-configurator { diff --git a/addons/web/static/src/core/color_picker/color_picker.xml b/addons/web/static/src/core/color_picker/color_picker.xml index 7b5531831bea6..fda79a5ea2c16 100644 --- a/addons/web/static/src/core/color_picker/color_picker.xml +++ b/addons/web/static/src/core/color_picker/color_picker.xml @@ -114,11 +114,11 @@
-
- +
diff --git a/addons/web/static/src/core/color_picker/gradient_picker/gradient_picker.xml b/addons/web/static/src/core/color_picker/gradient_picker/gradient_picker.xml index 059d1d8cae989..e5fe66f77a2c4 100644 --- a/addons/web/static/src/core/color_picker/gradient_picker/gradient_picker.xml +++ b/addons/web/static/src/core/color_picker/gradient_picker/gradient_picker.xml @@ -91,6 +91,7 @@
diff --git a/addons/website/static/tests/tours/snippet_background_edition.js b/addons/website/static/tests/tours/snippet_background_edition.js index 476ee34344b2a..d2c6c0b0149a1 100644 --- a/addons/website/static/tests/tours/snippet_background_edition.js +++ b/addons/website/static/tests/tours/snippet_background_edition.js @@ -16,20 +16,29 @@ const snippets = [ groupName: "Content", }, ]; +const backgroundColors = [ + { + code: "200", + hex: "#e9ecef" + }, + { + code: "800", + hex: "#343a40" + }, +] const gradients = [ 'linear-gradient(135deg, rgb(203, 94, 238) 0%, rgb(75, 225, 236) 100%)', 'linear-gradient(135deg, rgb(255, 222, 202) 0%, rgb(202, 115, 69) 100%)', ]; function typeToName(xType) { - return xType === 'cc' ? 'color combinations' : xType === 'bg' ? 'background colors' : 'gradients'; + return xType === "cc" ? "Theme" : xType === "bg" ? "Custom" : "Gradient"; } function switchTo(type, _name) { - const target = type === 'cc' ? 'color-combinations' : type === 'bg' ? 'custom-colors' : 'gradients'; const name = _name || typeToName(type); return { - trigger: `.o_we_colorpicker_switch_pane_btn[data-target="${target}"]`, + trigger: `.o_font_color_selector .btn-tab:contains("${name}")`, content: `Switch to ${name}`, run: "click", }; @@ -41,8 +50,8 @@ function addCheck(steps, checkX, checkNoX, xType, noSwitch = false) { } const name = typeToName(xType); - const selectorCheckX = checkX && `.o_we_color_btn[data-color="${checkX}"].selected`; - const selectorCheckNoX = checkNoX && `.o_we_color_btn[data-color="${checkNoX}"]:not(.selected)`; + const selectorCheckX = checkX && `[data-color="${checkX}"].selected`; + const selectorCheckNoX = checkNoX && `[data-color="${checkNoX}"]:not(.selected)`; const step = { trigger: selectorCheckX || selectorCheckNoX, content: `The correct ${name} is marked as selected`, @@ -76,7 +85,11 @@ function checkAndUpdateBackgroundColor({ if (changeType) { steps.push(switchTo(changeType)); - steps.push(changeOption('ColoredLevelBackground', `.o_we_color_btn[data-color="${change}"]`, 'background color', 'top', true)); + steps.push({ + content: "Change background color", + trigger: `.o_popover [data-color="${change}"]`, + run: "click" + }) steps.push({ trigger: finalSelector, content: "The selected colors have been applied (CC AND (BG or GRADIENT))", @@ -89,10 +102,7 @@ function checkAndUpdateBackgroundColor({ } function updateAndCheckCustomGradient({updateStep, checkGradient}) { - const steps = [updateStep, { - trigger: `:iframe #wrapwrap section.${snippets[0].id}.o_cc1`, - content: 'Color combination 1 still selected', - }]; + const steps = [ updateStep ]; addCheck(steps, checkGradient, checkGradient !== gradients[0] && gradients[0], 'gradient', true); return steps; } @@ -106,11 +116,7 @@ registerWebsitePreviewTour('snippet_background_edition', { ...clickOnSnippet(snippets[0]), // Set background image and save. -{ - content: "Click on camera icon", - trigger: ".snippet-option-ColoredLevelBackground we-button.fa-camera", - run: "click", -}, +changeOption("Text - Image", "button[data-action-id='toggleBgImage']"), { content: "Click on image", trigger: ".o_select_media_dialog img[title='test.png']", @@ -119,114 +125,101 @@ registerWebsitePreviewTour('snippet_background_edition', { ...clickOnSave(), { content: "Check that the image is set", - trigger: `:iframe section.${snippets[0].id} img[data-original-id]`, + trigger: `:iframe section.${snippets[0].id}[style*="background-image"]`, }, ...clickOnEditAndWaitEditMode(), ...clickOnSnippet(snippets[0]), // Remove background image. -{ - content: "Click on camera icon", - trigger: ".snippet-option-ColoredLevelBackground we-button.fa-camera", - run: "click", -}, +changeOption("Text - Image", "button[data-action-id='toggleBgImage']"), // Add a color combination ...checkAndUpdateBackgroundColor({ changeType: 'cc', - change: 3, - finalSelector: `:iframe .${snippets[0].id}.o_cc.o_cc3:not([class*=bg-]):not([style*="background"])`, + change: "o_cc3", + finalSelector: `:iframe .${snippets[0].id}.o_cc3:not([class*=bg-]):not([style*="background"])`, }), // Change the color combination + Check the previous one was marked as selected ...checkAndUpdateBackgroundColor({ - checkCC: 3, + checkCC: "o_cc3", changeType: 'cc', - change: 2, - finalSelector: `:iframe .${snippets[0].id}.o_cc.o_cc2:not(.o_cc3):not([class*=bg-])`, + change: "o_cc2", + finalSelector: `:iframe .${snippets[0].id}.o_cc2:not(.o_cc3):not([class*=bg-])`, }), // Check the color combination was marked as selected + Edit the bg color ...checkAndUpdateBackgroundColor({ - checkCC: 2, - checkNoCC: 3, + checkCC: "o_cc2", + checkNoCC: "o_cc3", changeType: 'bg', - change: 'black-50', - finalSelector: `:iframe .${snippets[0].id}.o_cc.o_cc2.bg-black-50`, + change: backgroundColors[0].code, + finalSelector: `:iframe .${snippets[0].id}.o_cc2.bg-${backgroundColors[0].code}`, }), // Check the current color palette selection + Change the bg color ...checkAndUpdateBackgroundColor({ - checkCC: 2, - checkBg: 'black-50', + checkCC: "o_cc2", + checkBg: backgroundColors[0].hex, changeType: 'bg', - change: '800', - finalSelector: `:iframe .${snippets[0].id}.o_cc.o_cc2.bg-800:not(.bg-black-50)`, + change: backgroundColors[1].code, + finalSelector: `:iframe .${snippets[0].id}.o_cc2.bg-${backgroundColors[1].code}:not(.bg-${backgroundColors[0].code})`, }), // Check the current color palette selection + Change the color combination -// again. It should keep the bg color class. +// again. It should remove the bg color class. ...checkAndUpdateBackgroundColor({ - checkCC: 2, - checkBg: '800', - checkNoBg: 'black-50', + checkCC: "o_cc2", + checkBg: backgroundColors[1].hex, + checkNoBg: backgroundColors[0].hex, changeType: 'cc', - change: 4, - finalSelector: `:iframe .${snippets[0].id}.o_cc.o_cc4:not(.o_cc2).bg-800`, + change: "o_cc4", + finalSelector: `:iframe .${snippets[0].id}.o_cc4:not(.o_cc2):not(.bg-${backgroundColors[1].code})`, }), // Check the current color palette status + Replace the bg color by a gradient +// It should remove the custom color class. ...checkAndUpdateBackgroundColor({ - checkCC: 4, - checkNoCC: 2, - checkBg: '800', + checkCC: "o_cc4", + checkNoCC: "o_cc2", changeType: 'gradient', change: gradients[0], - finalSelector: `:iframe .${snippets[0].id}.o_cc.o_cc4:not(.bg-800)[style*="background-image: ${gradients[0]}"]`, + finalSelector: `:iframe .${snippets[0].id}:not(.o_cc4)[style*="background-image: ${gradients[0]}"]`, }), // Check the current color palette status + Replace the gradient ...checkAndUpdateBackgroundColor({ - checkCC: 4, - checkNoBg: '800', + checkNoCC: "o_cc4", checkGradient: gradients[0], changeType: 'gradient', change: gradients[1], - finalSelector: `:iframe .${snippets[0].id}.o_cc.o_cc4[style*="background-image: ${gradients[1]}"]:not([style*="background-image: ${gradients[0]}"])`, + finalSelector: `:iframe .${snippets[0].id}[style*="background-image: ${gradients[1]}"]:not([style*="background-image: ${gradients[0]}"])`, }), // Check the current color palette selection + Change the color combination -// again. It should keep the gradient. +// again. It should remove the gradient. ...checkAndUpdateBackgroundColor({ - checkCC: 4, checkGradient: gradients[1], checkNoGradient: gradients[0], changeType: 'cc', - change: 1, - finalSelector: `:iframe .${snippets[0].id}.o_cc.o_cc1:not(.o_cc4)[style*="background-image: ${gradients[1]}"]`, + change: "o_cc1", + finalSelector: `:iframe .${snippets[0].id}.o_cc1:not([style*="background-image: ${gradients[1]}"])`, }), // Final check of the color status in the color palette ...checkAndUpdateBackgroundColor({ - checkCC: 1, - checkNoCC: 4, - checkGradient: gradients[1], + checkCC: "o_cc1", + checkNoGradient: gradients[1], }), -// Now, add an image on top of that color combination + gradient -{ - // Close the palette before selecting a media. - trigger: '.snippet-option-ColoredLevelBackground we-title', - content: 'Close palette', - run: "click", -}, -changeOption('ColoredLevelBackground', '[data-name="bg_image_toggle_opt"]'), +// Now, add an image on top of that color combination +changeOption("Text - Image", "button[data-action-id='toggleBgImage']"), { trigger: '.o_existing_attachment_cell img', content: "Select an image in the media dialog", run: "click", }, { - trigger: `:iframe .${snippets[0].id}.o_cc.o_cc1`, + trigger: `:iframe .${snippets[0].id}.o_cc1`, run: function () { const parts = weUtils.backgroundImageCssToParts( getComputedStyle(this.anchor)["background-image"] @@ -234,25 +227,22 @@ changeOption('ColoredLevelBackground', '[data-name="bg_image_toggle_opt"]'), if (!parts.url || !parts.url.startsWith('url(')) { throw new Error('An image should have been added as background.'); } - if (parts.gradient !== gradients[1]) { - throw new Error('The gradient should have been kept when adding the background image'); - } }, }, -// Replace the gradient while there is a background-image +// Add the gradient while there is a background-image. +// It should remove the image. ...checkAndUpdateBackgroundColor({ - checkCC: 1, - checkGradient: gradients[1], + checkCC: "o_cc1", changeType: 'gradient', change: gradients[0], - finalSelector: `:iframe .${snippets[0].id}.o_cc.o_cc1:not([style*="${gradients[1]}"])`, + finalSelector: `:iframe .${snippets[0].id}:not(.o_cc1):not([style*="${gradients[1]}"])`, finalRun: function () { const parts = weUtils.backgroundImageCssToParts( getComputedStyle(this.anchor)["background-image"] ); - if (!parts.url || !parts.url.startsWith('url(')) { - throw new Error('The image should have been kept when changing the gradient'); + if (parts.url && parts.url.startsWith("url(")) { + throw new Error("The image should have been removed when changing the gradien"); } if (parts.gradient !== gradients[0]) { throw new Error('The gradient should have been changed'); @@ -263,42 +253,40 @@ changeOption('ColoredLevelBackground', '[data-name="bg_image_toggle_opt"]'), // Customize gradient changeBackgroundColor(), switchTo('gradient'), +{ + content: "Click on 'Custom' button to show custom gradient options", + trigger: ".o_popover .o_custom_gradient_button", + run: "click" +}, // Avoid navigating across tabs to maintain current editor state // Step colors ...updateAndCheckCustomGradient({ updateStep: { - trigger: '.colorpicker .o_custom_gradient_scale', + trigger: ".o_popover .gradient-preview", content: 'Add step', - run() { - // TODO: use run: "click", instead - this.anchor.click(); - } + run: "click" }, - checkGradient: 'linear-gradient(135deg, rgb(203, 94, 238) 0%, rgb(203, 94, 238) 0%, rgb(75, 225, 236) 100%)', + checkGradient: "linear-gradient(135deg, rgb(203, 94, 238) 0%, rgb(139, 160, 237) 50%, rgb(75, 225, 236) 100%)", }), ...updateAndCheckCustomGradient({ updateStep: { - trigger: '.colorpicker .o_slider_multi input.active', + trigger: ".o_popover .gradient-colors input.active", content: 'Move step', - run(helpers) { - this.anchor.value = 45; - helpers.click(); - }, + run: "range 45" }, - checkGradient: 'linear-gradient(135deg, rgb(203, 94, 238) 0%, rgb(203, 94, 238) 45%, rgb(75, 225, 236) 100%)', + checkGradient: "linear-gradient(135deg, rgb(203, 94, 238) 0%, rgb(139, 160, 237) 45%, rgb(75, 225, 236) 100%)", }), ...updateAndCheckCustomGradient({ updateStep: { - trigger: '.colorpicker .o_color_picker_inputs .o_hex_div input', + trigger: ".o_popover .o_color_picker_inputs .o_hex_div input", content: 'Pick step color', - // TODO: remove && click - run: "edit #FF0000 && click .o_color_picker_inputs", + run: "edit #FF0000" }, checkGradient: 'linear-gradient(135deg, rgb(203, 94, 238) 0%, rgb(255, 0, 0) 45%, rgb(75, 225, 236) 100%)', }), ...updateAndCheckCustomGradient({ updateStep: { - trigger: '.colorpicker .o_remove_color', + trigger: ".o_popover .gradient-color-bin a", content: 'Delete step', run: 'click', }, @@ -307,7 +295,7 @@ switchTo('gradient'), // Linear ...updateAndCheckCustomGradient({ updateStep: { - trigger: '.colorpicker input[data-name="angle"]', + trigger: ".o_popover input[name='angle']", content: 'Change angle', run: "edit 50 && click .o_color_picker_inputs", }, @@ -316,88 +304,64 @@ switchTo('gradient'), // Radial ...updateAndCheckCustomGradient({ updateStep: { - trigger: '.colorpicker we-button[data-gradient-type="radial-gradient"]', + trigger: ".o_popover button:contains('Radial')", content: 'Switch to Radial', run: 'click', }, - checkGradient: 'radial-gradient(circle farthest-side at 25% 25%, rgb(203, 94, 238) 0%, rgb(75, 225, 236) 100%)', + checkGradient: "radial-gradient(circle closest-side at 25% 25%, rgb(203, 94, 238) 0%, rgb(75, 225, 236) 100%)", }), ...updateAndCheckCustomGradient({ updateStep: { - trigger: '.colorpicker input[data-name="positionX"]', + trigger: ".o_popover input[name='positionX']", content: 'Change X position', run: "edit 33 && click .o_color_picker_inputs", }, - checkGradient: 'radial-gradient(circle farthest-side at 33% 25%, rgb(203, 94, 238) 0%, rgb(75, 225, 236) 100%)', + checkGradient: "radial-gradient(circle closest-side at 33% 25%, rgb(203, 94, 238) 0%, rgb(75, 225, 236) 100%)", }), ...updateAndCheckCustomGradient({ updateStep: { - trigger: '.colorpicker input[data-name="positionY"]', + trigger: ".o_popover input[name='positionY']", content: 'Change Y position', run: "edit 75 && click .o_color_picker_inputs", }, - checkGradient: 'radial-gradient(circle farthest-side at 33% 75%, rgb(203, 94, 238) 0%, rgb(75, 225, 236) 100%)', + checkGradient: "radial-gradient(circle closest-side at 33% 75%, rgb(203, 94, 238) 0%, rgb(75, 225, 236) 100%)", }), ...updateAndCheckCustomGradient({ updateStep: { - trigger: '.colorpicker we-button[data-gradient-size="closest-side"]', + trigger: ".o_popover button[title='Extend to the farthest side']", content: 'Change color spread size', run: 'click', }, - checkGradient: 'radial-gradient(circle closest-side at 33% 75%, rgb(203, 94, 238) 0%, rgb(75, 225, 236) 100%)', + checkGradient: "radial-gradient(circle farthest-side at 33% 75%, rgb(203, 94, 238) 0%, rgb(75, 225, 236) 100%)", }), // Revert to predefined gradient { - trigger: `.o_we_color_btn[data-color="${gradients[0]}"]`, + trigger: `.o_colorpicker_sections button[data-color="${gradients[0]}"]`, content: `Revert to predefiend gradient ${gradients[0]}`, run: 'click', }, -// Replace the gradient by a bg color +// Replace the gradient by a bg color. It should remove the gradient. ...checkAndUpdateBackgroundColor({ - checkCC: 1, checkGradient: gradients[0], - checkNoGradient: gradients[1], changeType: 'bg', - change: 'black-75', - finalSelector: `:iframe .${snippets[0].id}.o_cc.o_cc1.bg-black-75[style^="background-image: url("]:not([style*="${gradients[0]}"])` + change: backgroundColors[1].code, + finalSelector: `:iframe .${snippets[0].id}.bg-${backgroundColors[1].code}:not([style*="background-image: ${gradients[0]}"])` }), // Re-add a gradient ...checkAndUpdateBackgroundColor({ - checkCC: 1, - checkBg: 'black-75', + checkBg: backgroundColors[1].hex, checkNoGradient: gradients[0], changeType: 'gradient', change: gradients[1], - finalSelector: `:iframe .${snippets[0].id}.o_cc.o_cc1:not(.bg-black-75)`, - finalRun() { - const parts = weUtils.backgroundImageCssToParts( - getComputedStyle(this.anchor)["background-image"] - ); - if (!parts.url || !parts.url.startsWith('url(')) { - throw new Error('The image should have been kept when re-adding the gradient'); - } - if (parts.gradient !== gradients[1]) { - throw new Error('The gradient should have been re-added'); - } - }, + finalSelector: `:iframe .${snippets[0].id}[style*="background-image: ${gradients[1]}"]:not(.bg-${backgroundColors[1].code})`, }), -// Final check of color selection and removing the image -...checkAndUpdateBackgroundColor({ - checkCC: 1, - checkNoBg: 'black-75', - checkGradient: gradients[1], -}), -changeOption('ColoredLevelBackground', '[data-name="bg_image_toggle_opt"]', 'image toggle', 'top', true), -{ - trigger: `:iframe .${snippets[0].id}.o_cc.o_cc1[style*="background-image: ${gradients[1]}"]`, -}, - -// Now removing all colors via the 'None' button (note: colorpicker still opened) +// Now removing all colors via the 'None' button +changeBackgroundColor(), { - trigger: '.o_colorpicker_reset', + trigger: ".o_popover button[title='Reset']", content: "Click on the None button of the color palette", run: "click", }, diff --git a/addons/website/static/tests/tours/snippet_editor_panel_options.js b/addons/website/static/tests/tours/snippet_editor_panel_options.js index 992e48bc9a938..6c4a1a0e82a09 100644 --- a/addons/website/static/tests/tours/snippet_editor_panel_options.js +++ b/addons/website/static/tests/tours/snippet_editor_panel_options.js @@ -1,5 +1,6 @@ import { changeOption, + changeOptionInPopover, clickOnSave, insertSnippet, goBackToBlocks, @@ -7,19 +8,9 @@ import { } from '@website/js/tours/tour_utils'; import { browser } from '@web/core/browser/browser'; -registerWebsitePreviewTour('snippet_editor_panel_options', { - url: '/', - edition: true, -}, () => [ -...insertSnippet({ - id: 's_text_image', - name: 'Text - Image', - groupName: "Content", -}), -// Test keeping the text selection when using the width option. -{ +const selectParagraphTextInSnippet = (trigger) => ({ content: "Select the first paragraph.", - trigger: ':iframe .s_text_image p', + trigger: trigger, async run(actions) { await actions.click(); const range = document.createRange(); @@ -28,45 +19,59 @@ registerWebsitePreviewTour('snippet_editor_panel_options', { selection.removeAllRanges(); selection.addRange(range); }, -}, { - content: "The text toolbar should be visible. The paragraph should be selected.", - trigger: '#oe_snippets .o_we_customize_panel > #o_we_editor_toolbar_container', +}); + +const checkIfParagraphSelected = (trigger) => ({ + content: "Check if the paragraph is selected.", + trigger: trigger, run() { - const iframeDocument = document.querySelector('.o_iframe').contentDocument; - const pText = iframeDocument.querySelector('.s_text_image p').textContent; - const selection = iframeDocument.getSelection().toString(); + const pText = this.anchor.textContent; + const selection = this.anchor.ownerDocument.getSelection().toString(); if (pText !== selection) { console.error("The paragraph was not correctly selected."); } }, -}, { +}); + +const checkIfTextToolbarVisible = { + content: "Check if the text toolbar is visible", + trigger: ".o-we-toolbar", +}; + +registerWebsitePreviewTour('snippet_editor_panel_options', { + url: '/', + edition: true, +}, () => [ +...insertSnippet({ + id: 's_text_image', + name: 'Text - Image', + groupName: "Content", +}), +// Test keeping the text selection when using the width option. +selectParagraphTextInSnippet(":iframe .s_text_image p"), +checkIfParagraphSelected(":iframe .s_text_image p"), +checkIfTextToolbarVisible, +{ content: "Click on the width option.", - trigger: '[data-select-class="o_container_small"]', + trigger: "[data-action-param='o_container_small']", run: "click", }, { content: "The snippet should have the correct class.", trigger: ':iframe .s_text_image > .o_container_small', -}, { - content: "The text toolbar should still be visible, and the text still selected.", - trigger: '#oe_snippets .o_we_customize_panel > #o_we_editor_toolbar_container', - run() { - const iframeDocument = document.querySelector('.o_iframe').contentDocument; - const pText = iframeDocument.querySelector('.s_text_image p').textContent; - const selection = iframeDocument.getSelection().toString(); - if (pText !== selection) { - console.error("The paragraph text selection was lost."); - } - }, }, +checkIfParagraphSelected(":iframe .s_text_image p"), // Test the anchor option. { content: "Click on the anchor option", - trigger: '#oe_snippets .snippet-option-anchor we-button', + trigger: "[data-container-title='Text - Image'] .oe_snippet_anchor", async run(helpers) { // Patch and ignore write on clipboard in tour as we don't have permissions const oldWriteText = browser.navigator.clipboard.writeText; browser.navigator.clipboard.writeText = () => { console.info('Copy in clipboard ignored!') }; await helpers.click(); + // Restore the writeText after a short delay to avoid reverting it + // before the plugin function has been completed + await new Promise(resolve => setTimeout(resolve, 100)); browser.navigator.clipboard.writeText = oldWriteText; } }, { @@ -81,7 +86,7 @@ registerWebsitePreviewTour('snippet_editor_panel_options', { console.error('The anchor option should target the frontend'); } - const iframeDocument = document.querySelector('.o_iframe').contentDocument; + const iframeDocument = document.querySelector(".o_iframe_container iframe").contentDocument; const snippetId = iframeDocument.querySelector('.s_text_image').id; if (!url || url.indexOf(snippetId) < 0) { console.error('The anchor option does not target the correct snippet.'); @@ -95,38 +100,11 @@ goBackToBlocks(), name: 'Text', groupName: "Text", }), +selectParagraphTextInSnippet(":iframe .s_text_block p"), +checkIfParagraphSelected(":iframe .s_text_block p"), +checkIfTextToolbarVisible, +...changeOptionInPopover("Text", "Layout", "[data-action-value='3']"), { - content: "Select the first paragraph.", - trigger: ':iframe .s_text_block p', - async run(actions) { - await actions.click(); - const range = document.createRange(); - const selection = this.anchor.ownerDocument.getSelection(); - range.selectNodeContents(this.anchor); - selection.removeAllRanges(); - selection.addRange(range); - }, -}, { - content: "The text toolbar should be visible. The paragraph should be selected.", - trigger: '#oe_snippets .o_we_customize_panel > #o_we_editor_toolbar_container', - run() { - const iframeDocument = document.querySelector('.o_iframe').contentDocument; - const pText = iframeDocument.querySelector('.s_text_block p').textContent; - const selection = iframeDocument.getSelection().toString(); - if (pText !== selection) { - console.error("The paragraph was not correctly selected."); - } - }, -}, { - content: "Click on the columns option.", - trigger: '.snippet-option-layout_column we-select', - run: "click", -}, -{ - content: "Change the number of columns.", - trigger: '.snippet-option-layout_column [data-select-count="3"]', - run: "click", -}, { content: "The snippet should have the correct number of columns.", trigger: ':iframe .s_text_block .container > .row .col-lg-4:eq(3)', run() { @@ -134,92 +112,28 @@ goBackToBlocks(), console.error("The snippet does not have the correct number of columns"); } }, -}, { - content: "The text toolbar should still be visible, and the text still selected.", - trigger: '#oe_snippets .o_we_customize_panel > #o_we_editor_toolbar_container', - run() { - const iframeDocument = document.querySelector('.o_iframe').contentDocument; - const pText = iframeDocument.querySelector('.s_text_block p').textContent; - const selection = iframeDocument.getSelection().toString(); - if (pText !== selection) { - console.error("The paragraph text selection was lost."); - } - }, }, +checkIfParagraphSelected(":iframe .s_text_block p"), // Test keeping the text selection when removing all columns of a snippet. +...changeOptionInPopover("Text", "Layout", "[data-action-value='0']"), { - content: "Click on the columns option.", - trigger: '.snippet-option-layout_column we-select', - run: "click", -}, -{ - content: "Change the number of columns.", - trigger: '.snippet-option-layout_column [data-select-count="0"]', - run: "click", -}, { content: "The snippet should have the correct number of columns.", trigger: ':iframe .s_text_block .container:not(:has(.row))', -}, { - content: "The text toolbar should still be visible, and the text still selected.", - trigger: '#oe_snippets .o_we_customize_panel > #o_we_editor_toolbar_container', - run() { - const iframeDocument = document.querySelector('.o_iframe').contentDocument; - const pText = iframeDocument.querySelector('.s_text_block p').textContent; - const selection = iframeDocument.getSelection().toString(); - if (pText !== selection) { - console.error("The paragraph text selection was lost."); - } - }, }, +checkIfParagraphSelected(":iframe .s_text_block p"), // Test keeping the text selection when toggling the grid mode. -changeOption("layout_column", 'we-button[data-name="grid_mode"]'), +changeOption("Text", "[data-action-id='setGridLayout']"), { content: "The snippet row should have the grid mode class.", trigger: ":iframe .s_text_block .row.o_grid_mode", -}, { - content: "The text toolbar should still be visible, and the text still selected.", - trigger: "#oe_snippets .o_we_customize_panel > #o_we_editor_toolbar_container", - run() { - const iframeDocument = document.querySelector(".o_iframe").contentDocument; - const pText = iframeDocument.querySelector(".s_text_block p").textContent; - const selection = iframeDocument.getSelection().toString(); - if (pText !== selection) { - console.error("The paragraph text selection was lost."); - } - }, }, -// Test keeping the text selection when toggling back the normal mode. -changeOption("layout_column", 'we-button[data-name="normal_mode"]'), +checkIfParagraphSelected(":iframe .s_text_block p"), +// Test keeping the text selection when toggling back the column mode. +changeOption("Text", "[data-action-id='setColumnLayout']"), { content: "The snippet row should not have the grid mode class anymore.", trigger: ":iframe .s_text_block .row:not(.o_grid_mode)", -}, { - content: "The text toolbar should still be visible, and the text still selected.", - trigger: "#oe_snippets .o_we_customize_panel > #o_we_editor_toolbar_container", - run() { - const iframeDocument = document.querySelector(".o_iframe").contentDocument; - const pText = iframeDocument.querySelector(".s_text_block p").textContent; - const selection = iframeDocument.getSelection().toString(); - if (pText !== selection) { - console.error("The paragraph text selection was lost."); - } - }, -}, -// Test close dropdowns if click anywhere outside the dropdown -{ - content: "Open text style dropdown.", - trigger: "#style button.dropdown-toggle", - run: "click", -}, { - content: "Check if dropdown opened correctly.", - trigger: "#style button[data-bs-toggle=dropdown][aria-expanded=true]", -}, { - content: "Click on the first paragraph again.", - trigger: ":iframe .s_text_block p", - run: "click", -}, { - content: "Check if dropdown closed correctly.", - trigger: "#style button[data-bs-toggle=dropdown][aria-expanded=false]", }, +checkIfParagraphSelected(":iframe .s_text_block p"), ...clickOnSave(), ]); diff --git a/addons/website/tests/test_ui.py b/addons/website/tests/test_ui.py index 48a007d6b0fa2..a69b329035387 100644 --- a/addons/website/tests/test_ui.py +++ b/addons/website/tests/test_ui.py @@ -433,7 +433,6 @@ def test_10_website_conditional_visibility(self): self.start_tour(self.env['website'].get_client_action_url('/'), 'conditional_visibility_4', login='admin') self.start_tour(self.env['website'].get_client_action_url('/'), 'conditional_visibility_5', login='admin') - @unittest.skip def test_11_website_snippet_background_edition(self): self.env['ir.attachment'].create({ 'public': True, @@ -527,7 +526,6 @@ def test_18_website_snippets_menu_tabs(self): def test_19_website_page_options(self): self.start_tour("/odoo", "website_page_options", login="admin") - @unittest.skip def test_20_snippet_editor_panel_options(self): self.start_tour('/@/', 'snippet_editor_panel_options', login='admin') diff --git a/addons/website/tests/test_website_form_editor.py b/addons/website/tests/test_website_form_editor.py index b37725cb6fb36..8aeb2d3c51f2c 100644 --- a/addons/website/tests/test_website_form_editor.py +++ b/addons/website/tests/test_website_form_editor.py @@ -61,8 +61,6 @@ def test_contactus_form_email_stay_dynamic(self): def test_website_form_editable_content(self): self.start_tour('/', 'website_form_editable_content', login="admin") - # TODO @mysterious-egg: new tour - @unittest.skip def test_website_form_special_characters(self): self.start_tour('/', 'website_form_special_characters', login='admin') mail = self.env['mail.mail'].search([], order='id desc', limit=1)