Initial commit

This commit is contained in:
gsinghpal
2026-02-22 01:22:18 -05:00
commit 5200d5baf0
2394 changed files with 386834 additions and 0 deletions

View File

@@ -0,0 +1,649 @@
/** @odoo-module **/
import { click, drag, editInput, getFixture } from "@web/../tests/helpers/utils";
import { registerCleanup } from "@web/../tests/helpers/cleanup";
import { makeView, setupViewRegistries } from "@web/../tests/views/helpers";
import { sortableDrag } from "@web/../tests/core/utils/nested_sortable_tests"
let arch;
let serverData;
let target;
QUnit.module("Account Reports Builder", ({ beforeEach }) => {
beforeEach(async () => {
arch = `
<form>
<field class="w-100" name="line_ids" widget="account_report_lines_list_x2many">
<list>
<field name="id" column_invisible="1"/>
<field name="sequence" column_invisible="1"/>
<field name="parent_id" column_invisible="1"/>
<field name="hierarchy_level" column_invisible="1"/>
<field name="name"/>
<field name="code" optional="hide"/>
</list>
</field>
</form>
`;
serverData = {
models: {
report: {
fields: {
id: { string: "ID", type: "integer" },
line_ids: {
string: "Lines",
type: "one2many",
relation: "report_lines",
relation_field: "report_id",
},
},
records: [
{
id: 1,
line_ids: [1, 2, 3, 4, 5],
}
]
},
report_lines: {
fields: {
report_id: { string: "Report ID", type: "many2one", relation: "report" },
id: { string: "ID", type: "integer" },
sequence: { string: "Sequence", type: "integer" },
parent_id: {
string: "Parent Line",
type: "many2one",
relation: "report_lines",
relation_field: "id",
},
hierarchy_level: { string: "Level", type: "integer" },
name: { string: "Name", type: "char" },
code: { string: "Code", type: "char" },
},
records: [
{
id: 1,
sequence: null,
parent_id: false,
hierarchy_level: 1,
name: "Root without children",
code: "RWOC",
},
{
id: 2,
sequence: null,
parent_id: false,
hierarchy_level: 0,
name: "Root with children",
code: "RC",
},
{
id: 3,
sequence: null,
parent_id: 2,
hierarchy_level: 3,
name: "Child #1",
code: "C1",
},
{
id: 4,
sequence: null,
parent_id: 3,
hierarchy_level: 5,
name: "Grandchild",
code: "GC",
},
{
id: 5,
sequence: null,
parent_id: 2,
hierarchy_level: 3,
name: "Child #2",
code: "C2",
},
]
},
},
views: {
"report_lines,false,form": `
<form>
<field name="name"/>
</form>
`,
}
};
target = getFixture();
// Make fixture in visible range, so that document.elementFromPoint work as expected
target.style.position = "absolute";
target.style.top = "0";
target.style.left = "0";
target.style.height = "100%";
target.style.opacity = QUnit.config.debug ? "" : "0";
registerCleanup(async () => {
target.style.position = "";
target.style.top = "";
target.style.left = "";
target.style.height = "";
target.style.opacity = "";
});
setupViewRegistries();
});
//------------------------------------------------------------------------------------------------------------------
// Structure
//------------------------------------------------------------------------------------------------------------------
QUnit.test("have correct descendants count", async (assert) => {
await makeView({
type: "form",
resId: 1,
resModel: "report",
serverData,
arch,
});
assert.containsOnce(target.querySelector(".account_report_lines_list_x2many"), "li[data-descendants_count='0'] span:contains('Root without children')");
assert.containsOnce(target.querySelector(".account_report_lines_list_x2many"), "li[data-descendants_count='3'] span:contains('Root with children')");
assert.containsOnce(target.querySelector(".account_report_lines_list_x2many"), "li[data-descendants_count='1'] span:contains('Child #1')");
assert.containsOnce(target.querySelector(".account_report_lines_list_x2many"), "li[data-descendants_count='0'] span:contains('Grandchild')");
assert.containsOnce(target.querySelector(".account_report_lines_list_x2many"), "li[data-descendants_count='0'] span:contains('Child #2')");
});
//------------------------------------------------------------------------------------------------------------------
// Create
//------------------------------------------------------------------------------------------------------------------
QUnit.test("can create a line", async (assert) => {
await makeView({
type: "form",
resId: 1,
resModel: "report",
serverData,
arch,
});
await click(target.querySelector(".account_report_lines_list_x2many"), "li:last-of-type a");
assert.containsOnce(target, ".o_dialog");
await editInput(target.querySelector("div[name='name'] input"), null, "Created line");
await click(target.querySelector(".o_dialog"), ".o_form_button_save");
assert.containsOnce(target.querySelector(".account_report_lines_list_x2many"), "li span:contains('Created line')");
});
//------------------------------------------------------------------------------------------------------------------
// Edit
//------------------------------------------------------------------------------------------------------------------
QUnit.test("can edit a line", async (assert) => {
await makeView({
type: "form",
resId: 1,
resModel: "report",
serverData,
arch,
});
await click(target.querySelector(".account_report_lines_list_x2many"), "li[data-record_id='1'] .column");
assert.containsOnce(target, ".o_dialog");
await editInput(target.querySelector("div[name='name'] input"), null, "Line without children (edited)");
await click(target.querySelector(".o_dialog"), ".o_form_button_save");
assert.containsOnce(target.querySelector(".account_report_lines_list_x2many"), "li span:contains('Line without children (edited)')");
});
//------------------------------------------------------------------------------------------------------------------
// Delete
//------------------------------------------------------------------------------------------------------------------
QUnit.test("can delete a root", async (assert) => {
await makeView({
type: "form",
resId: 1,
resModel: "report",
serverData,
arch,
});
await click(target.querySelector(".account_report_lines_list_x2many"), "li[data-record_id='1'] > div > .trash");
assert.containsNone(target.querySelector(".account_report_lines_list_x2many"), "li span:contains('Root without children')");
assert.containsOnce(target.querySelector(".account_report_lines_list_x2many"), "li span:contains('Root with children')");
assert.containsOnce(target.querySelector(".account_report_lines_list_x2many"), "li span:contains('Child #1')");
assert.containsOnce(target.querySelector(".account_report_lines_list_x2many"), "li span:contains('Grandchild')");
assert.containsOnce(target.querySelector(".account_report_lines_list_x2many"), "li span:contains('Child #2')");
});
QUnit.test("can delete a root with children", async (assert) => {
await makeView({
type: "form",
resId: 1,
resModel: "report",
serverData,
arch,
});
await click(target.querySelector(".account_report_lines_list_x2many"), "li[data-record_id='2'] > div > .trash");
// Confirmation dialog "This line and all its children will be deleted. Are you sure you want to proceed?"
assert.containsOnce(target, ".o_dialog");
await click(target.querySelector(".o_dialog"), ".btn-primary");
assert.containsOnce(target.querySelector(".account_report_lines_list_x2many"), "li span:contains('Root without children')");
assert.containsNone(target.querySelector(".account_report_lines_list_x2many"), "li span:contains('Root with children')");
assert.containsNone(target.querySelector(".account_report_lines_list_x2many"), "li span:contains('Child #1')");
assert.containsNone(target.querySelector(".account_report_lines_list_x2many"), "li span:contains('Grandchild')");
assert.containsNone(target.querySelector(".account_report_lines_list_x2many"), "li span:contains('Child #2')");
});
QUnit.test("can delete a last child", async (assert) => {
await makeView({
type: "form",
resId: 1,
resModel: "report",
serverData,
arch,
});
await click(target.querySelector(".account_report_lines_list_x2many"), "li[data-record_id='4'] > div > .trash");
assert.containsOnce(target.querySelector(".account_report_lines_list_x2many"), "li span:contains('Root without children')");
assert.containsOnce(target.querySelector(".account_report_lines_list_x2many"), "li[data-descendants_count='2'] span:contains('Root with children')");
assert.containsOnce(target.querySelector(".account_report_lines_list_x2many"), "li[data-descendants_count='0'] span:contains('Child #1')");
assert.containsNone(target.querySelector(".account_report_lines_list_x2many"), "li span:contains('Grandchild')");
assert.containsOnce(target.querySelector(".account_report_lines_list_x2many"), "li span:contains('Child #2')");
});
//------------------------------------------------------------------------------------------------------------------
// Drag and drop
//------------------------------------------------------------------------------------------------------------------
QUnit.test("can move a root down", async (assert) => {
serverData.models.report.records[0].line_ids = [1, 2, 3, 4];
serverData.models.report_lines.records = [
{
id: 1,
sequence: null,
parent_id: false,
hierarchy_level: 1,
name: "dragged",
code: "D",
},
{
id: 2,
sequence: null,
parent_id: false,
hierarchy_level: 1,
name: "noChild",
code: "N",
},
{
id: 3,
sequence: null,
parent_id: false,
hierarchy_level: 0,
name: "parent",
code: "P",
},
{
id: 4,
sequence: null,
parent_id: 3,
hierarchy_level: 3,
name: "child",
code: "C",
},
];
await makeView({
type: "form",
resId: 1,
resModel: "report",
serverData,
arch,
mockRPC: (route, args) => {
if (args.method === 'web_save') {
const lineIds = args.args[1].line_ids;
// Parents
assert.equal(lineIds[0][2].parent_id, 3);
// Hierarchy levels
assert.equal(lineIds[0][2].hierarchy_level, 3);
// Sequences
assert.equal(lineIds[0][2].sequence, 4);
assert.equal(lineIds[1][2].sequence, 1);
assert.equal(lineIds[2][2].sequence, 2);
assert.equal(lineIds[3][2].sequence, 3);
}
}
});
const { drop, moveUnder } = await sortableDrag("li[data-record_id='1']");
await moveUnder("li[data-record_id='2']");
await moveUnder("li[data-record_id='4']");
await drop();
await click(target.querySelector(".o_form_button_save"));
});
QUnit.test("can move a root up", async (assert) => {
serverData.models.report.records[0].line_ids = [1, 2, 3, 4];
serverData.models.report_lines.records = [
{
id: 1,
sequence: null,
parent_id: false,
hierarchy_level: 0,
name: "parent",
code: "P",
},
{
id: 2,
sequence: null,
parent_id: 1,
hierarchy_level: 3,
name: "child",
code: "C",
},
{
id: 3,
sequence: null,
parent_id: false,
hierarchy_level: 1,
name: "noChild",
code: "N",
},
{
id: 4,
sequence: null,
parent_id: false,
hierarchy_level: 1,
name: "dragged",
code: "D",
},
];
await makeView({
type: "form",
resId: 1,
resModel: "report",
serverData,
arch,
mockRPC: (route, args) => {
if (args.method === 'web_save') {
const lineIds = args.args[1].line_ids;
// Parents
assert.equal(lineIds[0][2].parent_id, 1);
// Hierarchy levels
assert.equal(lineIds[0][2].hierarchy_level, 3);
// Sequences
assert.equal(lineIds[0][2].sequence, 2);
assert.equal(lineIds[1][2].sequence, 1);
assert.equal(lineIds[2][2].sequence, 3);
assert.equal(lineIds[3][2].sequence, 4);
}
}
});
const { drop, moveAbove } = await sortableDrag("li[data-record_id='4']");
await moveAbove("li[data-record_id='3']");
await moveAbove("li[data-record_id='2']");
await drop();
await click(target.querySelector(".o_form_button_save"));
});
QUnit.test("can move a child down", async (assert) => {
serverData.models.report.records[0].line_ids = [1, 2, 3, 4];
serverData.models.report_lines.records = [
{
id: 1,
sequence: null,
parent_id: false,
hierarchy_level: 0,
name: "parent",
code: "P",
},
{
id: 2,
sequence: null,
parent_id: 1,
hierarchy_level: 3,
name: "dragged",
code: "D",
},
{
id: 3,
sequence: null,
parent_id: 1,
hierarchy_level: 3,
name: "child",
code: "C",
},
{
id: 4,
sequence: null,
parent_id: false,
hierarchy_level: 1,
name: "noChild",
code: "N",
},
];
await makeView({
type: "form",
resId: 1,
resModel: "report",
serverData,
arch,
mockRPC: (route, args) => {
if (args.method === 'web_save') {
const lineIds = args.args[1].line_ids;
// Parents
assert.equal(lineIds[0][2].parent_id, false);
// Hierarchy levels
assert.equal(lineIds[0][2].hierarchy_level, 1);
// Sequences
assert.equal(lineIds[0][2].sequence, 4);
assert.equal(lineIds[1][2].sequence, 1);
assert.equal(lineIds[2][2].sequence, 2);
assert.equal(lineIds[3][2].sequence, 3);
}
}
});
const { drop, moveUnder } = await sortableDrag("li[data-record_id='2']");
await moveUnder("li[data-record_id='3']");
await moveUnder("li[data-record_id='4']");
await drop();
await click(target.querySelector(".o_form_button_save"));
});
QUnit.test("can move a child up", async (assert) => {
serverData.models.report.records[0].line_ids = [1, 2, 3];
serverData.models.report_lines.records = [
{
id: 1,
sequence: null,
parent_id: false,
hierarchy_level: 0,
name: "parent",
code: "P",
},
{
id: 2,
sequence: null,
parent_id: 1,
hierarchy_level: 3,
name: "child",
code: "C",
},
{
id: 3,
sequence: null,
parent_id: 1,
hierarchy_level: 3,
name: "dragged",
code: "D",
},
];
await makeView({
type: "form",
resId: 1,
resModel: "report",
serverData,
arch,
mockRPC: (route, args) => {
if (args.method === 'web_save') {
const lineIds = args.args[1].line_ids;
// Parents
assert.equal(lineIds[0][2].parent_id, false);
// Hierarchy levels
assert.equal(lineIds[0][2].hierarchy_level, 1);
// Sequences
assert.equal(lineIds[0][2].sequence, 1);
assert.equal(lineIds[1][2].sequence, 2);
assert.equal(lineIds[2][2].sequence, 3);
}
}
});
const { drop, moveAbove } = await sortableDrag("li[data-record_id='3']");
await moveAbove("li[data-record_id='2']");
await moveAbove("li[data-record_id='1']");
await drop();
await click(target.querySelector(".o_form_button_save"));
});
QUnit.test("can move a new root into a child", async (assert) => {
serverData.models.report.records[0].line_ids = [1, 2, 3];
serverData.models.report_lines.records = [
{
id: 1,
sequence: null,
parent_id: false,
hierarchy_level: 0,
name: "parent",
code: "P",
},
{
id: 2,
sequence: null,
parent_id: 1,
hierarchy_level: 3,
name: "child",
code: "C",
},
{
id: 3,
sequence: null,
parent_id: false,
hierarchy_level: 1,
name: "noChild",
code: "N",
},
];
await makeView({
type: "form",
resId: 1,
resModel: "report",
serverData,
arch,
mockRPC: (route, args) => {
if (args.method === 'web_save' && !target.querySelector(".o_dialog")) {
const lineIds = args.args[1].line_ids;
// Parents
assert.equal(lineIds[0][2].parent_id, 1);
// Hierarchy levels
assert.equal(lineIds[0][2].hierarchy_level, 3);
// Sequences
assert.equal(lineIds[0][2].sequence, 2);
assert.equal(lineIds[1][2].sequence, 1);
assert.equal(lineIds[2][2].sequence, 3);
assert.equal(lineIds[3][2].sequence, 4);
}
}
});
await click(target.querySelector(".account_report_lines_list_x2many"), "li:last-of-type a");
await editInput(target.querySelector("div[name='name'] input"), null, "dragged");
await click(target.querySelector(".o_dialog"), ".o_form_button_save");
const { drop, moveAbove } = await sortableDrag("li[data-record_id='4']");
await moveAbove("li[data-record_id='3']");
await moveAbove("li[data-record_id='2']");
await drop();
await click(target.querySelector(".o_form_button_save"));
});
QUnit.test("can move a child into a new root", async (assert) => {
serverData.models.report.records[0].line_ids = [];
serverData.models.report_lines.records = [];
await makeView({
type: "form",
resId: 1,
resModel: "report",
serverData,
arch,
mockRPC: (route, args) => {
if (args.method === 'web_save' && !target.querySelector(".o_dialog")) {
const lineIds = args.args[1].line_ids;
// Parents
assert.equal(lineIds[0][2].parent_id, 1);
// Hierarchy levels
assert.equal(lineIds[0][2].hierarchy_level, 3);
// Sequences
assert.equal(lineIds[0][2].sequence, 2);
assert.equal(lineIds[1][2].sequence, 1);
}
}
});
await click(target.querySelector(".account_report_lines_list_x2many"), "li:last-of-type a");
await editInput(target.querySelector("div[name='name'] input"), null, "parent");
await click(target.querySelector(".o_dialog"), ".o_form_button_save");
await click(target.querySelector(".account_report_lines_list_x2many"), "li:last-of-type a");
await editInput(target.querySelector("div[name='name'] input"), null, "dragged");
await click(target.querySelector(".o_dialog"), ".o_form_button_save");
const toSelector = target.querySelector("li[data-record_id='2']");
const { drop, moveTo } = await drag(toSelector);
await moveTo(toSelector, { x: 600 });
await drop();
await click(target.querySelector(".o_form_button_save"));
});
});

View File

@@ -0,0 +1,52 @@
/** @odoo-module **/
import { mockDownload } from "@web/../tests/helpers/utils";
import { createWebClient, doAction } from "@web/../tests/webclient/helpers";
let serverData;
QUnit.module('Account Reports', {}, function () {
QUnit.test('can execute account report download actions', async function (assert) {
assert.expect(5);
const actions = {
1: {
id: 1,
data: {
model: 'some_model',
options: {
someOption: true,
},
output_format: 'pdf',
},
type: 'ir_actions_account_report_download',
},
};
serverData = {actions};
mockDownload((options) => {
assert.step(options.url);
assert.deepEqual(options.data, {
model: 'some_model',
options: {
someOption: true,
},
output_format: 'pdf',
}, "should give the correct data");
return Promise.resolve();
});
const webClient = await createWebClient({
serverData,
mockRPC: function (route, args) {
assert.step(args.method || route);
},
});
await doAction(webClient, 1);
assert.verifySteps([
'/web/webclient/load_menus',
'/web/action/load',
'/fusion_accounting',
]);
});
});