From af970abf8925192fe6e899cf539ed5b1f3ed1a13 Mon Sep 17 00:00:00 2001 From: Lucas Perais Date: Fri, 27 Oct 2023 15:28:33 +0200 Subject: [PATCH] [FIX] web_editor: QWebPlugin select parent of a qweb field Follows commit: ffef01e327b0263a2af4892e9e438a2c0ef22184. It caused an issue in Firefox: On the sale order form view (with the field "notes" handled by the OdooEditor), clicking on a Many2one made the browser crash because the method getSelection did not exist on the target which was the input element. It did not crash in chrome as the event's target was always the Document. The added test actually tests the feature of the referenced commit, and checks, as much as possible, that there is no crash. closes odoo/odoo#140143 Signed-off-by: Lucas Perais (lpe) --- .../static/src/js/backend/QWebPlugin.js | 2 +- .../static/tests/html_field_tests.js | 59 +++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/addons/web_editor/static/src/js/backend/QWebPlugin.js b/addons/web_editor/static/src/js/backend/QWebPlugin.js index 28ac503030b..9258f86a181 100644 --- a/addons/web_editor/static/src/js/backend/QWebPlugin.js +++ b/addons/web_editor/static/src/js/backend/QWebPlugin.js @@ -135,7 +135,7 @@ export class QWebPlugin { } _selectQwebNode(editor) { editor.addDomListener(editor.document, 'selectionchange', e => { - const selection = e.target.getSelection(); + const selection = editor.document.getSelection(); const qwebNode = selection.anchorNode && closestElement(selection.anchorNode, '[t-field],[t-esc],[t-out]'); if (qwebNode){ const range = new Range(); diff --git a/addons/web_editor/static/tests/html_field_tests.js b/addons/web_editor/static/tests/html_field_tests.js index 67ad6432196..b01c66d8940 100644 --- a/addons/web_editor/static/tests/html_field_tests.js +++ b/addons/web_editor/static/tests/html_field_tests.js @@ -100,6 +100,65 @@ QUnit.module("WebEditor.HtmlField", ({ beforeEach }) => { assert.equal(mediaDialog.props.resId, 2); }); + QUnit.test("QWeb plugin select t-field", async (assert) => { + serverData.models.partner.fields.m2o = { type: "many2one", relation: "partner" }; + serverData.models.partner.records = [{ + id: 1, + txt: `demo` + }]; + await makeView({ + type: "form", + resId: 1, + resIds: [1, 2], + resModel: "partner", + serverData, + arch: ` +
+ + + `, + }); + + // Manually add a t-field in the form + // to be able to test that we don't trigger the same behavior + // as if we were inside the html field + const form = target.querySelector(".o_form_view"); + const span = document.createElement("span"); + span.setAttribute("t-field", "bogus"); + span.innerHTML = `bogus`; + form.appendChild(span); + + const sel = document.getSelection(); + sel.removeAllRanges(); + let range = new Range(); + range.setStart(target.querySelector(".insideoftfield"), 0); + sel.addRange(range); + await nextTick(); + assert.strictEqual(sel.anchorNode, target.querySelector(".o_field_html p")); + sel.removeAllRanges(); + + range = new Range(); + range.setStart(target.querySelector(".insidebogus"), 0); + sel.addRange(range); + await nextTick(); + assert.strictEqual(sel.anchorNode, target.querySelector(".insidebogus")); + + // Dispatch an invalid event to make sure nothing crashes + // It is hard to test this, but the issue was, in firefox, the target + // was used in the handler, and was the input which did not have some function + // In chrome, it worked fine, as selectionchange's target was always the document + const customEvent = new CustomEvent("selectionchange", { bubbles: true }); + Object.defineProperties(customEvent, { + target: { + value: null, + }, + currentTarget: { + value: null, + }, + }) + target.querySelector(".o_field_many2one input").dispatchEvent(customEvent); + }) + QUnit.module('Sandboxed Preview'); QUnit.test("complex html is automatically in sandboxed preview mode", async (assert) => {