/** @odoo-module **/
import { click, clickSave, editInput, getFixture } from "@web/../tests/helpers/utils";
import { makeView, setupViewRegistries } from "@web/../tests/views/helpers";
let serverData;
let target;
QUnit.module("Fields", (hooks) => {
hooks.beforeEach(() => {
serverData = {
models: {
partner: {
fields: {
display_name: { string: "Displayed name", type: "char" },
bar: { string: "Bar", type: "boolean", default: true },
int_field: { string: "int_field", type: "integer", sortable: true },
trululu: { string: "Trululu", type: "many2one", relation: "partner" },
product_id: { string: "Product", type: "many2one", relation: "product" },
color: {
type: "selection",
selection: [
["red", "Red"],
["black", "Black"],
],
default: "red",
string: "Color",
},
},
records: [
{
id: 1,
display_name: "first record",
bar: true,
int_field: 10,
trululu: 4,
},
{
id: 2,
display_name: "second record",
},
{
id: 3,
display_name: "third record",
},
],
onchanges: {},
},
product: {
fields: {
name: { string: "Product Name", type: "char" },
},
records: [
{
id: 37,
display_name: "xphone",
},
{
id: 41,
display_name: "xpad",
},
],
},
},
};
target = getFixture();
setupViewRegistries();
});
QUnit.module("RadioField");
QUnit.test("fieldradio widget on a many2one in a new record", async function (assert) {
await makeView({
type: "form",
resModel: "partner",
serverData,
arch: '
',
});
assert.ok(
target.querySelectorAll("div.o_radio_item").length,
"should have rendered outer div"
);
assert.containsN(target, "input.o_radio_input", 2, "should have 2 possible choices");
assert.strictEqual(
target.querySelector(".o_field_radio").textContent.replace(/\s+/g, ""),
"xphonexpad"
);
assert.containsNone(target, "input:checked", "none of the input should be checked");
await click(target.querySelectorAll("input.o_radio_input")[0]);
assert.containsOnce(target, "input:checked", "one of the input should be checked");
await clickSave(target);
assert.hasAttrValue(
target.querySelector("input.o_radio_input:checked"),
"data-value",
"37",
"should have saved record with correct value"
);
});
QUnit.test("required fieldradio widget on a many2one", async function (assert) {
await makeView({
serverData,
type: "form",
resModel: "partner",
arch: '',
});
assert.containsNone(
target,
".o_field_radio input:checked",
"none of the input should be checked"
);
await clickSave(target);
assert.strictEqual(
target.querySelector(".o_notification_title").textContent,
"Invalid fields: "
);
assert.strictEqual(
target.querySelector(".o_notification_content").innerHTML,
""
);
assert.hasClass(target.querySelector(".o_notification"), "border-danger");
});
QUnit.test("fieldradio change value by onchange", async function (assert) {
serverData.models.partner.onchanges = {
bar(obj) {
obj.product_id = obj.bar ? [41] : [37];
obj.color = obj.bar ? "red" : "black";
},
};
await makeView({
type: "form",
resModel: "partner",
serverData,
arch: `
`,
});
await click(target, "input[type='checkbox']");
assert.containsOnce(
target,
"input.o_radio_input[data-value='37']:checked",
"one of the input should be checked"
);
assert.containsOnce(
target,
"input.o_radio_input[data-value='black']:checked",
"the other of the input should be checked"
);
await click(target, "input[type='checkbox']");
assert.containsOnce(
target,
"input.o_radio_input[data-value='41']:checked",
"the other of the input should be checked"
);
assert.containsOnce(
target,
"input.o_radio_input[data-value='red']:checked",
"one of the input should be checked"
);
});
QUnit.test("fieldradio widget on a selection in a new record", async function (assert) {
await makeView({
type: "form",
resModel: "partner",
serverData,
arch: '',
});
assert.ok(
target.querySelectorAll("div.o_radio_item").length,
"should have rendered outer div"
);
assert.containsN(target, "input.o_radio_input", 2, "should have 2 possible choices");
assert.strictEqual(
target.querySelector(".o_field_radio").textContent.replace(/\s+/g, ""),
"RedBlack"
);
// click on 2nd option
await click(target.querySelectorAll("input.o_radio_input")[1]);
await clickSave(target);
assert.hasAttrValue(
target.querySelector("input.o_radio_input:checked"),
"data-value",
"black",
"should have saved record with correct value"
);
});
QUnit.test("fieldradio widget has o_horizontal or o_vertical class", async function (assert) {
serverData.models.partner.fields.color2 = serverData.models.partner.fields.color;
await makeView({
type: "form",
resModel: "partner",
serverData,
arch: `
`,
});
assert.containsOnce(
target,
".o_field_radio > div.o_vertical",
"should have o_vertical class"
);
const verticalRadio = target.querySelector(".o_field_radio > div.o_vertical");
assert.strictEqual(
verticalRadio.querySelector(".o_radio_item:first-child").getBoundingClientRect().right,
verticalRadio.querySelector(".o_radio_item:last-child").getBoundingClientRect().right
);
assert.containsOnce(
target,
".o_field_radio > div.o_horizontal",
"should have o_horizontal class"
);
const horizontalRadio = target.querySelector(".o_field_radio > div.o_horizontal");
assert.strictEqual(
horizontalRadio.querySelector(".o_radio_item:first-child").getBoundingClientRect().top,
horizontalRadio.querySelector(".o_radio_item:last-child").getBoundingClientRect().top
);
});
QUnit.test("fieldradio widget with numerical keys encoded as strings", async function (assert) {
assert.expect(5);
serverData.models.partner.fields.selection = {
type: "selection",
selection: [
["0", "Red"],
["1", "Black"],
],
};
await makeView({
type: "form",
resModel: "partner",
resId: 1,
serverData,
arch: '',
mockRPC: function (route, { args, method, model }) {
if (model === "partner" && method === "write") {
assert.strictEqual(args[1].selection, "1", "should write correct value");
}
},
});
assert.strictEqual(
target.querySelector(".o_field_widget").textContent.replace(/\s+/g, ""),
"RedBlack"
);
assert.containsNone(target, ".o_radio_input:checked", "no value should be checked");
await click(target.querySelectorAll("input.o_radio_input")[1]);
await clickSave(target);
assert.strictEqual(
target.querySelector(".o_field_widget").textContent.replace(/\s+/g, ""),
"RedBlack"
);
assert.containsOnce(
target,
".o_radio_input[data-index='1']:checked",
"'Black' should be checked"
);
});
QUnit.test(
"widget radio on a many2one: domain updated by an onchange",
async function (assert) {
assert.expect(4);
serverData.models.partner.onchanges = {
int_field() {},
};
let domain = [];
await makeView({
type: "form",
resModel: "partner",
resId: 1,
serverData,
arch: `
`,
mockRPC(route, { kwargs, method }) {
if (method === "onchange") {
domain = [["id", "in", [10]]];
return Promise.resolve({
value: {
trululu: false,
},
domain: {
trululu: domain,
},
});
}
if (method === "search_read") {
assert.deepEqual(kwargs.domain, domain, "sent domain should be correct");
}
},
});
assert.containsN(
target,
".o_field_widget[name='trululu'] .o_radio_item",
3,
"should be 3 radio buttons"
);
// trigger an onchange that will update the domain
await editInput(target, ".o_field_widget[name='int_field'] input", "2");
assert.containsNone(
target,
".o_field_widget[name='trululu'] .o_radio_item",
"should be no more radio button"
);
}
);
QUnit.test("field is empty", async function (assert) {
await makeView({
type: "form",
resModel: "partner",
resId: 2,
serverData,
arch: `
`,
});
assert.hasClass(target.querySelector(".o_field_widget[name=trululu]"), "o_field_empty");
assert.containsN(target, ".o_radio_input", 3);
assert.containsN(target, ".o_radio_input:disabled", 3);
assert.containsNone(target, ".o_radio_input:checked");
});
});