@@ -4,7 +4,7 @@ import { EditWebsiteSystrayItem } from "@html_builder/website_preview/edit_websi
44import { setContent , setSelection } from "@html_editor/../tests/_helpers/selection" ;
55import { insertText } from "@html_editor/../tests/_helpers/user_actions" ;
66import { expect , test } from "@odoo/hoot" ;
7- import { animationFrame , manuallyDispatchProgrammaticEvent } from "@odoo/hoot-dom" ;
7+ import { animationFrame , manuallyDispatchProgrammaticEvent , queryAllTexts } from "@odoo/hoot-dom" ;
88import { contains , mockService , onRpc , patchWithCleanup } from "@web/../tests/web_test_helpers" ;
99import { defineWebsiteModels , invisibleEl , setupWebsiteBuilder } from "./website_helpers" ;
1010
@@ -59,13 +59,15 @@ test("invisible elements in translate mode", async () => {
5959
6060test ( "translate text" , async ( ) => {
6161 const resultSave = [ ] ;
62- onRpc ( "ir.ui.view" , "web_update_field_translations" , ( { args } ) => {
63- resultSave . push ( args [ 2 ] [ "fr_BE" ] [ "sourceSha" ] ) ;
62+ onRpc ( "/web_editor/field/translation/update" , async ( data ) => {
63+ const { params } = await data . json ( ) ;
64+ resultSave . push ( params . translations . fr_BE . sourceSha ) ;
6465 return true ;
6566 } ) ;
66- const editor = await setupSidebarBuilderForTranslation ( {
67+ const { getEditor } = await setupSidebarBuilderForTranslation ( {
6768 websiteContent : getTranslateEditable ( "Hello" ) ,
6869 } ) ;
70+ const editor = getEditor ( ) ;
6971 const textNode = editor . editable . querySelector ( "span" ) . firstChild ;
7072 setSelection ( { anchorNode : textNode , anchorOffset : 1 } ) ;
7173 await insertText ( editor , "1" ) ;
@@ -75,9 +77,10 @@ test("translate text", async () => {
7577} ) ;
7678
7779test ( "add text in translate mode do not split" , async ( ) => {
78- const editor = await setupSidebarBuilderForTranslation ( {
80+ const { getEditor } = await setupSidebarBuilderForTranslation ( {
7981 websiteContent : getTranslateEditable ( "Hello" ) ,
8082 } ) ;
83+ const editor = getEditor ( ) ;
8184 setContent ( editor . editable . querySelector ( "#wrap" ) , getTranslateEditable ( "Hello[]" ) ) ;
8285 // Event trigger when you press "Enter" => create a new paragraph
8386 await manuallyDispatchProgrammaticEvent ( editor . editable , "beforeinput" , {
@@ -104,6 +107,79 @@ test("404 page in translate mode", async () => {
104107 expect ( ".o_popover .o_edit_website_dropdown_item:contains('Create page')" ) . toHaveCount ( 1 ) ;
105108} ) ;
106109
110+ test ( "translate attribute" , async ( ) => {
111+ const resultSave = [ ] ;
112+ onRpc ( "/web_editor/field/translation/update" , async ( data ) => {
113+ const { params } = await data . json ( ) ;
114+ resultSave . push ( params . translations . fr_BE . sourceSha ) ;
115+ return true ;
116+ } ) ;
117+ onRpc ( "ir.ui.view" , "save" , ( { args } ) => true ) ;
118+ await setupSidebarBuilderForTranslation ( {
119+ websiteContent : `
120+ <img src="/web/image/website.s_text_image_default_image" class="img img-fluid mx-auto rounded o_editable" loading="lazy" title="<span data-oe-model="ir.ui.view" data-oe-id="544" data-oe-field="arch_db" data-oe-translation-state="to_translate" data-oe-translation-source-sha="sourceSha">title</span>" style="" contenteditable="false"></img>
121+ ` ,
122+ } ) ;
123+ await contains ( ".modal .btn:contains(Ok, never show me this again)" ) . click ( ) ;
124+ await contains ( ":iframe img" ) . click ( ) ;
125+ await contains ( ".modal .modal-body input" ) . edit ( "titre" ) ;
126+ await contains ( ".modal .btn:contains(Ok)" ) . click ( ) ;
127+ await contains ( ".o-snippets-top-actions button:contains(Save)" ) . click ( ) ;
128+ expect ( resultSave . length ) . toBe ( 1 ) ;
129+ expect ( resultSave [ 0 ] ) . toBe ( "titre" ) ;
130+ } ) ;
131+
132+ test ( "translate attribute history" , async ( ) => {
133+ const { getEditableContent } = await setupSidebarBuilderForTranslation ( {
134+ websiteContent : `
135+ <img src="/web/image/website.s_text_image_default_image" class="img img-fluid o_editable" loading="lazy" title="<span data-oe-model="ir.ui.view" data-oe-id="544" data-oe-field="arch_db" data-oe-translation-state="to_translate" data-oe-translation-source-sha="sourceSha">title</span>" style="" contenteditable="false"></img>
136+ ` ,
137+ } ) ;
138+ const editable = getEditableContent ( ) ;
139+ await contains ( ".modal .btn:contains(Ok, never show me this again)" ) . click ( ) ;
140+ await contains ( ":iframe img" ) . click ( ) ;
141+ await contains ( ".modal .modal-body input" ) . edit ( "titre" ) ;
142+ await contains ( ".modal .btn:contains(Ok)" ) . click ( ) ;
143+ const getImg = ( { titleName, translated } ) =>
144+ `<img src="/web/image/website.s_text_image_default_image" class="img img-fluid o_editable o_translatable_attribute${
145+ translated ? " oe_translated" : ""
146+ } " loading="lazy" title="${ titleName } " style="" contenteditable="false" data-oe-translation-state="to_translate"></img>`;
147+ expect ( editable ) . toHaveInnerHTML ( getImg ( { titleName : "titre" , translated : true } ) ) ;
148+ await contains ( ".o-snippets-menu button.fa-undo" ) . click ( ) ;
149+ expect ( editable ) . toHaveInnerHTML ( getImg ( { titleName : "title" , translated : false } ) ) ;
150+ await contains ( ":iframe img" ) . click ( ) ;
151+ expect ( ".modal .modal-body input" ) . toHaveValue ( "title" ) ;
152+ } ) ;
153+
154+ test ( "translate select" , async ( ) => {
155+ await setupSidebarBuilderForTranslation ( {
156+ websiteContent : `
157+ <div class="row s_col_no_resize s_col_no_bgcolor">
158+ <label class="col-form-label col-sm-auto s_website_form_label">
159+ <span data-oe-model="ir.ui.view" data-oe-id="544" data-oe-field="arch_db" data-oe-translation-state="to_translate" data-oe-translation-source-sha="sourceSha" class="o_editable">
160+ <span class="s_website_form_label_content">Custom Text</span>
161+ </span>
162+ </label>
163+ <div class="col-sm">
164+ <span data-oe-model="ir.ui.view" data-oe-id="544" data-oe-field="arch_db" data-oe-translation-state="to_translate" data-oe-translation-source-sha="sourceSha" class="o_editable">
165+ <select class="form-select s_website_form_input" name="Custom Text" id="oojm1tjo6m19">
166+ <option id="optionId1" value="Option 1">Option 1</option>
167+ <option id="optionId2" value="Option 2">Option 2</option>
168+ </select>
169+ </span>
170+ </div>
171+ </div>
172+ ` ,
173+ } ) ;
174+ await contains ( ".modal .btn:contains(Ok, never show me this again)" ) . click ( ) ;
175+ await contains ( ":iframe [data-initial-translation-value='Option 1']" ) . click ( ) ;
176+ await contains ( ".modal .modal-body input" ) . edit ( "Option fr" ) ;
177+ await contains ( ".modal .btn:contains('Ok')" ) . click ( ) ;
178+ expect ( queryAllTexts ( ":iframe [data-initial-translation-value='Option 1']" ) ) . toEqual ( [
179+ "Option fr" ,
180+ ] ) ;
181+ } ) ;
182+
107183function getTranslateEditable ( inWrap ) {
108184 return `
109185 <div class="container s_allow_columns">
@@ -114,7 +190,7 @@ function getTranslateEditable(inWrap) {
114190}
115191
116192async function setupSidebarBuilderForTranslation ( options ) {
117- const { websiteContent, openEditor = true } = options ;
193+ const { websiteContent } = options ;
118194 // Hack: configure the snippets menu as in translate mode when clicking
119195 // on the "Edit" button of the systray. The goal of this hack is to avoid
120196 // the handling of an extra reload of the action to arrive in translate
@@ -132,6 +208,11 @@ async function setupSidebarBuilderForTranslation(options) {
132208 this . translation = true ;
133209 } ,
134210 } ) ;
135- const { getEditor } = await setupWebsiteBuilder ( websiteContent , { openEditor : openEditor } ) ;
136- return getEditor ( ) ;
211+ const { getEditor, getEditableContent, getIframeEl, openBuilderSidebar } =
212+ await setupWebsiteBuilder ( websiteContent , {
213+ openEditor : false ,
214+ } ) ;
215+ websiteServiceInTranslateMode . pageDocument = getIframeEl ( ) . contentDocument ;
216+ await openBuilderSidebar ( ) ;
217+ return { getEditor, getEditableContent } ;
137218}
0 commit comments