425 lines
14 KiB
JavaScript
425 lines
14 KiB
JavaScript
/** @odoo-module **/
|
|
|
|
import { click, editSelect, editInput, getFixture, clickSave } from "@web/../tests/helpers/utils";
|
|
import { makeView, setupViewRegistries } from "@web/../tests/views/helpers";
|
|
|
|
let serverData;
|
|
let target;
|
|
|
|
QUnit.module("Fields", (hooks) => {
|
|
hooks.beforeEach(() => {
|
|
target = getFixture();
|
|
serverData = {
|
|
models: {
|
|
partner: {
|
|
fields: {
|
|
display_name: { string: "Displayed name", type: "char" },
|
|
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",
|
|
int_field: 10,
|
|
trululu: 4,
|
|
},
|
|
{
|
|
id: 2,
|
|
display_name: "second record",
|
|
int_field: 9,
|
|
trululu: 1,
|
|
product_id: 37,
|
|
},
|
|
{
|
|
id: 4,
|
|
display_name: "aaa",
|
|
},
|
|
],
|
|
},
|
|
product: {
|
|
fields: {
|
|
name: { string: "Product Name", type: "char" },
|
|
},
|
|
records: [
|
|
{
|
|
id: 37,
|
|
display_name: "xphone",
|
|
},
|
|
{
|
|
id: 41,
|
|
display_name: "xpad",
|
|
},
|
|
],
|
|
},
|
|
},
|
|
};
|
|
|
|
setupViewRegistries();
|
|
});
|
|
|
|
QUnit.module("SelectionField");
|
|
|
|
QUnit.test("SelectionField in a list view", async function (assert) {
|
|
serverData.models.partner.records.forEach(function (r) {
|
|
r.color = "red";
|
|
});
|
|
|
|
await makeView({
|
|
type: "list",
|
|
resModel: "partner",
|
|
serverData,
|
|
arch: '<tree string="Colors" editable="top"><field name="color"/></tree>',
|
|
});
|
|
|
|
assert.containsN(target, ".o_data_row", 3);
|
|
await click(target.querySelector(".o_data_cell"));
|
|
|
|
const td = target.querySelector("tbody tr.o_selected_row td:not(.o_list_record_selector)");
|
|
assert.containsOnce(td, "select", "td should have a child 'select'");
|
|
assert.strictEqual(td.children.length, 1, "select tag should be only child of td");
|
|
});
|
|
|
|
QUnit.test("SelectionField, edition and on many2one field", async function (assert) {
|
|
serverData.models.partner.onchanges = { product_id: function () {} };
|
|
serverData.models.partner.records[0].product_id = 37;
|
|
serverData.models.partner.records[0].trululu = false;
|
|
|
|
await makeView({
|
|
type: "form",
|
|
resModel: "partner",
|
|
resId: 1,
|
|
serverData,
|
|
arch: `
|
|
<form>
|
|
<field name="product_id" widget="selection" />
|
|
<field name="trululu" widget="selection" />
|
|
<field name="color" widget="selection" />
|
|
</form>`,
|
|
mockRPC(route, { method }) {
|
|
assert.step(method);
|
|
},
|
|
});
|
|
|
|
assert.containsN(target, "select", 3);
|
|
assert.containsOnce(
|
|
target,
|
|
".o_field_widget[name='product_id'] select option[value='37']",
|
|
"should have fetched xphone option"
|
|
);
|
|
assert.containsOnce(
|
|
target,
|
|
".o_field_widget[name='product_id'] select option[value='41']",
|
|
"should have fetched xpad option"
|
|
);
|
|
assert.strictEqual(
|
|
target.querySelector(".o_field_widget[name='product_id'] select").value,
|
|
"37",
|
|
"should have correct product_id value"
|
|
);
|
|
assert.strictEqual(
|
|
target.querySelector(".o_field_widget[name='trululu'] select").value,
|
|
"false",
|
|
"should not have any value in trululu field"
|
|
);
|
|
|
|
await editSelect(target, ".o_field_widget[name='product_id'] select", "41");
|
|
|
|
assert.strictEqual(
|
|
target.querySelector(".o_field_widget[name='product_id'] select").value,
|
|
"41",
|
|
"should have a value of xphone"
|
|
);
|
|
|
|
assert.strictEqual(
|
|
target.querySelector(".o_field_widget[name='color'] select").value,
|
|
`"red"`,
|
|
"should have correct value in color field"
|
|
);
|
|
|
|
assert.verifySteps(["get_views", "read", "name_search", "name_search", "onchange"]);
|
|
});
|
|
|
|
QUnit.test("unset selection field with 0 as key", async function (assert) {
|
|
// The server doesn't make a distinction between false value (the field
|
|
// is unset), and selection 0, as in that case the value it returns is
|
|
// false. So the client must convert false to value 0 if it exists.
|
|
serverData.models.partner.fields.selection = {
|
|
type: "selection",
|
|
selection: [
|
|
[0, "Value O"],
|
|
[1, "Value 1"],
|
|
],
|
|
};
|
|
|
|
await makeView({
|
|
type: "form",
|
|
resModel: "partner",
|
|
resId: 1,
|
|
serverData,
|
|
arch: '<form edit="0"><field name="selection" /></form>',
|
|
});
|
|
|
|
assert.strictEqual(
|
|
target.querySelector(".o_field_widget").textContent,
|
|
"Value O",
|
|
"the displayed value should be 'Value O'"
|
|
);
|
|
assert.doesNotHaveClass(
|
|
target.querySelector(".o_field_widget"),
|
|
"o_field_empty",
|
|
"should not have class o_field_empty"
|
|
);
|
|
});
|
|
|
|
QUnit.test("unset selection field with string keys", async function (assert) {
|
|
// The server doesn't make a distinction between false value (the field
|
|
// is unset), and selection 0, as in that case the value it returns is
|
|
// false. So the client must convert false to value 0 if it exists. In
|
|
// this test, it doesn't exist as keys are strings.
|
|
serverData.models.partner.fields.selection = {
|
|
type: "selection",
|
|
selection: [
|
|
["0", "Value O"],
|
|
["1", "Value 1"],
|
|
],
|
|
};
|
|
|
|
await makeView({
|
|
type: "form",
|
|
resModel: "partner",
|
|
resId: 1,
|
|
serverData,
|
|
arch: '<form edit="0"><field name="selection" /></form>',
|
|
});
|
|
|
|
assert.strictEqual(
|
|
target.querySelector(".o_field_widget").textContent,
|
|
"",
|
|
"there should be no displayed value"
|
|
);
|
|
assert.hasClass(
|
|
target.querySelector(".o_field_widget"),
|
|
"o_field_empty",
|
|
"should have class o_field_empty"
|
|
);
|
|
});
|
|
|
|
QUnit.test("unset selection on a many2one field", async function (assert) {
|
|
assert.expect(1);
|
|
|
|
await makeView({
|
|
type: "form",
|
|
resModel: "partner",
|
|
resId: 1,
|
|
serverData,
|
|
arch: '<form><field name="trululu" widget="selection" /></form>',
|
|
mockRPC(route, { args, method }) {
|
|
if (method === "write") {
|
|
assert.strictEqual(
|
|
args[1].trululu,
|
|
false,
|
|
"should send 'false' as trululu value"
|
|
);
|
|
}
|
|
},
|
|
});
|
|
|
|
await editSelect(target, ".o_form_view select", "false");
|
|
await clickSave(target);
|
|
});
|
|
|
|
QUnit.test("field selection with many2ones and special characters", async function (assert) {
|
|
// edit the partner with id=4
|
|
serverData.models.partner.records[2].display_name = "<span>hey</span>";
|
|
|
|
await makeView({
|
|
type: "form",
|
|
resModel: "partner",
|
|
resId: 1,
|
|
serverData,
|
|
arch: '<form><field name="trululu" widget="selection" /></form>',
|
|
});
|
|
|
|
assert.strictEqual(
|
|
target.querySelector("select option[value='4']").textContent,
|
|
"<span>hey</span>"
|
|
);
|
|
});
|
|
|
|
QUnit.test(
|
|
"SelectionField 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: `
|
|
<form>
|
|
<field name="int_field" />
|
|
<field name="trululu" widget="selection" />
|
|
</form>`,
|
|
mockRPC(route, { args, method }) {
|
|
if (method === "onchange") {
|
|
domain = [["id", "in", [10]]];
|
|
return Promise.resolve({
|
|
domain: {
|
|
trululu: domain,
|
|
},
|
|
});
|
|
}
|
|
if (method === "name_search") {
|
|
assert.deepEqual(args[1], domain, "sent domain should be correct");
|
|
}
|
|
},
|
|
});
|
|
|
|
assert.containsN(
|
|
target,
|
|
".o_field_widget[name='trululu'] option",
|
|
4,
|
|
"should be 4 options in the selection"
|
|
);
|
|
|
|
// trigger an onchange that will update the domain
|
|
await editInput(target, ".o_field_widget[name='int_field'] input", 2);
|
|
|
|
assert.containsOnce(
|
|
target,
|
|
".o_field_widget[name='trululu'] option",
|
|
"should be 1 option in the selection"
|
|
);
|
|
}
|
|
);
|
|
|
|
QUnit.test("required selection widget should not have blank option", async function (assert) {
|
|
serverData.models.partner.fields.feedback_value = {
|
|
type: "selection",
|
|
required: true,
|
|
selection: [
|
|
["good", "Good"],
|
|
["bad", "Bad"],
|
|
],
|
|
default: "good",
|
|
string: "Good",
|
|
};
|
|
await makeView({
|
|
type: "form",
|
|
resModel: "partner",
|
|
resId: 1,
|
|
serverData,
|
|
arch: `
|
|
<form>
|
|
<field name="feedback_value" />
|
|
<field name="color" attrs="{'required': [('feedback_value', '=', 'bad')]}" />
|
|
</form>`,
|
|
});
|
|
|
|
assert.deepEqual(
|
|
[...target.querySelectorAll(".o_field_widget[name='color'] option")].map(
|
|
(option) => option.style.display
|
|
),
|
|
["", "", ""]
|
|
);
|
|
assert.deepEqual(
|
|
[...target.querySelectorAll(".o_field_widget[name='feedback_value'] option")].map(
|
|
(option) => option.style.display
|
|
),
|
|
["none", "", ""]
|
|
);
|
|
|
|
// change value to update widget modifier values
|
|
await editSelect(target, ".o_field_widget[name='feedback_value'] select", '"bad"');
|
|
assert.deepEqual(
|
|
[...target.querySelectorAll(".o_field_widget[name='color'] option")].map(
|
|
(option) => option.style.display
|
|
),
|
|
["none", "", ""]
|
|
);
|
|
});
|
|
|
|
QUnit.test(
|
|
"required selection widget should have only one blank option",
|
|
async function (assert) {
|
|
serverData.models.partner.fields.feedback_value = {
|
|
type: "selection",
|
|
required: true,
|
|
selection: [
|
|
["good", "Good"],
|
|
["bad", "Bad"],
|
|
],
|
|
default: "good",
|
|
string: "Good",
|
|
};
|
|
serverData.models.partner.fields.color.selection = [
|
|
[false, ""],
|
|
...serverData.models.partner.fields.color.selection,
|
|
];
|
|
|
|
await makeView({
|
|
type: "form",
|
|
resModel: "partner",
|
|
resId: 1,
|
|
serverData,
|
|
arch: `
|
|
<form>
|
|
<field name="feedback_value" />
|
|
<field name="color" attrs="{'required': [('feedback_value', '=', 'bad')]}" />
|
|
</form>`,
|
|
});
|
|
|
|
assert.containsN(
|
|
target.querySelector(".o_field_widget[name='color']"),
|
|
"option",
|
|
3,
|
|
"Three options in non required field (one blank option)"
|
|
);
|
|
|
|
// change value to update widget modifier values
|
|
await editSelect(target, ".o_field_widget[name='feedback_value'] select", '"bad"');
|
|
assert.deepEqual(
|
|
[...target.querySelectorAll(".o_field_widget[name='color'] option")].map(
|
|
(option) => option.style.display
|
|
),
|
|
["none", "", ""]
|
|
);
|
|
}
|
|
);
|
|
|
|
QUnit.test("selection field with placeholder", async function (assert) {
|
|
await makeView({
|
|
type: "form",
|
|
resModel: "partner",
|
|
serverData,
|
|
arch: `
|
|
<form>
|
|
<field name="trululu" widget="selection" placeholder="Placeholder"/>
|
|
</form>`,
|
|
});
|
|
|
|
const placeholderOption = target.querySelector(
|
|
".o_field_widget[name='trululu'] select option"
|
|
);
|
|
assert.strictEqual(placeholderOption.textContent, "Placeholder");
|
|
assert.strictEqual(placeholderOption.value, "false");
|
|
});
|
|
});
|