Odoo18-Base/addons/web/static/tests/views/fields/html_field_tests.js
2025-03-10 11:12:23 +07:00

299 lines
11 KiB
JavaScript

/** @odoo-module **/
import {
click,
clickSave,
editInput,
getFixture,
patchWithCleanup,
} from "@web/../tests/helpers/utils";
import { makeView, setupViewRegistries } from "@web/../tests/views/helpers";
import { registry } from "@web/core/registry";
import { HtmlField } from "@web/views/fields/html/html_field";
import { makeFakeLocalizationService } from "@web/../tests/helpers/mock_services";
import { session } from "@web/session";
const RED_TEXT = /* html */ `<div class="kek" style="color:red">some text</div>`;
const GREEN_TEXT = /* html */ `<div class="kek" style="color:green">hello</div>`;
const BLUE_TEXT = /* html */ `<div class="kek" style="color:blue">hello world</div>`;
const serviceRegistry = registry.category("services");
QUnit.module("Fields", ({ beforeEach }) => {
let serverData;
let target;
beforeEach(() => {
serverData = {
models: {
partner: {
fields: {
txt: { string: "txt", type: "html", trim: true },
},
records: [{ id: 1, txt: RED_TEXT }],
},
},
};
target = getFixture();
setupViewRegistries();
// Explicitly removed by web_editor, we need to add it back
registry.category("fields").add("html", HtmlField, { force: true });
});
QUnit.module("HtmlField");
QUnit.test("html fields are correctly rendered in form view (readonly)", async (assert) => {
await makeView({
type: "form",
resModel: "partner",
resId: 1,
serverData,
arch: /* xml */ `<form><field name="txt" readonly="1" /></form>`,
});
assert.containsOnce(target, "div.kek");
assert.strictEqual(target.querySelector(".o_field_html .kek").style.color, "red");
assert.strictEqual(target.querySelector(".o_field_html").textContent, "some text");
});
QUnit.test("html field with required attribute", async function (assert) {
await makeView({
type: "form",
resModel: "partner",
resId: 1,
serverData,
arch: /* xml */ `<form><field name="txt" required="1"/></form>`,
});
const textarea = target.querySelector(".o_field_html textarea");
assert.ok(textarea, "should have a text area");
await editInput(textarea, null, "");
assert.strictEqual(textarea.value, "");
await clickSave(target);
assert.strictEqual(
target.querySelector(".o_notification_title").textContent,
"Invalid fields: "
);
assert.strictEqual(
target.querySelector(".o_notification_content").innerHTML,
"<ul><li>txt</li></ul>"
);
});
QUnit.test("html fields are correctly rendered (edit)", async (assert) => {
await makeView({
type: "form",
resModel: "partner",
resId: 1,
serverData,
arch: /* xml */ `<form><field name="txt" /></form>`,
});
const textarea = target.querySelector(".o_field_html textarea");
assert.ok(textarea, "should have a text area");
assert.strictEqual(textarea.value, RED_TEXT);
await editInput(textarea, null, GREEN_TEXT);
assert.strictEqual(textarea.value, GREEN_TEXT);
assert.containsNone(target.querySelector(".o_field_html"), ".kek");
await editInput(textarea, null, BLUE_TEXT);
assert.strictEqual(textarea.value, BLUE_TEXT);
});
QUnit.test("html fields are correctly rendered in list view", async (assert) => {
await makeView({
type: "list",
resModel: "partner",
serverData,
arch: `
<tree editable="top">
<field name="txt"/>
</tree>`,
});
const txt = target.querySelector(".o_data_row [name='txt']");
assert.strictEqual(txt.textContent, "some text");
assert.strictEqual(txt.querySelector(".kek").style.color, "red");
await click(target.querySelector(".o_data_row [name='txt']"));
assert.strictEqual(
target.querySelector(".o_data_row [name='txt'] textarea").value,
'<div class="kek" style="color:red">some text</div>'
);
});
QUnit.test(
"html field displays an empty string for the value false in list view",
async (assert) => {
serverData.models.partner.records[0].txt = false;
await makeView({
type: "list",
resModel: "partner",
serverData,
arch: `
<tree editable="top">
<field name="txt"/>
</tree>`,
});
assert.strictEqual(target.querySelector(".o_data_row [name='txt']").textContent, "");
await click(target.querySelector(".o_data_row [name='txt']"));
assert.strictEqual(target.querySelector(".o_data_row [name='txt'] textarea").value, "");
}
);
QUnit.test("html fields are correctly rendered in kanban view", async (assert) => {
await makeView({
type: "kanban",
resModel: "partner",
serverData,
arch: `
<kanban class="o_kanban_test">
<templates>
<t t-name="kanban-box">
<div>
<field name="txt"/>
</div>
</t>
</templates>
</kanban>`,
});
const txt = target.querySelector(".kek");
assert.strictEqual(txt.textContent, "some text");
assert.strictEqual(txt.style.color, "red");
});
QUnit.test("field html translatable", async (assert) => {
assert.expect(10);
serverData.models.partner.fields.txt.translate = true;
serviceRegistry.add("localization", makeFakeLocalizationService({ multiLang: true }), {
force: true,
});
patchWithCleanup(session.user_context, {
lang: "en_US",
});
await makeView({
type: "form",
resModel: "partner",
resId: 1,
serverData,
arch: `
<form string="Partner">
<sheet>
<group>
<field name="txt" widget="html"/>
</group>
</sheet>
</form>`,
mockRPC(route, { args, method, model }) {
if (route === "/web/dataset/call_kw/partner/get_field_translations") {
assert.deepEqual(
args,
[[1], "txt"],
"should translate the txt field of the record"
);
return Promise.resolve([
[
{ lang: "en_US", source: "first paragraph", value: "first paragraph" },
{
lang: "en_US",
source: "second paragraph",
value: "second paragraph",
},
{
lang: "fr_BE",
source: "first paragraph",
value: "",
},
{
lang: "fr_BE",
source: "second paragraph",
value: "deuxième paragraphe",
},
],
{ translation_type: "char", translation_show_source: true },
]);
}
if (route === "/web/dataset/call_kw/res.lang/get_installed") {
return Promise.resolve([
["en_US", "English"],
["fr_BE", "French (Belgium)"],
]);
}
if (route === "/web/dataset/call_kw/partner/update_field_translations") {
assert.deepEqual(
args,
[
[1],
"txt",
{
en_US: { "first paragraph": "first paragraph modified" },
fr_BE: {
"first paragraph": "premier paragraphe modifié",
"deuxième paragraphe": "deuxième paragraphe modifié",
},
},
],
"the new translation value should be written"
);
return Promise.resolve(null);
}
},
});
assert.hasClass(target.querySelector("[name=txt] textarea"), "o_field_translate");
assert.containsOnce(
target,
".o_field_html .btn.o_field_translate",
"should have a translate button"
);
assert.strictEqual(
target.querySelector(".o_field_html .btn.o_field_translate").textContent,
"EN",
"the button should have as test the current language"
);
await click(target, ".o_field_html .btn.o_field_translate");
assert.containsOnce(target, ".modal", "a translate modal should be visible");
assert.containsN(target, ".translation", 4, "four rows should be visible");
const translations = target.querySelectorAll(
".modal .o_translation_dialog .translation input"
);
const enField1 = translations[0];
assert.strictEqual(
enField1.value,
"first paragraph",
"first part of english translation should be filled"
);
await editInput(enField1, null, "first paragraph modified");
const frField1 = translations[2];
assert.strictEqual(
frField1.value,
"",
"first part of french translation should not be filled"
);
await editInput(frField1, null, "premier paragraphe modifié");
const frField2 = translations[3];
assert.strictEqual(
frField2.value,
"deuxième paragraphe",
"second part of french translation should be filled"
);
await editInput(frField2, null, "deuxième paragraphe modifié");
await click(target, ".modal button.btn-primary"); // save
});
});