import { beforeEach, describe, expect, test } from "@odoo/hoot";
import { click, queryAll } from "@odoo/hoot-dom";
import { animationFrame } from "@odoo/hoot-mock";
import {
contains,
defineModels,
fields,
getDropdownMenu,
getService,
models,
mountView,
mountWithCleanup,
onRpc,
patchWithCleanup,
} from "@web/../tests/web_test_helpers";
import { browser } from "@web/core/browser/browser";
import { user } from "@web/core/user";
import { WebClientEnterprise } from "@web_enterprise/webclient/webclient";
class Foo extends models.Model {
foo = fields.Char();
bar = fields.Boolean();
_records = [
{ id: 1, bar: true, foo: "yop" },
{ id: 2, bar: true, foo: "blip" },
{ id: 3, bar: true, foo: "gnap" },
{ id: 4, bar: false, foo: "blip" },
];
}
defineModels([Foo]);
const getDefaultConfig = () => ({
actionId: 1,
actionType: "ir.actions.act_window",
actionXmlId: "action_1",
});
describe.current.tags("desktop");
beforeEach(() => {
onRpc("has_group", () => true);
});
test("add custom field button with other optional columns - studio not installed", async () => {
expect.assertions(8);
onRpc("search_read", ({ model }) => {
if (model === "ir.module.module") {
expect.step("studio_module_id");
return [{ id: 42 }];
}
});
onRpc("button_immediate_install", ({ model, args }) => {
if (model === "ir.module.module") {
expect(args[0]).toEqual([42], {
message: "Should be the id of studio module returned by the search read",
});
expect.step("studio_module_install");
return true;
}
});
await mountView({
type: "list",
resModel: "foo",
arch: /* xml */ `
`,
config: getDefaultConfig(),
});
patchWithCleanup(browser.location, {
reload: function () {
expect.step("window_reload");
},
});
expect(".o_data_row").toHaveCount(4);
expect(".o_optional_columns_dropdown_toggle").toHaveCount(1);
await click(".o_optional_columns_dropdown_toggle");
await animationFrame();
const dropdown = getDropdownMenu(".o_optional_columns_dropdown");
expect(queryAll(".dropdown-item", { root: dropdown })).toHaveCount(2);
expect(queryAll(".dropdown-item-studio", { root: dropdown })).toHaveCount(1);
await click(".dropdown-item-studio");
await animationFrame();
expect(".modal-studio").toHaveCount(1);
await click(".modal .o_install_studio");
await animationFrame();
expect(browser.localStorage.getItem("openStudioOnReload")).toBe("main");
expect.verifySteps(["studio_module_id", "studio_module_install", "window_reload"]);
});
test("add custom field button without other optional columns - studio not installed", async () => {
expect.assertions(8);
onRpc("search_read", ({ model }) => {
if (model === "ir.module.module") {
expect.step("studio_module_id");
return [{ id: 42 }];
}
});
onRpc("button_immediate_install", ({ model, args }) => {
if (model === "ir.module.module") {
expect(args[0]).toEqual([42], {
message: "Should be the id of studio module returned by the search read",
});
expect.step("studio_module_install");
return true;
}
});
await mountView({
type: "list",
resModel: "foo",
config: getDefaultConfig(),
arch: /* xml */ `
`,
});
patchWithCleanup(browser.location, {
reload: function () {
expect.step("window_reload");
},
});
expect(".o_data_row").toHaveCount(4);
expect(".o_optional_columns_dropdown_toggle").toHaveCount(1);
await click(".o_optional_columns_dropdown_toggle");
await animationFrame();
const dropdown = getDropdownMenu(".o_optional_columns_dropdown");
expect(queryAll(".dropdown-item", { root: dropdown })).toHaveCount(1);
expect(queryAll(".dropdown-item-studio", { root: dropdown })).toHaveCount(1);
await click(".dropdown-item-studio");
await animationFrame();
expect(".modal-studio").toHaveCount(1);
await click(".modal .o_install_studio");
await animationFrame();
expect(browser.localStorage.getItem("openStudioOnReload")).toBe("main");
expect.verifySteps(["studio_module_id", "studio_module_install", "window_reload"]);
});
test("add custom field button not shown to non-system users (with opt. col.)", async () => {
expect.assertions(3);
patchWithCleanup(user, { isSystem: false });
await mountView({
type: "list",
resModel: "foo",
config: getDefaultConfig(),
arch: /* xml */ `
`,
});
expect(".o_optional_columns_dropdown_toggle").toHaveCount(1);
await click(".o_optional_columns_dropdown_toggle");
await animationFrame();
const dropdown = getDropdownMenu(".o_optional_columns_dropdown");
expect(queryAll(".dropdown-item", { root: dropdown })).toHaveCount(1);
expect(queryAll(".dropdown-item-studio", { root: dropdown })).toHaveCount(0);
});
test("add custom field button not shown to non-system users (wo opt. col.)", async () => {
patchWithCleanup(user, { isSystem: false });
await mountView({
type: "list",
resModel: "foo",
config: getDefaultConfig(),
arch: /* xml */ `
`,
});
expect(".o_optional_columns_dropdown_toggle").toHaveCount(0);
});
test("add custom field button not shown with invalid action", async () => {
expect.assertions(1);
patchWithCleanup(user, { isSystem: false });
await mountView({
type: "list",
resModel: "foo",
config: { ...getDefaultConfig(), actionId: null },
arch: /* xml */ `
`,
});
expect(".o_optional_columns_dropdown_toggle").toHaveCount(0);
});
test("add custom field button not shown with bank statement line model", async () => {
class AccountBankStatementLine extends models.Model {
name = fields.Char();
_views = {
kanban: `
`,
};
}
defineModels([AccountBankStatementLine]);
expect.assertions(3);
await mountWithCleanup(WebClientEnterprise);
await animationFrame();
await getService("action").doAction({
xml_id: "test",
id: 1312,
name: "test",
res_id: 1,
res_model: "account.bank.statement.line",
type: "ir.actions.act_window",
views: [[false, "kanban"], [false, "list"]],
});
expect("button.o_switch_view.o_list[data-tooltip='List']").toHaveCount(1);
await contains("button.o_switch_view.o_list[data-tooltip='List']").click();
expect(".o_list_renderer .o_list_controller button.dropdown-toggle").toHaveCount(1);
await contains(".o_list_renderer .o_list_controller button.dropdown-toggle").click();
expect(".dropdown-item-studio").toHaveCount(0);
});
test("x2many should not be editable", async () => {
class Bar extends models.Model {}
defineModels([Bar]);
Foo._fields.o2m = fields.One2many({ relation: "bar" });
await mountView({
type: "form",
resModel: "foo",
arch: /* xml */ `