Initial commit
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
import { expect, test } from "@odoo/hoot";
|
||||
import { click, press } from "@odoo/hoot-dom";
|
||||
import { animationFrame } from "@odoo/hoot-mock";
|
||||
import { mountWithCleanup, makeMockEnv, defineModels } from "@web/../tests/web_test_helpers";
|
||||
import { mailModels } from "@mail/../tests/mail_test_helpers";
|
||||
|
||||
import { AccountReportLineCellEditable } from "@fusion_accounting/components/account_report/line_cell_editable/line_cell_editable";
|
||||
|
||||
// Due to dependency with mail module, we have to define their models for our tests.
|
||||
defineModels(mailModels);
|
||||
|
||||
test("can unformat a value when focus and format when blur", async () => {
|
||||
const env = await makeMockEnv({
|
||||
controller: {},
|
||||
});
|
||||
await mountWithCleanup(AccountReportLineCellEditable, {
|
||||
env,
|
||||
props: {
|
||||
cell: {
|
||||
name: "5,702.22",
|
||||
no_format: 5702.22,
|
||||
edit_popup_data: {},
|
||||
},
|
||||
line: {},
|
||||
},
|
||||
});
|
||||
|
||||
expect(".o_input").toHaveValue("5,702.22");
|
||||
await click(".o_input");
|
||||
await animationFrame();
|
||||
expect(".o_input").toHaveValue("5702.22");
|
||||
await press("Enter");
|
||||
await animationFrame();
|
||||
expect(".o_input").toHaveValue("5,702.22");
|
||||
});
|
||||
649
Fusion Accounting/static/tests/legacy/account_report_builder.js
Normal file
649
Fusion Accounting/static/tests/legacy/account_report_builder.js
Normal 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"));
|
||||
});
|
||||
});
|
||||
@@ -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',
|
||||
]);
|
||||
|
||||
});
|
||||
});
|
||||
340
Fusion Accounting/static/tests/move_line.test.js
Normal file
340
Fusion Accounting/static/tests/move_line.test.js
Normal file
@@ -0,0 +1,340 @@
|
||||
import { beforeEach, test } from "@odoo/hoot";
|
||||
import { defineAccountModels } from "@account/../tests/account_test_helpers";
|
||||
import {
|
||||
assertSteps,
|
||||
click,
|
||||
contains,
|
||||
onRpcBefore,
|
||||
openListView,
|
||||
patchUiSize,
|
||||
SIZES,
|
||||
start,
|
||||
startServer,
|
||||
step,
|
||||
} from "@mail/../tests/mail_test_helpers";
|
||||
import { onRpc, serverState } from "@web/../tests/web_test_helpers";
|
||||
import { getOrigin } from "@web/core/utils/urls";
|
||||
|
||||
const ROUTES_TO_IGNORE = [
|
||||
"/bus/im_status",
|
||||
"/web/dataset/call_kw/account.move.line/get_views",
|
||||
"/web/webclient/load_menus",
|
||||
"/web/dataset/call_kw/res.users/load_views",
|
||||
"/hr_attendance/attendance_user_data",
|
||||
"/web/dataset/call_kw/res.users/has_group",
|
||||
];
|
||||
const openPreparedView = async (size) => {
|
||||
patchUiSize({ size: size });
|
||||
onRpcBefore((route, args) => {
|
||||
if (
|
||||
ROUTES_TO_IGNORE.includes(route) ||
|
||||
route.includes("/web/static/lib/pdfjs/web/viewer.html")
|
||||
) {
|
||||
return;
|
||||
}
|
||||
step(`${route} - ${JSON.stringify(args)}`);
|
||||
});
|
||||
onRpc(({ method, model, args, kwargs }) => {
|
||||
const route = `/web/dataset/call_kw/${model}/${method}`;
|
||||
if (ROUTES_TO_IGNORE.includes(route)) {
|
||||
return;
|
||||
}
|
||||
step(`${route} - {"kwargs":${JSON.stringify(kwargs)}}`);
|
||||
});
|
||||
await start();
|
||||
await assertSteps([
|
||||
`/mail/data - ${JSON.stringify({
|
||||
init_messaging: {},
|
||||
failures: true,
|
||||
systray_get_activities: true,
|
||||
context: { lang: "en", tz: "taht", uid: serverState.userId, allowed_company_ids: [1] },
|
||||
})}`,
|
||||
]);
|
||||
await openListView("account.move.line", {
|
||||
context: { group_by: ["move_id"] },
|
||||
arch: `
|
||||
<list editable='bottom' js_class='account_move_line_list'>
|
||||
<field name='id'/>
|
||||
<field name='name'/>
|
||||
<field name='move_id'/>
|
||||
</list>`,
|
||||
});
|
||||
};
|
||||
|
||||
defineAccountModels();
|
||||
|
||||
beforeEach(async () => {
|
||||
const pyEnv = await startServer();
|
||||
const accountMoveLineIds = pyEnv["account.move.line"].create([
|
||||
{ name: "line0" },
|
||||
{ name: "line1" },
|
||||
{ name: "line2" },
|
||||
{ name: "line3" },
|
||||
{ name: "line4" },
|
||||
{ name: "line5" },
|
||||
]);
|
||||
const accountMove = pyEnv["account.move"].create([
|
||||
{ name: "move0", invoice_line_ids: [accountMoveLineIds[0], accountMoveLineIds[1]] },
|
||||
{ name: "move1", invoice_line_ids: [accountMoveLineIds[2], accountMoveLineIds[3]] },
|
||||
{ name: "move2", invoice_line_ids: [accountMoveLineIds[4], accountMoveLineIds[5]] },
|
||||
]);
|
||||
const attachmentIds = pyEnv["ir.attachment"].create([
|
||||
{ res_id: accountMove[1], res_model: "account.move", mimetype: "application/pdf" },
|
||||
{ res_id: accountMove[2], res_model: "account.move", mimetype: "application/pdf" },
|
||||
]);
|
||||
pyEnv["account.move"].write([accountMove[1]], { attachment_ids: [attachmentIds[0]] });
|
||||
pyEnv["account.move.line"].write([accountMoveLineIds[0]], { move_id: accountMove[0] });
|
||||
pyEnv["account.move.line"].write([accountMoveLineIds[1]], { move_id: accountMove[0] });
|
||||
pyEnv["account.move.line"].write([accountMoveLineIds[2]], {
|
||||
move_id: accountMove[1],
|
||||
move_attachment_ids: [attachmentIds[0]],
|
||||
});
|
||||
pyEnv["account.move.line"].write([accountMoveLineIds[3]], {
|
||||
move_id: accountMove[1],
|
||||
move_attachment_ids: [attachmentIds[0]],
|
||||
});
|
||||
pyEnv["account.move.line"].write([accountMoveLineIds[4]], {
|
||||
move_id: accountMove[2],
|
||||
move_attachment_ids: [attachmentIds[1]],
|
||||
});
|
||||
pyEnv["account.move.line"].write([accountMoveLineIds[5]], {
|
||||
move_id: accountMove[2],
|
||||
move_attachment_ids: [attachmentIds[1]],
|
||||
});
|
||||
});
|
||||
|
||||
test("No preview on small devices", async () => {
|
||||
await openPreparedView(SIZES.XL);
|
||||
await contains(".o_move_line_list_view");
|
||||
await assertSteps([
|
||||
`/web/dataset/call_kw/account.move.line/web_read_group - ${JSON.stringify({
|
||||
kwargs: {
|
||||
orderby: "",
|
||||
lazy: true,
|
||||
offset: 0,
|
||||
limit: 80,
|
||||
context: {
|
||||
lang: "en",
|
||||
tz: "taht",
|
||||
uid: serverState.userId,
|
||||
allowed_company_ids: [1],
|
||||
group_by: ["move_id"],
|
||||
},
|
||||
groupby: ["move_id"],
|
||||
domain: [],
|
||||
fields: ["id:sum"],
|
||||
},
|
||||
})}`,
|
||||
]);
|
||||
// weak test, no guarantee to wait long enough for the potential attachment preview to show
|
||||
await contains(".o_attachment_preview", { count: 0 }); // The preview component shouldn't be mounted for small screens
|
||||
await click(":nth-child(1 of .o_group_header)");
|
||||
await contains(".o_data_row", { count: 2 });
|
||||
await assertSteps([
|
||||
`/web/dataset/call_kw/account.move.line/web_search_read - ${JSON.stringify({
|
||||
kwargs: {
|
||||
specification: {
|
||||
id: {},
|
||||
name: {},
|
||||
move_id: { fields: { display_name: {} } },
|
||||
move_attachment_ids: { fields: { mimetype: {} } },
|
||||
},
|
||||
offset: 0,
|
||||
order: "",
|
||||
limit: 80,
|
||||
context: {
|
||||
lang: "en",
|
||||
tz: "taht",
|
||||
uid: serverState.userId,
|
||||
allowed_company_ids: [1],
|
||||
bin_size: true,
|
||||
group_by: ["move_id"],
|
||||
default_move_id: 1,
|
||||
},
|
||||
count_limit: 10001,
|
||||
domain: [["move_id", "=", 1]],
|
||||
},
|
||||
})}`,
|
||||
]);
|
||||
await click(":nth-child(1 of .o_data_row) :nth-child(2 of .o_data_cell)");
|
||||
await contains(":nth-child(1 of .o_data_row) :nth-child(2 of .o_data_cell) input");
|
||||
// weak test, no guarantee to wait long enough for the potential attachment preview to show
|
||||
await contains(".o_attachment_preview", { count: 0 }); // The preview component shouldn't be mounted for small screens even when clicking on a line without attachment
|
||||
await click(":nth-child(2 of .o_group_header)");
|
||||
await contains(".o_data_row", { count: 4 });
|
||||
await assertSteps([
|
||||
`/web/dataset/call_kw/account.move.line/web_search_read - ${JSON.stringify({
|
||||
kwargs: {
|
||||
specification: {
|
||||
id: {},
|
||||
name: {},
|
||||
move_id: { fields: { display_name: {} } },
|
||||
move_attachment_ids: { fields: { mimetype: {} } },
|
||||
},
|
||||
offset: 0,
|
||||
order: "",
|
||||
limit: 80,
|
||||
context: {
|
||||
lang: "en",
|
||||
tz: "taht",
|
||||
uid: serverState.userId,
|
||||
allowed_company_ids: [1],
|
||||
bin_size: true,
|
||||
group_by: ["move_id"],
|
||||
default_move_id: 2,
|
||||
},
|
||||
count_limit: 10001,
|
||||
domain: [["move_id", "=", 2]],
|
||||
},
|
||||
})}`,
|
||||
]);
|
||||
await click(":nth-child(4 of .o_data_row) :nth-child(2 of .o_data_cell)");
|
||||
await contains(":nth-child(4 of .o_data_row) :nth-child(2 of .o_data_cell) input");
|
||||
// weak test, no guarantee to wait long enough for the potential attachment preview to show
|
||||
await contains(".o_attachment_preview", { count: 0 }); // The preview component shouldn't be mounted for small screens even when clicking on a line with attachment
|
||||
await assertSteps([], "no extra rpc should be done");
|
||||
});
|
||||
|
||||
test("Fetch and preview of attachments on big devices", async () => {
|
||||
await openPreparedView(SIZES.XXL);
|
||||
await contains(".o_move_line_list_view");
|
||||
await assertSteps([
|
||||
`/web/dataset/call_kw/account.move.line/web_read_group - ${JSON.stringify({
|
||||
kwargs: {
|
||||
orderby: "",
|
||||
lazy: true,
|
||||
offset: 0,
|
||||
limit: 80,
|
||||
context: {
|
||||
lang: "en",
|
||||
tz: "taht",
|
||||
uid: serverState.userId,
|
||||
allowed_company_ids: [1],
|
||||
group_by: ["move_id"],
|
||||
},
|
||||
groupby: ["move_id"],
|
||||
domain: [],
|
||||
fields: ["id:sum"],
|
||||
},
|
||||
})}`,
|
||||
]);
|
||||
await contains(".o_attachment_preview");
|
||||
await contains(".o_attachment_preview p", {
|
||||
text: "Choose a line to preview its attachments.",
|
||||
});
|
||||
await contains(".o_attachment_preview iframe", { count: 0 });
|
||||
await click(":nth-child(1 of .o_group_header)");
|
||||
await contains(".o_data_row", { count: 2 });
|
||||
await assertSteps([
|
||||
`/web/dataset/call_kw/account.move.line/web_search_read - ${JSON.stringify({
|
||||
kwargs: {
|
||||
specification: {
|
||||
id: {},
|
||||
name: {},
|
||||
move_id: { fields: { display_name: {} } },
|
||||
move_attachment_ids: { fields: { mimetype: {} } },
|
||||
},
|
||||
offset: 0,
|
||||
order: "",
|
||||
limit: 80,
|
||||
context: {
|
||||
lang: "en",
|
||||
tz: "taht",
|
||||
uid: serverState.userId,
|
||||
allowed_company_ids: [1],
|
||||
bin_size: true,
|
||||
group_by: ["move_id"],
|
||||
default_move_id: 1,
|
||||
},
|
||||
count_limit: 10001,
|
||||
domain: [["move_id", "=", 1]],
|
||||
},
|
||||
})}`,
|
||||
]);
|
||||
await click(":nth-child(1 of .o_data_row) :nth-child(2 of .o_data_cell)");
|
||||
await contains(".o_attachment_preview iframe", { count: 0 });
|
||||
await contains(".o_attachment_preview p", { text: "No attachments linked." });
|
||||
await click(":nth-child(2 of .o_group_header)");
|
||||
await contains(".o_data_row", { count: 4 });
|
||||
await contains(".o_attachment_preview p", { text: "No attachments linked." });
|
||||
await assertSteps([
|
||||
`/web/dataset/call_kw/account.move.line/web_search_read - ${JSON.stringify({
|
||||
kwargs: {
|
||||
specification: {
|
||||
id: {},
|
||||
name: {},
|
||||
move_id: { fields: { display_name: {} } },
|
||||
move_attachment_ids: { fields: { mimetype: {} } },
|
||||
},
|
||||
offset: 0,
|
||||
order: "",
|
||||
limit: 80,
|
||||
context: {
|
||||
lang: "en",
|
||||
tz: "taht",
|
||||
uid: serverState.userId,
|
||||
allowed_company_ids: [1],
|
||||
bin_size: true,
|
||||
group_by: ["move_id"],
|
||||
default_move_id: 2,
|
||||
},
|
||||
count_limit: 10001,
|
||||
domain: [["move_id", "=", 2]],
|
||||
},
|
||||
})}`,
|
||||
]);
|
||||
await click(":nth-child(4 of .o_data_row) :nth-child(2 of .o_data_cell)");
|
||||
await contains(".o_attachment_preview p", { count: 0 });
|
||||
await contains(
|
||||
`.o_attachment_preview iframe[data-src='/web/static/lib/pdfjs/web/viewer.html?file=${encodeURIComponent(
|
||||
getOrigin() + "/web/content/1"
|
||||
)}#pagemode=none']`
|
||||
);
|
||||
await assertSteps([], "no extra rpc should be done");
|
||||
await click(":nth-child(3 of .o_group_header)");
|
||||
await contains(".o_data_row", { count: 6 });
|
||||
// weak test, no guarantee to wait long enough for the potential attachment to change
|
||||
await contains(
|
||||
`.o_attachment_preview iframe[data-src='/web/static/lib/pdfjs/web/viewer.html?file=${encodeURIComponent(
|
||||
getOrigin() + "/web/content/1"
|
||||
)}#pagemode=none']`
|
||||
); // The previewer content shouldn't change without clicking on another line from another account.move
|
||||
await assertSteps([
|
||||
`/web/dataset/call_kw/account.move.line/web_search_read - ${JSON.stringify({
|
||||
kwargs: {
|
||||
specification: {
|
||||
id: {},
|
||||
name: {},
|
||||
move_id: { fields: { display_name: {} } },
|
||||
move_attachment_ids: { fields: { mimetype: {} } },
|
||||
},
|
||||
offset: 0,
|
||||
order: "",
|
||||
limit: 80,
|
||||
context: {
|
||||
lang: "en",
|
||||
tz: "taht",
|
||||
uid: serverState.userId,
|
||||
allowed_company_ids: [1],
|
||||
bin_size: true,
|
||||
group_by: ["move_id"],
|
||||
default_move_id: 3,
|
||||
},
|
||||
count_limit: 10001,
|
||||
domain: [["move_id", "=", 3]],
|
||||
},
|
||||
})}`,
|
||||
]);
|
||||
await click(":nth-child(5 of .o_data_row) :nth-child(2 of .o_data_cell)");
|
||||
await contains(":nth-child(5 of .o_data_row) :nth-child(2 of .o_data_cell) input");
|
||||
await contains(
|
||||
`.o_attachment_preview iframe[data-src='/web/static/lib/pdfjs/web/viewer.html?file=${encodeURIComponent(
|
||||
getOrigin() + "/web/content/2"
|
||||
)}#pagemode=none']`
|
||||
);
|
||||
await assertSteps([]);
|
||||
await click(":nth-child(1 of .o_data_row) :nth-child(2 of .o_data_cell)");
|
||||
await contains(".o_attachment_preview iframe", { count: 0 });
|
||||
await contains(".o_attachment_preview p");
|
||||
await assertSteps([]);
|
||||
});
|
||||
35
Fusion Accounting/static/tests/tours/account.js
Normal file
35
Fusion Accounting/static/tests/tours/account.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import { _t } from "@web/core/l10n/translation";
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
import { accountTourSteps } from "@account/js/tours/account";
|
||||
|
||||
patch(accountTourSteps, {
|
||||
onboarding() {
|
||||
return [
|
||||
{
|
||||
trigger: ".o_widget_account_onboarding .fa-circle",
|
||||
},
|
||||
{
|
||||
trigger: "a[data-method=action_open_step_fiscal_year]",
|
||||
content: _t("Set Periods"),
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: "button[name=action_save_onboarding_fiscal_year]",
|
||||
content: _t("Save Fiscal Year end"),
|
||||
run: "click",
|
||||
},
|
||||
];
|
||||
},
|
||||
newInvoice() {
|
||||
return [
|
||||
{
|
||||
trigger: ".o_widget_account_onboarding .fa-check-circle",
|
||||
},
|
||||
{
|
||||
trigger: "button[name=action_create_new]",
|
||||
content: _t("Now, we'll create your first invoice (accountant)"),
|
||||
run: "click",
|
||||
},
|
||||
];
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,61 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import { accountTourSteps } from "@account/js/tours/account";
|
||||
import { registry } from "@web/core/registry";
|
||||
|
||||
registry.category("web_tour.tours").add("account_merge_wizard_tour", {
|
||||
url: "/odoo",
|
||||
steps: () => [
|
||||
...accountTourSteps.goToAccountMenu("Go to Accounting"),
|
||||
{
|
||||
content: "Go to Configuration",
|
||||
trigger: 'span:contains("Configuration")',
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Go to Chart of Accounts",
|
||||
trigger: 'a:contains("Chart of Accounts")',
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: '.o_breadcrumb .text-truncate:contains("Chart of Accounts")',
|
||||
},
|
||||
{
|
||||
content: "Select accounts",
|
||||
trigger: "thead .o_list_record_selector",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Check that exactly 4 accounts are present and selected",
|
||||
trigger: ".o_list_selection_box:contains(4):contains(selected)",
|
||||
},
|
||||
{
|
||||
content: "Open Actions menu",
|
||||
trigger: ".o_cp_action_menus .dropdown-toggle",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Open Merge accounts wizard",
|
||||
trigger: 'span:contains("Merge accounts")',
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Group by name",
|
||||
trigger: 'div[name="is_group_by_name"] input',
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Wait for content to be updated",
|
||||
trigger: 'td:contains("Current Assets (Current Assets)")',
|
||||
},
|
||||
{
|
||||
content: "Merge accounts",
|
||||
trigger: 'button:not([disabled]) span:contains("Merge")',
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Check that there are now exactly 2 accounts",
|
||||
trigger: "tr.o_data_row:contains(2)",
|
||||
},
|
||||
],
|
||||
});
|
||||
262
Fusion Accounting/static/tests/tours/account_reports.js
Normal file
262
Fusion Accounting/static/tests/tours/account_reports.js
Normal file
@@ -0,0 +1,262 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { Asserts } from "./asserts";
|
||||
import { registry } from "@web/core/registry";
|
||||
|
||||
registry.category("web_tour.tours").add("account_reports", {
|
||||
url: "/odoo/action-fusion_accounting.action_account_report_bs",
|
||||
steps: () => [
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
// Foldable
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
content: "Initial foldable",
|
||||
trigger: ".o_content",
|
||||
run: () => {
|
||||
Asserts.DOMContainsNumber("tbody > tr:not(.d-none):not(.empty)", 28);
|
||||
|
||||
// Since the total line is not displayed (folded), the amount should be on the line
|
||||
Asserts.isEqual(
|
||||
document.querySelector("tr:nth-child(4) td:nth-child(2)").textContent,
|
||||
"75.00"
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
content: "Click to unfold line",
|
||||
trigger: "tr:nth-child(4) td:first()",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Line is unfolded",
|
||||
trigger: "tr:nth-child(5) .name:contains('101401')",
|
||||
run: () => {
|
||||
Asserts.DOMContainsNumber("tbody > tr:not(.d-none):not(.empty)", 30);
|
||||
|
||||
// Since the total line is displayed (unfolded), the amount should not be on the line
|
||||
Asserts.isEqual(
|
||||
document.querySelector("tr:nth-child(4) td:nth-child(2)").textContent,
|
||||
""
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
content: "Click to fold line",
|
||||
trigger: "tr:nth-child(4) td:first()",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Line is folded",
|
||||
trigger: ".o_content",
|
||||
run: () => {
|
||||
Asserts.DOMContainsNumber("tbody > tr:not(.d-none):not(.empty)", 28);
|
||||
},
|
||||
},
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
// Sortable
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
content: "Unfold first line",
|
||||
trigger: "tr:nth-child(4) td:first()",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Unfold second line",
|
||||
trigger: "tr:nth-child(7) td:first()",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Unfold third line",
|
||||
trigger: "tr:nth-child(10) td:first()",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Extra Trigger step",
|
||||
trigger: "tr:nth-child(12):not(.d-none) .name:contains('101404')",
|
||||
},
|
||||
{
|
||||
content: "Initial sortable",
|
||||
trigger: ".o_content",
|
||||
run: () => {
|
||||
// Bank and Cash Accounts
|
||||
Asserts.isEqual(
|
||||
document.querySelector("tr:nth-child(5) td:nth-child(2)").textContent,
|
||||
"75.00"
|
||||
);
|
||||
Asserts.isEqual(
|
||||
document.querySelector("tr:nth-child(6) td:nth-child(2)").textContent,
|
||||
"75.00"
|
||||
);
|
||||
|
||||
// Receivables
|
||||
Asserts.isEqual(
|
||||
document.querySelector("tr:nth-child(8) td:nth-child(2)").textContent,
|
||||
"25.00"
|
||||
);
|
||||
Asserts.isEqual(
|
||||
document.querySelector("tr:nth-child(9) td:nth-child(2)").textContent,
|
||||
"25.00"
|
||||
);
|
||||
|
||||
// Current Assets
|
||||
Asserts.isEqual(
|
||||
document.querySelector("tr:nth-child(11) td:nth-child(2)").textContent,
|
||||
"100.00"
|
||||
);
|
||||
Asserts.isEqual(
|
||||
document.querySelector("tr:nth-child(12) td:nth-child(2)").textContent,
|
||||
"50.00"
|
||||
);
|
||||
Asserts.isEqual(
|
||||
document.querySelector("tr:nth-child(13) td:nth-child(2)").textContent,
|
||||
"150.00"
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
content: "Click sort",
|
||||
trigger: "th .btn_sortable",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: "tr:nth-child(11) td:nth-child(2):contains('50.00')",
|
||||
},
|
||||
{
|
||||
content: "Unfold not previously unfolded line",
|
||||
trigger: "tr:nth-child(22):contains('Current Liabilities') td:first()",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Line is unfolded",
|
||||
trigger: "tr:nth-child(23) .name:contains('251000')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Sortable (asc)",
|
||||
trigger: "tr:nth-child(11) td:nth-child(2):contains('50.00')",
|
||||
run: () => {
|
||||
// Bank and Cash Accounts
|
||||
Asserts.isEqual(
|
||||
document.querySelector("tr:nth-child(5) td:nth-child(2)").textContent,
|
||||
"75.00"
|
||||
);
|
||||
Asserts.isEqual(
|
||||
document.querySelector("tr:nth-child(6) td:nth-child(2)").textContent,
|
||||
"75.00"
|
||||
);
|
||||
|
||||
// Receivables
|
||||
Asserts.isEqual(
|
||||
document.querySelector("tr:nth-child(8) td:nth-child(2)").textContent,
|
||||
"25.00"
|
||||
);
|
||||
Asserts.isEqual(
|
||||
document.querySelector("tr:nth-child(9) td:nth-child(2)").textContent,
|
||||
"25.00"
|
||||
);
|
||||
|
||||
// Current Assets
|
||||
Asserts.isEqual(
|
||||
document.querySelector("tr:nth-child(11) td:nth-child(2)").textContent,
|
||||
"50.00"
|
||||
);
|
||||
Asserts.isEqual(
|
||||
document.querySelector("tr:nth-child(12) td:nth-child(2)").textContent,
|
||||
"100.00"
|
||||
);
|
||||
Asserts.isEqual(
|
||||
document.querySelector("tr:nth-child(13) td:nth-child(2)").textContent,
|
||||
"150.00"
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
content: "Click sort",
|
||||
trigger: "th .btn_sortable",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Sortable (desc)",
|
||||
trigger: "tr:nth-child(11) td:nth-child(2):contains('100.00')",
|
||||
run: () => {
|
||||
// Bank and Cash Accounts
|
||||
Asserts.isEqual(
|
||||
document.querySelector("tr:nth-child(5) td:nth-child(2)").textContent,
|
||||
"75.00"
|
||||
);
|
||||
Asserts.isEqual(
|
||||
document.querySelector("tr:nth-child(6) td:nth-child(2)").textContent,
|
||||
"75.00"
|
||||
);
|
||||
|
||||
// Receivables
|
||||
Asserts.isEqual(
|
||||
document.querySelector("tr:nth-child(8) td:nth-child(2)").textContent,
|
||||
"25.00"
|
||||
);
|
||||
Asserts.isEqual(
|
||||
document.querySelector("tr:nth-child(9) td:nth-child(2)").textContent,
|
||||
"25.00"
|
||||
);
|
||||
|
||||
// Current Assets
|
||||
Asserts.isEqual(
|
||||
document.querySelector("tr:nth-child(11) td:nth-child(2)").textContent,
|
||||
"100.00"
|
||||
);
|
||||
Asserts.isEqual(
|
||||
document.querySelector("tr:nth-child(12) td:nth-child(2)").textContent,
|
||||
"50.00"
|
||||
);
|
||||
Asserts.isEqual(
|
||||
document.querySelector("tr:nth-child(13) td:nth-child(2)").textContent,
|
||||
"150.00"
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
content: "Click sort",
|
||||
trigger: "th .btn_sortable",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Sortable (reset)",
|
||||
trigger: "tr:nth-child(5) td:nth-child(2):contains('75.00')",
|
||||
run: () => {
|
||||
// Bank and Cash Accounts
|
||||
Asserts.isEqual(
|
||||
document.querySelector("tr:nth-child(5) td:nth-child(2)").textContent,
|
||||
"75.00"
|
||||
);
|
||||
Asserts.isEqual(
|
||||
document.querySelector("tr:nth-child(6) td:nth-child(2)").textContent,
|
||||
"75.00"
|
||||
);
|
||||
|
||||
// Receivables
|
||||
Asserts.isEqual(
|
||||
document.querySelector("tr:nth-child(8) td:nth-child(2)").textContent,
|
||||
"25.00"
|
||||
);
|
||||
Asserts.isEqual(
|
||||
document.querySelector("tr:nth-child(9) td:nth-child(2)").textContent,
|
||||
"25.00"
|
||||
);
|
||||
|
||||
// Current Assets
|
||||
Asserts.isEqual(
|
||||
document.querySelector("tr:nth-child(11) td:nth-child(2)").textContent,
|
||||
"100.00"
|
||||
);
|
||||
Asserts.isEqual(
|
||||
document.querySelector("tr:nth-child(12) td:nth-child(2)").textContent,
|
||||
"50.00"
|
||||
);
|
||||
Asserts.isEqual(
|
||||
document.querySelector("tr:nth-child(13) td:nth-child(2)").textContent,
|
||||
"150.00"
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -0,0 +1,94 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { registry } from "@web/core/registry";
|
||||
|
||||
registry.category("web_tour.tours").add('account_reports_rounding_unit', {
|
||||
url: '/odoo/action-fusion_accounting.action_account_report_bs',
|
||||
steps: () => [
|
||||
{
|
||||
content: 'Test the value of `Receivables` line in decimals',
|
||||
trigger: '.line_name:contains("Receivables") + .line_cell:contains("1,150,000.00")',
|
||||
run: "click",
|
||||
},
|
||||
// Units
|
||||
{
|
||||
content: "Open amounts rounding dropdown",
|
||||
trigger: "#filter_rounding_unit button",
|
||||
run: 'click',
|
||||
},
|
||||
{
|
||||
content: "Select the units filter",
|
||||
trigger: ".dropdown-item:contains('In $')",
|
||||
run: 'click',
|
||||
},
|
||||
{
|
||||
trigger:
|
||||
'.line_name:contains("Receivables") + .line_cell:not(:contains("1,150,000.00"))',
|
||||
},
|
||||
{
|
||||
content: 'test the value of `Receivables` line in units',
|
||||
// We wait for the value to change.
|
||||
// We check the new value.
|
||||
trigger: '.line_name:contains("Receivables") + .line_cell:contains("1,150,000")',
|
||||
run: "click",
|
||||
},
|
||||
// Thousands
|
||||
{
|
||||
content: "Open amounts rounding dropdown",
|
||||
trigger: "#filter_rounding_unit button",
|
||||
run: 'click',
|
||||
},
|
||||
{
|
||||
content: "Select the thousands filter",
|
||||
trigger: ".dropdown-item:contains('In K$')",
|
||||
run: 'click',
|
||||
},
|
||||
{
|
||||
trigger: '.line_name:contains("Receivables") + .line_cell:not(:contains("1,150,000"))',
|
||||
},
|
||||
{
|
||||
content: 'test the value of `Receivables` line in thousands',
|
||||
// We wait for the value to change.
|
||||
// We check the new value.
|
||||
trigger: '.line_name:contains("Receivables") + .line_cell:contains("1,150")',
|
||||
run: "click",
|
||||
},
|
||||
// Millions
|
||||
{
|
||||
content: "Open amounts rounding dropdown",
|
||||
trigger: "#filter_rounding_unit button",
|
||||
run: 'click',
|
||||
},
|
||||
{
|
||||
content: "Select the millions filter",
|
||||
trigger: ".dropdown-item:contains('In M$')",
|
||||
run: 'click',
|
||||
},
|
||||
{
|
||||
trigger: '.line_name:contains("Receivables") + .line_cell:not(:contains("1,150"))',
|
||||
},
|
||||
{
|
||||
content: 'test the value of `Receivables` line in millions',
|
||||
// We wait for the value to change.
|
||||
// We check the new value.
|
||||
trigger: '.line_name:contains("Receivables") + .line_cell:contains("1")',
|
||||
run: "click",
|
||||
},
|
||||
// Decimals
|
||||
{
|
||||
content: "Open amounts rounding dropdown",
|
||||
trigger: "#filter_rounding_unit button",
|
||||
run: 'click',
|
||||
},
|
||||
{
|
||||
content: "Select the decimals filter",
|
||||
trigger: ".dropdown-item:contains('In .$')",
|
||||
run: 'click',
|
||||
},
|
||||
{
|
||||
content: 'test the value of `Receivables` line in millions',
|
||||
trigger: '.line_name:contains("Receivables") + .line_cell:contains("1,150,000.00")',
|
||||
run: () => null,
|
||||
},
|
||||
]
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { registry } from "@web/core/registry";
|
||||
|
||||
registry.category("web_tour.tours").add("account_reports_analytic_filters", {
|
||||
url: "/odoo/action-fusion_accounting.action_account_report_general_ledger",
|
||||
steps: () => [
|
||||
{
|
||||
content: "click analytic filters",
|
||||
trigger: ".filter_analytic button",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "insert text in the searchbar",
|
||||
trigger: ".o_multi_record_selector input",
|
||||
run: "edit Time",
|
||||
},
|
||||
{
|
||||
content: "click on the item",
|
||||
trigger: '.o-autocomplete--dropdown-item:contains("Time Off")',
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Check the label of the badge",
|
||||
trigger: '.dropdown-menu .o_tag_badge_text:contains("Time Off")',
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -0,0 +1,298 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { Asserts } from "./asserts";
|
||||
import { registry } from "@web/core/registry";
|
||||
|
||||
registry.category("web_tour.tours").add("account_reports_annotations", {
|
||||
url: "/odoo/action-fusion_accounting.action_account_report_bs",
|
||||
steps: () => [
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
// Annotations
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
// Test the initial status of annotations - There are 2 annotations to display
|
||||
{
|
||||
content: "Initial annotations",
|
||||
trigger: ".o_content",
|
||||
run: () => {
|
||||
Asserts.DOMContainsNone(".annotations");
|
||||
},
|
||||
},
|
||||
{
|
||||
content: "Unfold first line",
|
||||
trigger: "tr:nth-child(4) td:first()",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Unfold second line",
|
||||
trigger: "tr:nth-child(7) td:first()",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Unfold third line",
|
||||
trigger: "tr:nth-child(10) td:first()",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Extra Trigger step",
|
||||
trigger: "tr:nth-child(12):not(.d-none) .name:contains('101404')",
|
||||
},
|
||||
{
|
||||
content: "Check there are two lines annotated initially",
|
||||
trigger: ".o_content",
|
||||
run: () => {
|
||||
const annotations = document.querySelectorAll(".btn_annotation .fa-commenting");
|
||||
|
||||
// Check the number of annotated lines
|
||||
Asserts.isEqual(annotations.length, 2);
|
||||
|
||||
// Check the annotations buttons are on the right lines
|
||||
Asserts.isTrue(
|
||||
annotations[0] ===
|
||||
document.querySelector("tr:nth-child(5)").querySelector(".fa-commenting")
|
||||
);
|
||||
Asserts.isTrue(
|
||||
annotations[1] ===
|
||||
document.querySelector("tr:nth-child(12)").querySelector(".fa-commenting")
|
||||
);
|
||||
},
|
||||
},
|
||||
// Test that we can add a new annotation
|
||||
{
|
||||
content: "Click to show caret option",
|
||||
trigger: "tr:nth-child(8) .dropdown-toggle",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Caret option is displayed",
|
||||
trigger: "tr:nth-child(8)",
|
||||
run: () => {
|
||||
Asserts.hasClass("tr:nth-child(8) .o-dropdown", "show");
|
||||
},
|
||||
},
|
||||
{
|
||||
content: "Click on annotate",
|
||||
trigger: ".o-dropdown--menu .dropdown-item:last-of-type:contains('Annotate')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Add text to annotate",
|
||||
trigger: "textarea",
|
||||
run: "edit Annotation 121000",
|
||||
},
|
||||
{
|
||||
content: "Submit annotation by blurring",
|
||||
trigger: "textarea",
|
||||
run: function () {
|
||||
const annotation = this.anchor;
|
||||
annotation.dispatchEvent(new InputEvent("input"));
|
||||
annotation.dispatchEvent(new Event("change"));
|
||||
},
|
||||
},
|
||||
{
|
||||
content: "Wait for annotation created",
|
||||
trigger: "tr:nth-child(8) .btn_annotation .fa-commenting",
|
||||
},
|
||||
{
|
||||
content: "Close annotation",
|
||||
trigger: ".o_content",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Check there are now three lines annotated",
|
||||
trigger: ".o_content",
|
||||
run: () => {
|
||||
const annotations = document.querySelectorAll(".btn_annotation .fa-commenting");
|
||||
|
||||
// Check the number of annotated lines
|
||||
Asserts.isEqual(annotations.length, 3);
|
||||
|
||||
// Check the annotations buttons are on the right lines
|
||||
Asserts.isTrue(
|
||||
annotations[0] ===
|
||||
document.querySelector("tr:nth-child(5)").querySelector(".fa-commenting")
|
||||
);
|
||||
Asserts.isTrue(
|
||||
annotations[1] ===
|
||||
document.querySelector("tr:nth-child(8)").querySelector(".fa-commenting")
|
||||
);
|
||||
Asserts.isTrue(
|
||||
annotations[2] ===
|
||||
document.querySelector("tr:nth-child(12)").querySelector(".fa-commenting")
|
||||
);
|
||||
},
|
||||
},
|
||||
// Test that we can edit an annotation
|
||||
{
|
||||
content: "Open second annotated line annotation popover",
|
||||
trigger: "tr:nth-child(8) .btn_annotation",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Annotate contains previous text value",
|
||||
trigger: "textarea",
|
||||
run: () => {
|
||||
Asserts.isEqual(document.querySelector("textarea").value, "Annotation 121000");
|
||||
},
|
||||
},
|
||||
{
|
||||
content: "Add text to annotate",
|
||||
trigger: "textarea",
|
||||
run: "edit Annotation 121000 edited",
|
||||
},
|
||||
{
|
||||
content: "Annotation is edited",
|
||||
trigger: "tr:nth-child(8) .btn_annotation",
|
||||
run: () => {
|
||||
Asserts.isEqual(
|
||||
document.querySelector(".annotation_popover_autoresize_textarea").value,
|
||||
"Annotation 121000 edited"
|
||||
);
|
||||
},
|
||||
},
|
||||
// Test that we can delete an annotation by clicking the trash icon
|
||||
{
|
||||
content: "Click on trash can",
|
||||
trigger: ".btn_annotation_delete",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Check there are now only two lines annotated",
|
||||
trigger: "tr:nth-child(8):not(:has(.fa-commenting))",
|
||||
run: () => {
|
||||
const annotations = document.querySelectorAll(".btn_annotation .fa-commenting");
|
||||
|
||||
// Check the number of annotated lines
|
||||
Asserts.isEqual(annotations.length, 2);
|
||||
|
||||
// Check the annotations buttons are on the right lines
|
||||
Asserts.isTrue(
|
||||
annotations[0] ===
|
||||
document.querySelector("tr:nth-child(5)").querySelector(".fa-commenting")
|
||||
);
|
||||
Asserts.isTrue(
|
||||
annotations[1] ===
|
||||
document.querySelector("tr:nth-child(12)").querySelector(".fa-commenting")
|
||||
);
|
||||
},
|
||||
},
|
||||
// Test that we can add an annotation by clicking on the "New" button inside the popover
|
||||
{
|
||||
content: "Open an annotated line annotation popover",
|
||||
trigger: "tr:nth-child(12) .btn_annotation",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Click on the 'New' button",
|
||||
trigger: ".annotation_popover_line .oe_link",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Add text to annotate",
|
||||
trigger: "textarea:last()",
|
||||
run: "edit Annotation 101404 bis",
|
||||
},
|
||||
{
|
||||
content: "Submit annotation by blurring",
|
||||
trigger: "textarea:last()",
|
||||
run: function () {
|
||||
const annotation = this.anchor;
|
||||
annotation.dispatchEvent(new InputEvent("input"));
|
||||
annotation.dispatchEvent(new Event("change"));
|
||||
},
|
||||
},
|
||||
// Check the current state of the annotations
|
||||
{
|
||||
content: "Check there are two annotated lines to end the test",
|
||||
trigger: ".o_content",
|
||||
run: () => {
|
||||
const annotations = document.querySelectorAll(".btn_annotation .fa-commenting");
|
||||
|
||||
// Check there is only one annotated line
|
||||
Asserts.isEqual(annotations.length, 2);
|
||||
|
||||
// Check the annotation buttons are on the right lines
|
||||
Asserts.isTrue(
|
||||
annotations[0] ===
|
||||
document.querySelector("tr:nth-child(5)").querySelector(".fa-commenting")
|
||||
);
|
||||
Asserts.isTrue(
|
||||
annotations[1] ===
|
||||
document.querySelector("tr:nth-child(12)").querySelector(".fa-commenting")
|
||||
);
|
||||
},
|
||||
},
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
// Annotations dates
|
||||
//--------------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
content:
|
||||
"Remove first annotation to only have one annotation on line 12 (required setup step)",
|
||||
trigger: ".annotation_popover tr:nth-child(2) .btn_annotation_delete",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Verify that we still have one element",
|
||||
trigger: ".annotation_popover tr:nth-child(3):contains('Add a line')",
|
||||
},
|
||||
{
|
||||
content: "Modify the date of an annotation to a further period",
|
||||
trigger: ".annotation_popover tr:nth-child(2) input",
|
||||
run: "edit 01/01/2100",
|
||||
},
|
||||
{
|
||||
content: "Modify the date of an annotation to a further period",
|
||||
trigger: ".annotation_popover tr:nth-child(2) input",
|
||||
run: function () {
|
||||
// Since the t-on-change of the input is not triggered by the run: "edit" action,
|
||||
// we need to dispatch the event manually requiring a function.
|
||||
const input = this.anchor;
|
||||
input.dispatchEvent(new InputEvent("input"));
|
||||
input.dispatchEvent(new Event("change", { bubbles: true }));
|
||||
},
|
||||
},
|
||||
{
|
||||
content: "Check that there is no annotation anymore on line 12",
|
||||
trigger: "tr:nth-child(12):not(:has(.fa-commenting))",
|
||||
},
|
||||
{
|
||||
content: "change date filter",
|
||||
trigger: "#filter_date button",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Open specific date button",
|
||||
trigger: ".dropdown-menu div.dropdown-item",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Go to 15 January 2100",
|
||||
trigger: ".o_datetime_input",
|
||||
run: "edit 01/15/2100",
|
||||
},
|
||||
{
|
||||
content: "Apply filter by closing the dropdown",
|
||||
trigger: "#filter_date .btn:first()",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "wait refresh",
|
||||
trigger: `#filter_date button:not(:contains(${new Date().getFullYear()}))`,
|
||||
},
|
||||
{
|
||||
content: "Check there is one annotation on line 12",
|
||||
trigger: "tr:nth-child(12):has(.fa-commenting)",
|
||||
run: () => {
|
||||
const annotations = document.querySelectorAll(".btn_annotation .fa-commenting");
|
||||
|
||||
// Check there is only one annotated line
|
||||
Asserts.isEqual(annotations.length, 1);
|
||||
|
||||
// Check the annotation buttons are on the right lines
|
||||
Asserts.isTrue(
|
||||
annotations[0] ===
|
||||
document.querySelector("tr:nth-child(12)").querySelector(".fa-commenting")
|
||||
);
|
||||
}
|
||||
},
|
||||
]
|
||||
});
|
||||
@@ -0,0 +1,107 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { registry } from "@web/core/registry";
|
||||
|
||||
registry.category("web_tour.tours").add('account_reports_hide_0_lines', {
|
||||
url: '/odoo/action-fusion_accounting.action_account_report_bs',
|
||||
steps: () => [
|
||||
{
|
||||
content: 'test if the Bank and Cash line is present (but the value is 0)',
|
||||
trigger: '.line_name:contains("Bank and Cash Accounts")',
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: 'test if the Current Year Unallocated Earnings line is present (but the value is 0)',
|
||||
trigger: '.line_name:contains("Current Year Unallocated Earnings")',
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: 'test if the Unallocated Earnings line is present (but value is different from 0 and so should be there after the hide_0_lines',
|
||||
trigger: '.line_name:contains("Unallocated Earnings")',
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Open options selector",
|
||||
trigger: "#filter_extra_options button",
|
||||
run: 'click',
|
||||
},
|
||||
{
|
||||
content: "Select the hide line at 0 option",
|
||||
trigger: ".dropdown-item:contains('Hide lines at 0')",
|
||||
run: 'click',
|
||||
},
|
||||
{
|
||||
content: 'test if the Unallocated Earnings line is still present',
|
||||
trigger: '.line_name:contains("Unallocated Earnings")',
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: 'test if the Bank and Cash line is not present',
|
||||
trigger: '.line_name:not(:contains("Bank and Cash Accounts"))',
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: 'test if the Current Year Unallocated Earnings line is not present',
|
||||
trigger: '.line_name:not(:contains("Current Year Unallocated Earnings"))',
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Click again to open the options selector",
|
||||
trigger: "#filter_extra_options button",
|
||||
run: 'click',
|
||||
},
|
||||
{
|
||||
content: "Select the hide lines at 0 option again",
|
||||
trigger: ".dropdown-item:contains('Hide lines at 0')",
|
||||
run: 'click',
|
||||
},
|
||||
{
|
||||
content: 'test again if the Bank and Cash line is present (but the value is 0)',
|
||||
trigger: '.line_name:contains("Bank and Cash Accounts")',
|
||||
run: () => null,
|
||||
},
|
||||
]
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add('account_reports_hide_0_lines_with_string_columns', {
|
||||
url: '/odoo/action-fusion_accounting.action_account_report_general_ledger',
|
||||
steps: () => [
|
||||
{
|
||||
content: "Check if the 211000 Account Payable line is present (but the value is 0)",
|
||||
trigger: ".name:contains('211000 Account Payable')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Check if the MISC item line is present with string values set up, but all amounts are at 0",
|
||||
trigger: ".name:contains('Coucou les biloutes')",
|
||||
},
|
||||
{
|
||||
content: "Open options selector",
|
||||
trigger: "#filter_extra_options button",
|
||||
run: 'click',
|
||||
},
|
||||
{
|
||||
content: "Select the hide line at 0 option",
|
||||
trigger: ".dropdown-item:contains('Hide lines at 0')",
|
||||
run: 'click',
|
||||
},
|
||||
{
|
||||
content: "Check if the MISC item line is hidden",
|
||||
trigger: ":not(:visible):contains('Coucou les biloutes')",
|
||||
},
|
||||
{
|
||||
content: "Click again to open the options selector",
|
||||
trigger: "#filter_extra_options button",
|
||||
run: 'click',
|
||||
},
|
||||
{
|
||||
content: "Select the hide lines at 0 option again",
|
||||
trigger: ".dropdown-item:contains('Hide lines at 0')",
|
||||
run: 'click',
|
||||
},
|
||||
{
|
||||
content: "Check again if the MISC item line is present (but the value is 0)",
|
||||
trigger: ".name:contains('Coucou les biloutes')",
|
||||
},
|
||||
]
|
||||
});
|
||||
@@ -0,0 +1,43 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { registry } from "@web/core/registry";
|
||||
|
||||
registry.category("web_tour.tours").add('account_reports_search', {
|
||||
url: '/odoo/action-fusion_accounting.action_account_report_general_ledger',
|
||||
steps: () => [
|
||||
{
|
||||
content: "click search",
|
||||
trigger: '.o_searchview_input',
|
||||
run: 'click',
|
||||
},
|
||||
{
|
||||
content: 'insert text in the searchbar',
|
||||
trigger: '.o_searchview_input',
|
||||
run: "edit 40",
|
||||
},
|
||||
{
|
||||
content: 'test if the product sale line is present',
|
||||
trigger: '.line_name:contains("400000 Product Sales")',
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "click search",
|
||||
trigger: '.o_searchview_input',
|
||||
run: 'click',
|
||||
},
|
||||
{
|
||||
content: 'insert text in the search bar',
|
||||
trigger: '.o_searchview_input',
|
||||
run: "edit Account",
|
||||
},
|
||||
{
|
||||
content: 'test if the receivable line is present',
|
||||
trigger: '.line_name:contains("121000 Account Receivable")',
|
||||
run: 'click',
|
||||
},
|
||||
{
|
||||
content: 'check that the product sale line is not present',
|
||||
trigger: '.line_name:not(:contains("400000 Product Sales"))',
|
||||
},
|
||||
]
|
||||
});
|
||||
129
Fusion Accounting/static/tests/tours/account_reports_sections.js
Normal file
129
Fusion Accounting/static/tests/tours/account_reports_sections.js
Normal file
@@ -0,0 +1,129 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
const { DateTime } = luxon;
|
||||
|
||||
import { Asserts } from "./asserts";
|
||||
import { registry } from "@web/core/registry";
|
||||
|
||||
registry.category("web_tour.tours").add('account_reports_sections', {
|
||||
url: "/odoo/action-fusion_accounting.action_account_report_gt",
|
||||
steps: () => [
|
||||
{
|
||||
content: "Open variant selector",
|
||||
trigger: "#filter_variant button",
|
||||
run: 'click',
|
||||
},
|
||||
{
|
||||
content: "Select the test variant using sections",
|
||||
trigger: ".dropdown-item:contains('Test Sections')",
|
||||
run: 'click',
|
||||
},
|
||||
{
|
||||
content: "Check the lines of section 1 are displayed",
|
||||
trigger: ".line_name:contains('Section 1 line')",
|
||||
},
|
||||
{
|
||||
content: "Check the columns of section 1 are displayed",
|
||||
trigger: "#table_header th:last():contains('Column 1')",
|
||||
},
|
||||
{
|
||||
content: "Check the export buttons belong to the composite report",
|
||||
trigger: ".btn:contains('composite_report_custom_button')",
|
||||
},
|
||||
{
|
||||
content: "Check the filters displayed belong to section 1 (journals filter is not enabled on section 2, nor the composite report)",
|
||||
trigger: "#filter_journal",
|
||||
},
|
||||
{
|
||||
content: "Check the date chosen by default",
|
||||
trigger: "#filter_date",
|
||||
run: (actionHelper) => {
|
||||
// Generic tax report opens on the previous period and in this case the period is one month.
|
||||
// And since we are using the generic tax report, we need to go back one month.
|
||||
const previousMonth = DateTime.now().minus({months: 1});
|
||||
|
||||
Asserts.isTrue(actionHelper.anchor.getElementsByTagName('button')[0].innerText.includes(previousMonth.year));
|
||||
},
|
||||
},
|
||||
{
|
||||
content: "Switch to section 2",
|
||||
trigger: "#section_selector .btn:contains('Section 2')",
|
||||
run: 'click',
|
||||
},
|
||||
{
|
||||
content: "Check the lines of section 2 are displayed",
|
||||
trigger: ".line_name:contains('Section 2 line')",
|
||||
},
|
||||
{
|
||||
content: "Check the columns of section 2 are displayed",
|
||||
trigger: "#table_header th:last():contains('Column 2')",
|
||||
},
|
||||
{
|
||||
content: "Check the export buttons belong to the composite report",
|
||||
trigger: ".btn:contains('composite_report_custom_button')",
|
||||
},
|
||||
{
|
||||
content: "Check the filters displayed belong to section 2 (comparison filter is not enabled on section 1, nor the composite report)",
|
||||
trigger: "#filter_comparison",
|
||||
},
|
||||
{
|
||||
content: "Open date switcher",
|
||||
trigger: "#filter_date button",
|
||||
run: 'click',
|
||||
},
|
||||
{
|
||||
content: "Select another date in the future",
|
||||
trigger: ".dropdown-menu span.dropdown-item:nth-child(3) .btn_next_date",
|
||||
run: 'click'
|
||||
},
|
||||
{
|
||||
content: "Apply filter by closing the dropdown for the future date",
|
||||
trigger: "#filter_date .btn:first()",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Check that the date has changed",
|
||||
trigger: `#filter_date button:not(:contains(${ DateTime.now().minus({months: 1}).year }))`, // We need to remove one month for the case where we are in january. It will impact the year.
|
||||
run: (actionHelper) => {
|
||||
const nextYear = DateTime.now().plus({years: 1}).year;
|
||||
|
||||
Asserts.isTrue(actionHelper.anchor.innerText.includes(nextYear));
|
||||
},
|
||||
},
|
||||
{
|
||||
content: "Open date switcher",
|
||||
trigger: "#filter_date button",
|
||||
run: 'click',
|
||||
},
|
||||
{
|
||||
content: "Select another date first time",
|
||||
trigger: ".dropdown-menu span.dropdown-item:nth-child(3) .btn_previous_date",
|
||||
run: 'click'
|
||||
},
|
||||
{
|
||||
trigger: `.dropdown-menu span.dropdown-item:nth-child(3) time:contains(${ DateTime.now().year})`,
|
||||
},
|
||||
{
|
||||
content: "Select another date second time",
|
||||
trigger: ".dropdown-menu span.dropdown-item:nth-child(3) .btn_previous_date",
|
||||
run: 'click'
|
||||
},
|
||||
{
|
||||
trigger: `.dropdown-menu span.dropdown-item:nth-child(3) time:contains(${ DateTime.now().minus({years: 1}).year })`,
|
||||
},
|
||||
{
|
||||
content: "Apply filter by closing the dropdown",
|
||||
trigger: "#filter_date .btn:first()",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Check that the date has changed",
|
||||
trigger: `#filter_date button:contains(${ DateTime.now().minus({years: 1}).year })`,
|
||||
},
|
||||
{
|
||||
content: "Switch back to section 1",
|
||||
trigger: "#section_selector .btn:contains('Section 1')",
|
||||
run: 'click',
|
||||
},
|
||||
]
|
||||
});
|
||||
@@ -0,0 +1,82 @@
|
||||
import { registry } from "@web/core/registry";
|
||||
|
||||
registry.category("web_tour.tours").add("account_reports_widgets", {
|
||||
url: "/odoo/action-fusion_accounting.action_account_report_pl",
|
||||
steps: () => [
|
||||
{
|
||||
content: "change date filter",
|
||||
trigger: "#filter_date button",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Select another date in the future",
|
||||
trigger: ".dropdown-menu span.dropdown-item:nth-child(3) .btn_next_date",
|
||||
run: 'click'
|
||||
},
|
||||
{
|
||||
content: "Apply filter by closing the dropdown",
|
||||
trigger: "#filter_date .btn:first()",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "wait refresh",
|
||||
trigger: `#filter_date button:not(:contains(${ new Date().getFullYear() }))`,
|
||||
},
|
||||
{
|
||||
content: "change date filter for the second time",
|
||||
trigger: "#filter_date button",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Select another date in the past first time",
|
||||
trigger: ".dropdown-menu span.dropdown-item:nth-child(3) .btn_previous_date",
|
||||
run: 'click'
|
||||
},
|
||||
{
|
||||
trigger: `.dropdown-menu span.dropdown-item:nth-child(3) time:contains(${new Date().getFullYear()})`,
|
||||
},
|
||||
{
|
||||
content: "Select another date in the past second time",
|
||||
trigger: ".dropdown-menu span.dropdown-item:nth-child(3) .btn_previous_date",
|
||||
run: 'click'
|
||||
},
|
||||
{
|
||||
trigger: `.dropdown-menu span.dropdown-item:nth-child(3) time:contains(${
|
||||
new Date().getFullYear() - 1
|
||||
})`,
|
||||
},
|
||||
{
|
||||
content: "Apply filter by closing the dropdown",
|
||||
trigger: "#filter_date .btn:first()",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "wait refresh",
|
||||
trigger: `#filter_date button:contains(${ new Date().getFullYear() - 1 })`,
|
||||
},
|
||||
{
|
||||
content: "change comparison filter",
|
||||
trigger: "#filter_comparison .btn:first()",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "change comparison filter",
|
||||
trigger: ".dropdown-item.period:first()",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Apply filter by closing the dropdown",
|
||||
trigger: "#filter_comparison .btn:first()",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "wait refresh, report should have 4 columns",
|
||||
trigger: "th + th + th + th",
|
||||
},
|
||||
{
|
||||
content: "export xlsx",
|
||||
trigger: "button:contains('XLSX')",
|
||||
run: "click",
|
||||
},
|
||||
],
|
||||
});
|
||||
10
Fusion Accounting/static/tests/tours/account_tours.js
Normal file
10
Fusion Accounting/static/tests/tours/account_tours.js
Normal file
@@ -0,0 +1,10 @@
|
||||
/** @odoo-module **/
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
import { accountTourSteps } from "@account/js/tours/account";
|
||||
import { stepUtils } from "@web_tour/tour_service/tour_utils";
|
||||
|
||||
patch(accountTourSteps, {
|
||||
goToAccountMenu(description="Open Accounting Menu") {
|
||||
return stepUtils.goToAppSteps('fusion_accounting.menu_accounting', description);
|
||||
}
|
||||
});
|
||||
115
Fusion Accounting/static/tests/tours/asserts.js
Normal file
115
Fusion Accounting/static/tests/tours/asserts.js
Normal file
@@ -0,0 +1,115 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// This class provides some helpers function to do assertions on tours
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
export class Asserts {
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
// Gets the number of 'selector' element inside 'target' element
|
||||
static getCount(target, selector) {
|
||||
return document.querySelector(target).querySelectorAll(selector).length;
|
||||
}
|
||||
// Gets the number of 'selector' element inside DOM
|
||||
static getDOMCount(selector) {
|
||||
return document.querySelectorAll(selector).length;
|
||||
}
|
||||
static check(condition, success, error) {
|
||||
condition ? Asserts.success(success) : Asserts.error(error);
|
||||
}
|
||||
static success(message) {
|
||||
return console.info(`SUCCESS: ${message}`);
|
||||
}
|
||||
static error(message) {
|
||||
throw new Error(`FAIL: ${message}`);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
// Asserts
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
static isTrue(actual) {
|
||||
Asserts.check(actual, `${actual} is true`, `${actual} is not true`);
|
||||
}
|
||||
static isFalse(actual) {
|
||||
Asserts.check(!actual, `${actual} is false`, `${actual} is not false`);
|
||||
}
|
||||
// Assert that 'actual' and 'expected' are equal
|
||||
static isEqual(actual, expected) {
|
||||
Asserts.check(
|
||||
(actual == expected),
|
||||
`${actual} is equal to expected ${expected}`,
|
||||
`${actual} is not equal to expected ${expected}`
|
||||
);
|
||||
}
|
||||
// Asserts that 'actual' and 'expected' are strictly equal
|
||||
static isStrictEqual(actual, expected) {
|
||||
Asserts.check(
|
||||
(actual === expected),
|
||||
`${actual} is strictly equal to expected ${expected}`,
|
||||
`${actual} is not strictly equal to expected ${expected}`
|
||||
);
|
||||
}
|
||||
// Assert that 'target' element contains at least one 'selector' element
|
||||
static contains(target, selector) {
|
||||
const count = Asserts.getCount(target, selector);
|
||||
Asserts.check(
|
||||
(count > 0),
|
||||
`There is at least one ${selector} in ${target}`,
|
||||
`There should be at least one ${selector} in ${target} but there is ${count}`
|
||||
);
|
||||
}
|
||||
// Asserts there is no 'selector' element in 'target' element
|
||||
static containsNone(target, selector) {
|
||||
const count = Asserts.getCount(target, selector);
|
||||
Asserts.check(
|
||||
(count === 0),
|
||||
`There is no ${selector} in ${target}`,
|
||||
`There should be no ${selector} in ${target} but there is ${count}`
|
||||
);
|
||||
}
|
||||
// Asserts that 'target' element contains 'number' of 'selector' elements
|
||||
static containsNumber(target, selector, number) {
|
||||
const count = Asserts.getCount(target, selector);
|
||||
Asserts.check(
|
||||
(count === number),
|
||||
`There is the correct number (${number}) of ${selector} in ${target}`,
|
||||
`There should be at ${number} ${selector} in ${target} but there is ${count}`
|
||||
);
|
||||
}
|
||||
// Asserts that DOM contains at least one 'selector' element
|
||||
static DOMContains(selector) {
|
||||
const count = Asserts.getDOMCount(selector);
|
||||
Asserts.check(
|
||||
(count > 0),
|
||||
`There is at least one ${selector} in the DOM`,
|
||||
`There should be at least one ${selector} in the DOM but there is ${count}`
|
||||
);
|
||||
}
|
||||
// Asserts there is no 'selector' element in the DOM
|
||||
static DOMContainsNone(selector) {
|
||||
const count = Asserts.getDOMCount(selector);
|
||||
Asserts.check(
|
||||
(count === 0),
|
||||
`There is no ${selector} in the DOM`,
|
||||
`There should be 0 ${selector} in the DOM but there is ${count}`
|
||||
);
|
||||
}
|
||||
// Asserts that DOM contains 'number' of 'selector' element
|
||||
static DOMContainsNumber(selector, number) {
|
||||
const count = Asserts.getDOMCount(selector);
|
||||
Asserts.check(
|
||||
(Asserts.getDOMCount(selector) === number),
|
||||
`There is the correct number (${number}) of ${selector} in the DOM`,
|
||||
`There should be ${number} ${selector} in the DOM but there is ${count}`
|
||||
);
|
||||
}
|
||||
// Asserts that 'selector' element has class 'classname'
|
||||
static hasClass(selector, classname) {
|
||||
Asserts.check(
|
||||
document.querySelector(selector).classList.contains(classname),
|
||||
`${selector} has class ${classname}`,
|
||||
`${selector} should have class ${classname} but hasn't`
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { registry } from "@web/core/registry";
|
||||
import { stepUtils } from "@web_tour/tour_service/tour_utils";
|
||||
import { accountTourSteps } from "@account/js/tours/account";
|
||||
|
||||
registry.category("web_tour.tours").add("fusion_accounting_bank_rec_widget_rainbowman_reset", {
|
||||
url: "/odoo",
|
||||
steps: () => [
|
||||
stepUtils.showAppsMenuItem(),
|
||||
...accountTourSteps.goToAccountMenu("Open the accounting module"),
|
||||
|
||||
// Open the widget. The first line should be selected by default.
|
||||
{
|
||||
trigger: ".o_breadcrumb",
|
||||
},
|
||||
{
|
||||
content: "Open the bank reconciliation widget",
|
||||
trigger: "button.btn-secondary[name='action_open_reconcile']",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: "div[name='line_ids'] td[field='name']:contains('line1')",
|
||||
},
|
||||
{
|
||||
content: "'line1' should be selected and form mounted",
|
||||
trigger: ".o_bank_rec_selected_st_line:contains('line1')",
|
||||
},
|
||||
// Rainbowman gets reset
|
||||
{
|
||||
content: "Mount invoice 2 for line 1",
|
||||
trigger:
|
||||
"div.bank_rec_widget_form_amls_list_anchor table.o_list_table td[name='move_id']:contains('INV/2019/00002')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger:
|
||||
"div.bank_rec_widget_form_amls_list_anchor table.o_list_table tr.o_rec_widget_list_selected_item td[name='move_id']:contains('INV/2019/00002')",
|
||||
},
|
||||
{
|
||||
content: "Validate line1",
|
||||
trigger: "button:contains('Validate')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o_bank_rec_selected_st_line:contains('line2')",
|
||||
},
|
||||
{
|
||||
content: "No records brings rainbows",
|
||||
trigger: "div.o_kanban_view .o_searchview_input",
|
||||
run: "fill thisShouldNotReturnAnyRecords",
|
||||
},
|
||||
{
|
||||
content: "Select the Journal Entry search option from the dropdown",
|
||||
trigger: ".o_searchview_autocomplete li:contains(Journal Entry)",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o_reward_rainbow_man:contains('You reconciled 1 transaction in')",
|
||||
},
|
||||
{
|
||||
content: "Remove the filter while rainbow man is on screen",
|
||||
trigger: ".o_kanban_view .o_searchview_facet:nth-child(3) .o_facet_remove",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o_bank_rec_st_line:contains('line2')",
|
||||
},
|
||||
{
|
||||
content: "Search for no results again",
|
||||
trigger: "div.o_kanban_view .o_searchview_input",
|
||||
run: "fill thisShouldNotReturnAnyRecords",
|
||||
},
|
||||
{
|
||||
content: "Select the Journal Entry search option from the dropdown",
|
||||
trigger: ".o_searchview_autocomplete li:contains(Journal Entry)",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "No content helper is displayed instead of rainbowman",
|
||||
trigger: ".o_view_nocontent_smiling_face",
|
||||
},
|
||||
// End
|
||||
...stepUtils.toggleHomeMenu(),
|
||||
...accountTourSteps.goToAccountMenu("Reset back to accounting module"),
|
||||
{
|
||||
content: "check that we're back on the dashboard",
|
||||
trigger: 'a:contains("Customer Invoices")',
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -0,0 +1,95 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { registry } from "@web/core/registry";
|
||||
import { stepUtils } from "@web_tour/tour_service/tour_utils";
|
||||
import { accountTourSteps } from "@account/js/tours/account";
|
||||
|
||||
registry.category("web_tour.tours").add('fusion_accounting_bank_rec_widget_statements',
|
||||
{
|
||||
url: '/odoo',
|
||||
steps: () => [
|
||||
stepUtils.showAppsMenuItem(),
|
||||
...accountTourSteps.goToAccountMenu("Open the accounting module"),
|
||||
{
|
||||
trigger: ".o_breadcrumb",
|
||||
},
|
||||
{
|
||||
content: "Open the bank reconciliation widget",
|
||||
trigger: "button.btn-secondary[name='action_open_reconcile']",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Statement button",
|
||||
trigger:
|
||||
".o_bank_rec_st_line:eq(2) a.oe_kanban_action:contains('Statement'):not(:visible)",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".modal-dialog:contains('Create Statement')",
|
||||
},
|
||||
{
|
||||
content: "Save the statement with proposed values",
|
||||
trigger: ".o_form_button_save",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Click the Valid Statement with $ 1,000.00 that is visible in Kanban",
|
||||
trigger: "span[name='kanban-subline-clickable-amount']:contains('$ 1,000.00')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Modify the end balance",
|
||||
trigger: "input[id='balance_end_real_0']",
|
||||
run: "edit 100 && click body",
|
||||
},
|
||||
{
|
||||
trigger: ".alert-warning:contains('The running balance')",
|
||||
},
|
||||
{
|
||||
content: "Dialog displays warning, save anyway",
|
||||
trigger: ".breadcrumb-item.o_back_button:nth-of-type(2)",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".btn-link:contains('$ 2,100.00')",
|
||||
},
|
||||
{
|
||||
content: "Click the red statement, after checking the balance",
|
||||
trigger: "span[name='kanban-subline-clickable-amount']:contains('$ 100.00')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Back in the form view",
|
||||
trigger: ".alert-warning:contains('The running balance')",
|
||||
},
|
||||
{
|
||||
content: "Click on Action",
|
||||
trigger: ".o_cp_action_menus button",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Click on Delete",
|
||||
trigger: ".o-dropdown--menu span:contains('Delete')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Confirm Deletion",
|
||||
trigger: ".btn-primary:contains('Delete')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o_kanban_renderer:not(:has(.kanban-statement))",
|
||||
},
|
||||
{
|
||||
content: "balance displays $3000.00 and no statement",
|
||||
trigger: ".btn-link:contains('$ 3,000')",
|
||||
},
|
||||
// End
|
||||
...stepUtils.toggleHomeMenu(),
|
||||
...accountTourSteps.goToAccountMenu("Reset back to accounting module"),
|
||||
{
|
||||
content: "check that we're back on the dashboard",
|
||||
trigger: 'a:contains("Customer Invoices")',
|
||||
}
|
||||
]
|
||||
});
|
||||
983
Fusion Accounting/static/tests/tours/test_tour_bank_rec_ui.js
Normal file
983
Fusion Accounting/static/tests/tours/test_tour_bank_rec_ui.js
Normal file
@@ -0,0 +1,983 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { registry } from "@web/core/registry";
|
||||
import { stepUtils } from "@web_tour/tour_service/tour_utils";
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
import { accountTourSteps } from "@account/js/tours/account";
|
||||
|
||||
patch(accountTourSteps, {
|
||||
bankRecUiReportSteps() {
|
||||
return [
|
||||
{
|
||||
trigger: ".o_bank_rec_selected_st_line:contains('line1')",
|
||||
},
|
||||
{
|
||||
content: "balance is 2100",
|
||||
trigger: ".btn-link:contains('$ 2,100.00')",
|
||||
},
|
||||
];
|
||||
},
|
||||
});
|
||||
patch(accountTourSteps, {
|
||||
bankRecUiReportSteps() {
|
||||
return [
|
||||
{
|
||||
trigger: ".o_bank_rec_selected_st_line:contains('line1')",
|
||||
},
|
||||
{
|
||||
content: "balance is 2100",
|
||||
trigger: ".btn-link:contains('$ 2,100.00')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: "span:contains('General Ledger')",
|
||||
},
|
||||
{
|
||||
content: "Breadcrumb back to Bank Reconciliation from the report",
|
||||
trigger: ".breadcrumb-item a:contains('Bank Reconciliation')",
|
||||
run: "click",
|
||||
},
|
||||
];
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
registry.category("web_tour.tours").add("fusion_accounting_bank_rec_widget_ui", {
|
||||
url: "/odoo",
|
||||
steps: () => [
|
||||
stepUtils.showAppsMenuItem(),
|
||||
...accountTourSteps.goToAccountMenu("Open the accounting module"),
|
||||
|
||||
// Open the widget. The first line should be selected by default.
|
||||
{
|
||||
trigger: ".o_breadcrumb",
|
||||
},
|
||||
{
|
||||
content: "Open the bank reconciliation widget",
|
||||
trigger: "button.btn-secondary[name='action_open_reconcile']",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: "div[name='line_ids'] td[field='name']:contains('line1')",
|
||||
},
|
||||
{
|
||||
content: "'line1' should be selected and form mounted",
|
||||
trigger: ".o_bank_rec_selected_st_line:contains('line1')",
|
||||
},
|
||||
// Select line2. It should remain selected when returning using the breadcrumbs.
|
||||
{
|
||||
trigger: ".o_bank_rec_st_line:contains('line3')",
|
||||
},
|
||||
{
|
||||
content: "select 'line2'",
|
||||
trigger: ".o_bank_rec_st_line:contains('line2')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "'line2' should be selected",
|
||||
trigger: ".o_bank_rec_selected_st_line:contains('line2')",
|
||||
},
|
||||
{
|
||||
content: "View an invoice",
|
||||
trigger: "button.btn-secondary[name='action_open_business_doc']:eq(1)",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o_breadcrumb .active:contains('INV/2019/00001')",
|
||||
},
|
||||
{
|
||||
content: "Breadcrumb back to Bank Reconciliation from INV/2019/00001",
|
||||
trigger: ".breadcrumb-item:contains('Bank Reconciliation')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o_bank_rec_st_line:contains('line1')",
|
||||
},
|
||||
{
|
||||
content: "'line2' should be selected after returning",
|
||||
trigger: ".o_bank_rec_selected_st_line:contains('line2')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: "div[name='line_ids'] td[field='name']:contains('line2')",
|
||||
},
|
||||
{
|
||||
content: "'line2' form mounted",
|
||||
trigger: ".o_bank_rec_selected_st_line:contains('line2')",
|
||||
run: "click",
|
||||
},
|
||||
// Keep AML search, and prepared entry (line_ids) when changing tabs, using breadcrumbs, and view switcher
|
||||
{
|
||||
trigger:
|
||||
"div.bank_rec_widget_form_amls_list_anchor table.o_list_table tr:nth-child(2) td[name='move_id']:contains('INV/2019/00001')",
|
||||
},
|
||||
{
|
||||
content: "AMLs list has both invoices",
|
||||
trigger:
|
||||
"div.bank_rec_widget_form_amls_list_anchor table.o_list_table tr:nth-child(1) td[name='move_id']:contains('INV/2019/00002')",
|
||||
},
|
||||
{
|
||||
trigger: "a.active[name='amls_tab']",
|
||||
},
|
||||
{
|
||||
content: "Search for INV/2019/00001",
|
||||
trigger: "div.bank_rec_widget_form_amls_list_anchor .o_searchview_input",
|
||||
run: "edit INV/2019/00001",
|
||||
},
|
||||
{
|
||||
content: "Select the Journal Entry search option from the dropdown",
|
||||
trigger: ".o_searchview_autocomplete li:contains(Journal Entry)",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "AMLs list only displays one invoice",
|
||||
trigger:
|
||||
"div.bank_rec_widget_form_amls_list_anchor table.o_list_table tr:nth-child(1) td[name='move_id']:contains('INV/2019/00001')",
|
||||
},
|
||||
{
|
||||
content: "Liquidity line displays debit '$ 1,000.00'",
|
||||
trigger:
|
||||
"div[name='line_ids'] table.o_list_table tr.o_bank_rec_liquidity_line td[field='debit']:contains('$ 1,000.00')",
|
||||
},
|
||||
{
|
||||
content: "Select the liquidity line",
|
||||
trigger: "tr.o_bank_rec_liquidity_line td[field='debit']",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Modify the liquidity line amount",
|
||||
trigger: "div[name='amount_currency'] input",
|
||||
run: "edit 100.00 && click body",
|
||||
},
|
||||
{
|
||||
content: "Liquidity line displays debit '$ 100.00'",
|
||||
trigger:
|
||||
"div[name='line_ids'] table.o_list_table tr.o_bank_rec_liquidity_line td[field='debit']:contains('$ 100.00')",
|
||||
},
|
||||
{
|
||||
trigger: "div[name='partner_id'] input",
|
||||
},
|
||||
{
|
||||
content: "Select 'amls_tab'",
|
||||
trigger: "a[name='amls_tab']",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger:
|
||||
"div.bank_rec_widget_form_amls_list_anchor .o_searchview_facet:nth-child(1) .o_facet_value:contains('INV/2019/00001')",
|
||||
},
|
||||
{
|
||||
content: "AMLs list contains the search facet, and one invoice - select it",
|
||||
trigger:
|
||||
"div.bank_rec_widget_form_amls_list_anchor table.o_list_table tr:nth-child(1) td[name='move_id']:contains('INV/2019/00001')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger:
|
||||
"div.bank_rec_widget_form_amls_list_anchor table.o_list_table tr.o_rec_widget_list_selected_item td[name='move_id']:contains('INV/2019/00001')",
|
||||
},
|
||||
{
|
||||
content: "Check INV/2019/00001 is well marked as selected",
|
||||
trigger:
|
||||
"div.bank_rec_widget_form_amls_list_anchor table.o_list_table tr.o_rec_widget_list_selected_item td[name='move_id']:contains('INV/2019/00001')",
|
||||
},
|
||||
{
|
||||
content: "View an invoice",
|
||||
trigger: "button.btn-secondary[name='action_open_business_doc']:nth-child(1)",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o_breadcrumb .active:contains('INV/2019/00001')",
|
||||
},
|
||||
{
|
||||
content: "Breadcrumb back to Bank Reconciliation from INV/2019/00001",
|
||||
trigger: ".breadcrumb-item:contains('Bank Reconciliation')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger:
|
||||
"div.bank_rec_widget_form_amls_list_anchor .o_searchview_facet:nth-child(1) .o_facet_value:contains('INV/2019/00001')",
|
||||
},
|
||||
{
|
||||
content: "Check INV/2019/00001 is selected and still contains the search facet",
|
||||
trigger:
|
||||
"div.bank_rec_widget_form_amls_list_anchor table.o_list_table tr.o_rec_widget_list_selected_item td[name='move_id']:contains('INV/2019/00001')",
|
||||
},
|
||||
// Search should remove some lines, select the first unmatched record, and persist when returning with breadcrumbs
|
||||
{
|
||||
trigger: "a.active[name='amls_tab']",
|
||||
},
|
||||
{
|
||||
content: "Search for line2",
|
||||
trigger: "div.o_kanban_view .o_searchview_input",
|
||||
run: "fill line2",
|
||||
},
|
||||
{
|
||||
content: "Select the Transaction search option from the dropdown",
|
||||
trigger: ".o_searchview_autocomplete li:contains(Transaction)",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: "div[name='line_ids'] td[field='name']:contains('line2')",
|
||||
},
|
||||
{
|
||||
content: "'line2' should be selected",
|
||||
trigger: ".o_bank_rec_st_line:last():contains('line2')",
|
||||
},
|
||||
{
|
||||
trigger:
|
||||
"div.bank_rec_widget_form_amls_list_anchor .o_searchview_facet:nth-child(1) .o_facet_value:contains('INV/2019/00001')",
|
||||
},
|
||||
{
|
||||
content:
|
||||
"Nothing has changed: INV/2019/00001 is selected and still contains the search facet",
|
||||
trigger:
|
||||
"div.bank_rec_widget_form_amls_list_anchor table.o_list_table tr.o_rec_widget_list_selected_item td[name='move_id']:contains('INV/2019/00001')",
|
||||
},
|
||||
{
|
||||
trigger: ".o_switch_view.o_kanban.active",
|
||||
},
|
||||
{
|
||||
content: "Switch to list view",
|
||||
trigger: ".o_switch_view.o_list",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o_switch_view.o_list.active",
|
||||
},
|
||||
{
|
||||
content: "Switch back to kanban",
|
||||
trigger: ".o_switch_view.o_kanban",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Remove the kanban filter for line2",
|
||||
trigger: ".o_kanban_view .o_searchview_facet:nth-child(3) .o_facet_remove",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger:
|
||||
"div.bank_rec_widget_form_amls_list_anchor .o_searchview_facet:nth-child(1) .o_facet_value:contains('INV/2019/00001')",
|
||||
},
|
||||
{
|
||||
content:
|
||||
"Nothing has changed: INV/2019/00001 is still selected and contains the search facet",
|
||||
trigger:
|
||||
"div.bank_rec_widget_form_amls_list_anchor table.o_list_table tr.o_rec_widget_list_selected_item td[name='move_id']:contains('INV/2019/00001')",
|
||||
},
|
||||
// AML Search Facet is removed, and line_ids reset when changing line
|
||||
{
|
||||
trigger: ".o_bank_rec_st_line:contains('line3')",
|
||||
},
|
||||
{
|
||||
content: "selecting 'line1' should reset the AML search filter ",
|
||||
trigger: ".o_bank_rec_st_line:contains('line1')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: "div[name='line_ids'] td[field='name']:contains('line1')",
|
||||
},
|
||||
{
|
||||
content: "select 'line2' again",
|
||||
trigger: ".o_bank_rec_st_line:contains('line2')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: "div[name='line_ids'] td[field='name']:contains('line2')",
|
||||
},
|
||||
{
|
||||
content: "Bank Suspense Account is back",
|
||||
trigger: "div[name='line_ids'] .o_bank_rec_auto_balance_line",
|
||||
},
|
||||
{
|
||||
content: "AML Search Filter has been reset",
|
||||
trigger: ".o_list_view .o_searchview_input_container:not(:has(.o_searchview_facet))",
|
||||
},
|
||||
// Test statement line selection when using the pager
|
||||
{
|
||||
content: "Click Pager",
|
||||
trigger: ".o_pager_value:first()",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Change pager to display lines 1-2",
|
||||
trigger: "input.o_pager_value",
|
||||
run: "edit 1-2 && click body",
|
||||
},
|
||||
{
|
||||
trigger: ".o_pager_value:contains('1-2')",
|
||||
},
|
||||
{
|
||||
content: "Last St Line is line2",
|
||||
trigger: ".o_bank_rec_st_line:last():contains('line2')",
|
||||
},
|
||||
{
|
||||
content: "Page Next",
|
||||
trigger: ".o_pager_next:first():not(:disabled)",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o_pager_value:contains('3-3')",
|
||||
},
|
||||
{
|
||||
content: "Statement line3 is selected",
|
||||
trigger: ".o_bank_rec_selected_st_line:contains('line3')",
|
||||
},
|
||||
{
|
||||
content: "Page to beginning",
|
||||
trigger: ".o_pager_next:first()",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: "div[name='line_ids'] td[field='name']:contains('line1')",
|
||||
},
|
||||
{
|
||||
content: "Statement line1 is selected",
|
||||
trigger: ".o_bank_rec_selected_st_line:contains('line1')",
|
||||
},
|
||||
// HTML buttons
|
||||
{
|
||||
content: "Mount an invoice",
|
||||
trigger:
|
||||
"div.bank_rec_widget_form_amls_list_anchor table.o_list_table td[name='move_id']:contains('INV/2019/00003')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger:
|
||||
"div[name='line_ids']:has(.text-decoration-line-through:contains('$ 2,000.00'))",
|
||||
},
|
||||
{
|
||||
content: "Select the mounted invoice line and check the strikethrough value",
|
||||
trigger:
|
||||
"div[name='line_ids'] tr.o_data_row:last() td[field='name']:contains('INV/2019/00003')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: "a.active[name='manual_operations_tab']",
|
||||
},
|
||||
{
|
||||
content: "Fully Paid button",
|
||||
trigger: "button[name='action_apply_line_suggestion']:contains('fully paid')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Check the remainder",
|
||||
trigger:
|
||||
"div[name='line_ids'] tr.o_data_row:contains('Suspense') td[field='debit']:contains('$ 1,000.00')",
|
||||
},
|
||||
{
|
||||
content: "Partial Payment",
|
||||
trigger: "button[name='action_apply_line_suggestion']:contains('partial payment')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: "button[name='action_apply_line_suggestion']:contains('fully paid')",
|
||||
},
|
||||
{
|
||||
content: "View Invoice 0003",
|
||||
trigger: "button[name='action_redirect_to_move']",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o_breadcrumb .active:contains('INV/2019/00003')",
|
||||
},
|
||||
{
|
||||
content: "Breadcrumb back to Bank Reconciliation from INV/2019/00003",
|
||||
trigger: ".breadcrumb-item:contains('Bank Reconciliation')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Select the mounted invoice line INV/2019/00003",
|
||||
trigger:
|
||||
"div[name='line_ids'] tr.o_data_row:last() td[field='name']:contains('INV/2019/00003')",
|
||||
run: "click",
|
||||
},
|
||||
// Match Existing entries tab is activated when line is removed
|
||||
{
|
||||
trigger: "a.active[name='manual_operations_tab']",
|
||||
},
|
||||
{
|
||||
content: "Remove the invoice",
|
||||
trigger: ".o_list_record_remove .fa-trash-o",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "amls_tab is activated",
|
||||
trigger: "a.active[name='amls_tab']",
|
||||
},
|
||||
{
|
||||
content: "Activate Manual Operations to add manual entries",
|
||||
trigger: "a[name='manual_operations_tab']",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "add manual entry 1",
|
||||
trigger: "div[name='amount_currency'] input",
|
||||
run: "edit -600.0 && click body",
|
||||
},
|
||||
{
|
||||
content: "mount the remaining opening balance line",
|
||||
trigger:
|
||||
"div[name='line_ids'] tr.o_data_row:contains('Suspense') td[field='credit']:contains('$ 400.00')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: "div[name='amount_currency'] input:value('-400.00'):focus-within",
|
||||
},
|
||||
{
|
||||
content: "Remove the manual entry",
|
||||
trigger: ".o_list_record_remove .fa-trash-o",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger:
|
||||
"div[name='line_ids'] tr.o_data_row:contains('Suspense') td[field='credit']:contains('$ 1,000.00')",
|
||||
},
|
||||
{
|
||||
content: "amls_tab is activated and auto balancing line is 1000",
|
||||
trigger: "a.active[name='amls_tab']",
|
||||
},
|
||||
{
|
||||
content: "Mount another invoice",
|
||||
trigger:
|
||||
"div.bank_rec_widget_form_amls_list_anchor table.o_list_table td[name='move_id']:contains('INV/2019/00001')",
|
||||
run: "click",
|
||||
},
|
||||
// After validating, line1 should disappear & line2 should be selected (due to filters)
|
||||
{
|
||||
trigger:
|
||||
"div.bank_rec_widget_form_amls_list_anchor table.o_list_table tr.o_rec_widget_list_selected_item td[name='move_id']:contains('INV/2019/00001')",
|
||||
},
|
||||
{
|
||||
content: "Validate line1",
|
||||
trigger: "button:contains('Validate')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: "div[name='line_ids'] td[field='name']:contains('line2')",
|
||||
},
|
||||
{
|
||||
content: "The 'line2' is the first kanban record and is selected",
|
||||
trigger: ".o_bank_rec_st_line:first():contains('line2')",
|
||||
},
|
||||
// Test Reset, "Matched" badge and double-click
|
||||
{
|
||||
content: "Remove the kanban filter for 'Not Matched'",
|
||||
trigger: ".o_kanban_view .o_searchview_facet:nth-child(2) .o_facet_remove",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: "div[name='line_ids'] td[field='name']:contains('line2')",
|
||||
},
|
||||
{
|
||||
content: "The 'line1' is the first kanban record with line2 selected",
|
||||
trigger: ".o_bank_rec_st_line:first():contains('line1')",
|
||||
},
|
||||
{
|
||||
content: "Mount invoice 2 for line 2",
|
||||
trigger:
|
||||
"div.bank_rec_widget_form_amls_list_anchor table.o_list_table td[name='move_id']:contains('INV/2019/00002')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger:
|
||||
"div.bank_rec_widget_form_amls_list_anchor table.o_list_table tr.o_rec_widget_list_selected_item td[name='move_id']:contains('INV/2019/00002')",
|
||||
},
|
||||
{
|
||||
content: "Validate line2 with double click",
|
||||
trigger: "button:contains('Validate')",
|
||||
run: "dblclick",
|
||||
},
|
||||
{
|
||||
trigger: ".o_bank_rec_st_line:contains('line2') .badge.text-bg-success",
|
||||
},
|
||||
{
|
||||
content: "Click Pager again after line2 is matched",
|
||||
trigger: ".o_pager_value:first()",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Change pager to display lines 1-3",
|
||||
trigger: "input.o_pager_value",
|
||||
run: "edit 1-3 && click body",
|
||||
},
|
||||
{
|
||||
trigger: ".o_bank_rec_selected_st_line:contains('line3')",
|
||||
},
|
||||
{
|
||||
content: "manually select line2 again by clicking it's matched icon",
|
||||
trigger: ".badge.text-bg-success:last()",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger:
|
||||
"div[name='line_ids']:not(:has(.fa-trash-o)) td[field='name']:contains('line2')",
|
||||
},
|
||||
{
|
||||
content: "Reset line2",
|
||||
trigger: "button:contains('Reset')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o_bank_rec_selected_st_line:contains('line2'):not(:has(div.badge))",
|
||||
},
|
||||
{
|
||||
content: "amls_tab is activated while still on line2 which doesn't contain a badge",
|
||||
trigger: ".o_notebook a.active[name='amls_tab']",
|
||||
},
|
||||
// Test view_switcher
|
||||
{
|
||||
trigger: ".o_switch_view.o_kanban.active",
|
||||
},
|
||||
{
|
||||
content: "Switch to list view",
|
||||
trigger: ".o_switch_view.o_list",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".btn-secondary:contains('View')",
|
||||
},
|
||||
{
|
||||
content: "Select the first Match Button (line2)",
|
||||
trigger: ".btn-secondary:contains('Match')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o_bank_rec_st_line:last():contains('line2')",
|
||||
},
|
||||
{
|
||||
content: "Last St Line is line2",
|
||||
trigger: ".o_bank_rec_selected_st_line:contains('line2')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Button To Check will reconcile since partner is saved on line2",
|
||||
trigger: ".btn-secondary:contains('To Check')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger:
|
||||
".o_bank_rec_selected_st_line:contains('line2'):has(div.badge[title='Matched'] i):has(span.badge:contains('To check'))",
|
||||
},
|
||||
{
|
||||
content: "both badges are visible, trash icon is not, manual operation tab is active",
|
||||
trigger:
|
||||
"div[name='line_ids']:not(:has(.fa-trash-o))+.o_notebook a.active[name='manual_operations_tab']",
|
||||
},
|
||||
{
|
||||
trigger: ".o_switch_view.o_kanban.active",
|
||||
},
|
||||
{
|
||||
content: "Switch to list view",
|
||||
trigger: ".o_switch_view.o_list",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o_switch_view.o_list.active",
|
||||
},
|
||||
{
|
||||
content: "Remove the line filter",
|
||||
trigger: ".o_searchview_facet:contains('0002') .o_facet_remove",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o_data_row:contains('line2'):has(.btn-secondary:contains('View'))",
|
||||
},
|
||||
{
|
||||
content: "Select the first Match Button (line3)",
|
||||
trigger: ".btn-secondary:contains('Match')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o_bank_rec_stats_buttons",
|
||||
},
|
||||
{
|
||||
content: "Open search bar menu",
|
||||
trigger: ".o_searchview_dropdown_toggler:eq(0)",
|
||||
run: "click",
|
||||
},
|
||||
// Test Reco Model
|
||||
{
|
||||
trigger: ".o-dropdown--menu.o_search_bar_menu",
|
||||
},
|
||||
{
|
||||
content: "Choose a filter",
|
||||
trigger: ".o_search_bar_menu .dropdown-item:first()",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o-dropdown--menu",
|
||||
},
|
||||
{
|
||||
content: "Not Matched Filter",
|
||||
trigger: ".dropdown-item:contains('Not Matched')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o_switch_view.o_kanban.active",
|
||||
},
|
||||
{
|
||||
content: "reco model dropdown",
|
||||
trigger: ".bank_rec_reco_model_dropdown i",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o-dropdown--menu",
|
||||
},
|
||||
{
|
||||
content: "create model",
|
||||
trigger: ".dropdown-item:contains('Create model')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "model name",
|
||||
trigger: "input#name_0",
|
||||
run: "edit Bank Fees",
|
||||
},
|
||||
{
|
||||
content: "add an account",
|
||||
trigger: "a:contains('Add a line')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "search for bank fees account",
|
||||
trigger: "[name='account_id'] input",
|
||||
run: "edit Bank Fees",
|
||||
},
|
||||
{
|
||||
trigger: ".o-autocomplete--dropdown-menu",
|
||||
},
|
||||
{
|
||||
content: "select the bank fees account",
|
||||
trigger: ".o-autocomplete--dropdown-item:contains('Bank Fees')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o_breadcrumb .active > span:contains('New')",
|
||||
},
|
||||
{
|
||||
content: "Breadcrumb back to Bank Reconciliation from the model",
|
||||
trigger: ".breadcrumb-item:contains('Bank Reconciliation')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Choose Bank Fees Model",
|
||||
trigger: ".recon_model_button:contains('Bank Fees')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Validate line3",
|
||||
trigger: "button:contains('Validate').btn-primary",
|
||||
run: "dblclick",
|
||||
},
|
||||
{
|
||||
trigger: ".o_reward_rainbow_man",
|
||||
},
|
||||
{
|
||||
content:
|
||||
"Remove the kanbans 'not matched' filter to reset all lines - use the rainbow man button",
|
||||
trigger: "p.btn-primary:contains('All Transactions')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger:
|
||||
".o_kanban_view .o_searchview:first() .o_searchview_facet:last():contains('Bank')",
|
||||
},
|
||||
{
|
||||
content: "Wait for search model change and line3 to appear",
|
||||
trigger: ".o_bank_rec_st_line:last():contains('line3')",
|
||||
},
|
||||
{
|
||||
trigger: ".o_bank_rec_selected_st_line:contains('line2')",
|
||||
},
|
||||
{
|
||||
content: "'line2' should be selected, reset it",
|
||||
trigger: "button:contains('Reset')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o_bank_rec_st_line:contains('line2'):not(:has(div.badge))",
|
||||
},
|
||||
{
|
||||
content: "select matched 'line3'",
|
||||
trigger: ".o_bank_rec_st_line:contains('line3')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o_bank_rec_selected_st_line:contains('line3')",
|
||||
},
|
||||
{
|
||||
content: "'line3' should be selected, reset it",
|
||||
trigger: "button:contains('Reset')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o_bank_rec_st_line:contains('line3'):not(:has(div.badge))",
|
||||
},
|
||||
{
|
||||
content: "select matched 'line1'",
|
||||
trigger: ".o_bank_rec_st_line:contains('line1')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o_bank_rec_selected_st_line:contains('line1')",
|
||||
},
|
||||
{
|
||||
content: "'line1' should be selected, reset it",
|
||||
trigger: "button:contains('Reset')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o_bank_rec_stats_buttons",
|
||||
},
|
||||
{
|
||||
content: "Open search bar menu",
|
||||
trigger: ".o_searchview_dropdown_toggler:eq(0)",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: "button:contains('Validate')",
|
||||
},
|
||||
{
|
||||
content: "Filter Menu",
|
||||
trigger: ".o_search_bar_menu .dropdown-item:first()",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o-dropdown--menu",
|
||||
},
|
||||
{
|
||||
content: "Activate the Not Matched filter",
|
||||
trigger: ".dropdown-item:contains('Not Matched')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o_searchview_facet:contains('Not Matched')",
|
||||
},
|
||||
{
|
||||
content: "Close the Filter Menu",
|
||||
trigger: ".o_searchview_dropdown_toggler:eq(0)",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o_searchview_facet:contains('Not Matched')",
|
||||
},
|
||||
{
|
||||
content: "select 'line2'",
|
||||
trigger: ".o_bank_rec_st_line:contains('line2')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o_bank_rec_selected_st_line:contains('line2')",
|
||||
},
|
||||
{
|
||||
content: "Validate 'line2' again",
|
||||
trigger: "button:contains('Validate')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o_bank_rec_selected_st_line:contains('line3')",
|
||||
},
|
||||
{
|
||||
content: "'line3' should be selected now",
|
||||
trigger: ".o_bank_rec_selected_st_line:contains('line3')",
|
||||
},
|
||||
// Test the Balance when changing journal and liquidity line
|
||||
...stepUtils.toggleHomeMenu(),
|
||||
...accountTourSteps.goToAccountMenu("Reset back to accounting module"),
|
||||
{
|
||||
trigger: ".o_breadcrumb",
|
||||
},
|
||||
{
|
||||
content: "Open the bank reconciliation widget for Bank2",
|
||||
trigger: "button.btn-secondary[name='action_open_reconcile']:last()",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Remove the kanbans 'not matched' filter",
|
||||
trigger: ".o_kanban_view .o_searchview_facet:nth-child(2) .o_facet_remove",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Remove the kanban 'journal' filter",
|
||||
trigger: ".o_kanban_view .o_searchview_facet:nth-child(1) .o_facet_remove",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "select 'line1' from another journal",
|
||||
trigger: ".o_bank_rec_st_line:contains('line1')",
|
||||
run: "click",
|
||||
},
|
||||
...accountTourSteps.bankRecUiReportSteps(),
|
||||
{
|
||||
content: "select 'line4' from this journal",
|
||||
trigger: ".o_bank_rec_st_line:contains('line4')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o_bank_rec_selected_st_line:contains('line4')",
|
||||
},
|
||||
{
|
||||
content: "balance is $222.22",
|
||||
trigger: ".btn-link:contains('$ 222.22')",
|
||||
},
|
||||
{
|
||||
content: "Select the liquidity line",
|
||||
trigger: "tr.o_bank_rec_liquidity_line td[field='debit']",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: "div[name='amount_currency'] input:focus-within",
|
||||
},
|
||||
{
|
||||
content: "Modify the liquidity line amount",
|
||||
trigger: "div[name='amount_currency'] input",
|
||||
run: "edit -333.33 && click body",
|
||||
},
|
||||
{
|
||||
trigger: ".btn-link:contains('$ -333.33')",
|
||||
},
|
||||
{
|
||||
content: "balance displays $-333.33",
|
||||
trigger: ".btn-link:contains('$ -333.33')",
|
||||
},
|
||||
{
|
||||
content: "Modify the label",
|
||||
trigger: "div[name='name'] input",
|
||||
run: "edit Spontaneous Combustion && click body",
|
||||
},
|
||||
{
|
||||
content: "statement line displays combustion and $-333.33",
|
||||
trigger: ".o_bank_rec_selected_st_line:contains('Combustion'):contains('$ -333.33')",
|
||||
},
|
||||
// Test that changing the balance in the list view updates the right side of the kanban view
|
||||
// (including reapplying matching rules)
|
||||
{
|
||||
content: "select matched 'line2'",
|
||||
trigger: ".o_bank_rec_st_line:contains('line2')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o_bank_rec_selected_st_line:contains('line2')",
|
||||
},
|
||||
{
|
||||
content: "'line2' should be selected, reset it",
|
||||
trigger: "button:contains('Reset')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o_bank_rec_selected_st_line:contains('line2'):not(:has(div.badge))",
|
||||
},
|
||||
{
|
||||
content: "Liquidity line displays debit '$ 100.00'",
|
||||
trigger:
|
||||
"div[name='line_ids'] table.o_list_table tr.o_bank_rec_liquidity_line td[field='debit']:contains('$ 100.00')",
|
||||
},
|
||||
{
|
||||
trigger: ".o_switch_view.o_kanban.active",
|
||||
},
|
||||
{
|
||||
content: "Switch to list view",
|
||||
trigger: ".o_switch_view.o_list",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Click amount field of 'line2'; Selects the row",
|
||||
trigger: "table.o_list_table tr.o_data_row:contains('line2') td[name='amount']",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Set balance of 'line2' (selected row) to 500.00",
|
||||
trigger: "table.o_list_table tr.o_data_row.o_selected_row td[name='amount'] input",
|
||||
run: "edit 500.00 && click body",
|
||||
},
|
||||
{
|
||||
trigger: ".o_switch_view.o_list.active",
|
||||
},
|
||||
{
|
||||
content: "Switch back to kanban",
|
||||
trigger: ".o_switch_view.o_kanban",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "'line2' is still selected",
|
||||
trigger: ".o_bank_rec_st_line:contains('line2')",
|
||||
},
|
||||
{
|
||||
content: "Liquidity line displays debit '$ 500.00'",
|
||||
trigger:
|
||||
"div[name='line_ids'] table.o_list_table tr.o_bank_rec_liquidity_line td[field='debit']:contains('$ 500.00')",
|
||||
},
|
||||
{
|
||||
content:
|
||||
"'INV/2019/00001' has been selected as matching existing entry by matching rules",
|
||||
trigger:
|
||||
"div.bank_rec_widget_form_amls_list_anchor table.o_list_table tr.o_rec_widget_list_selected_item td[name='name']:contains('INV/2019/00001')",
|
||||
},
|
||||
// End
|
||||
...stepUtils.toggleHomeMenu(),
|
||||
...accountTourSteps.goToAccountMenu("Reset back to accounting module"),
|
||||
{
|
||||
content: "check that we're back on the dashboard",
|
||||
trigger: 'a:contains("Customer Invoices")',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add('fusion_accounting_bank_rec_widget_reconciliation_button',
|
||||
{
|
||||
url: '/odoo',
|
||||
steps: () => [
|
||||
stepUtils.showAppsMenuItem(),
|
||||
...accountTourSteps.goToAccountMenu("Open the accounting module"),
|
||||
{
|
||||
content: "Open the bank reconciliation widget",
|
||||
trigger: "button.btn-secondary[name='action_open_reconcile']",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Remove suggested line, if present",
|
||||
trigger: ".o_list_record_remove",
|
||||
run() {
|
||||
const button = document.querySelector('.fa-trash-o');
|
||||
if(button) {
|
||||
button.click();
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
content: "Wait for deletion",
|
||||
trigger: ".o_data_row:contains('Open balance')",
|
||||
},
|
||||
{
|
||||
content: "Select reconciliation model creating a new move",
|
||||
trigger: ".recon_model_button:contains('test reconcile')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Confirm move created through reconciliation model writeoff button",
|
||||
trigger: "button[name=action_post]",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o_breadcrumb",
|
||||
},
|
||||
{
|
||||
content: "Breadcrumb back to Bank Reconciliation from created move",
|
||||
trigger: ".breadcrumb-item:contains('Bank Reconciliation')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Validate created move added as a line in reco widget",
|
||||
trigger: "button:contains('Validate')",
|
||||
run: "click",
|
||||
},
|
||||
// End
|
||||
...stepUtils.toggleHomeMenu(),
|
||||
...accountTourSteps.goToAccountMenu("Reset back to accounting module"),
|
||||
{
|
||||
content: "check that we're back on the dashboard",
|
||||
trigger: 'a:contains("Customer Invoices")',
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -0,0 +1,236 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { registry } from "@web/core/registry";
|
||||
import { stepUtils } from "@web_tour/tour_service/tour_utils";
|
||||
import { accountTourSteps } from "@account/js/tours/account";
|
||||
|
||||
registry.category("web_tour.tours").add("fusion_accounting_bank_rec_widget", {
|
||||
url: "/odoo",
|
||||
steps: () => [
|
||||
stepUtils.showAppsMenuItem(),
|
||||
...accountTourSteps.goToAccountMenu("Open the accounting module"),
|
||||
|
||||
// Open the widget. The first line should be selected by default.
|
||||
{
|
||||
trigger: ".o_breadcrumb",
|
||||
},
|
||||
{
|
||||
content: "Open the bank reconciliation widget",
|
||||
trigger: "button.btn-secondary[name='action_open_reconcile']",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: "div[name='line_ids']",
|
||||
},
|
||||
{
|
||||
content: "The 'line1' should be selected by default",
|
||||
trigger: "div[name='line_ids'] td[field='name']:contains('line1')",
|
||||
},
|
||||
|
||||
// Test 1: Check the loading of lazy notebook tabs.
|
||||
// Check 'amls_tab' (active by default).
|
||||
{
|
||||
trigger: "div.bank_rec_widget_form_amls_list_anchor table.o_list_table",
|
||||
},
|
||||
{
|
||||
content: "The 'amls_tab' should be active and the inner list view loaded",
|
||||
trigger: "a.active[name='amls_tab']",
|
||||
},
|
||||
// Check 'discuss_tab'.
|
||||
{
|
||||
trigger: "a.active[name='amls_tab']",
|
||||
},
|
||||
{
|
||||
content: "Click on the 'discuss_tab'",
|
||||
trigger: "a[name='discuss_tab']",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: "a.active[name='discuss_tab']",
|
||||
},
|
||||
{
|
||||
content: "The 'discuss_tab' should be active and the chatter loaded",
|
||||
trigger: "div.bank_rec_widget_form_discuss_anchor div.o-mail-Chatter",
|
||||
},
|
||||
// Check 'manual_operations_tab'.
|
||||
{
|
||||
trigger: "tr.o_bank_rec_auto_balance_line",
|
||||
},
|
||||
{
|
||||
content: "Click on the 'auto_balance' to make the 'manual_operations_tab' visible",
|
||||
trigger: "tr.o_bank_rec_auto_balance_line td[field='name']",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "The 'manual_operations_tab' should be active",
|
||||
trigger: "a.active[name='manual_operations_tab']",
|
||||
},
|
||||
{
|
||||
content: "The 'name' field should be focus automatically",
|
||||
trigger: "div.o_notebook div[name='name'] input:focus",
|
||||
},
|
||||
{
|
||||
trigger: "tr.o_bank_rec_auto_balance_line",
|
||||
},
|
||||
{
|
||||
content: "Click on the 'credit' field to change the focus from 'name' to 'amount_currency'",
|
||||
trigger: "tr.o_bank_rec_auto_balance_line td[field='credit']",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Wait to avoid non-deterministic errors on the next step",
|
||||
trigger: "tr.o_bank_rec_auto_balance_line td[field='credit']",
|
||||
},
|
||||
{
|
||||
content: "The 'balance' field should be focus now",
|
||||
trigger: "div.o_notebook div[name='amount_currency'] input:focus",
|
||||
},
|
||||
|
||||
// Test 2: Test validation + auto select the next line.
|
||||
{
|
||||
trigger: "a.active[name='manual_operations_tab']",
|
||||
},
|
||||
{
|
||||
content: "Click on the 'amls_tab'",
|
||||
trigger: "a[name='amls_tab']",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: "a.active[name='amls_tab']",
|
||||
},
|
||||
{
|
||||
content: "Mount INV/2019/00002",
|
||||
trigger:
|
||||
"div.bank_rec_widget_form_amls_list_anchor table.o_list_table td[name='move_id']:contains('INV/2019/00002')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger:
|
||||
"div.bank_rec_widget_form_amls_list_anchor table.o_list_table tr.o_rec_widget_list_selected_item td[name='move_id']:contains('INV/2019/00002')",
|
||||
},
|
||||
{
|
||||
content: "Check INV/2019/00002 is well marked as selected",
|
||||
trigger:
|
||||
"div.bank_rec_widget_form_amls_list_anchor table.o_list_table tr.o_rec_widget_list_selected_item td[name='move_id']:contains('INV/2019/00002')",
|
||||
},
|
||||
{
|
||||
trigger:
|
||||
"div.bank_rec_widget_form_amls_list_anchor table.o_list_table tr.o_rec_widget_list_selected_item td[name='move_id']:contains('INV/2019/00002')",
|
||||
},
|
||||
{
|
||||
content: "Remove INV/2019/00002",
|
||||
trigger: "tr td.o_list_record_remove button",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger:
|
||||
"div.bank_rec_widget_form_amls_list_anchor table.o_list_table tr:not(.o_rec_widget_list_selected_item) td[name='move_id']:contains('INV/2019/00002')",
|
||||
},
|
||||
{
|
||||
content: "Mount INV/2019/00001",
|
||||
trigger:
|
||||
"div.bank_rec_widget_form_amls_list_anchor table.o_list_table td[name='move_id']:contains('INV/2019/00001')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger:
|
||||
"div.bank_rec_widget_form_amls_list_anchor table.o_list_table tr.o_rec_widget_list_selected_item td[name='move_id']:contains('INV/2019/00001')",
|
||||
},
|
||||
{
|
||||
content: "Validate",
|
||||
trigger: "button:contains('Validate')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: "div[name='line_ids'] td[field='name']:contains('line2')",
|
||||
},
|
||||
{
|
||||
content: "The 'line2' is the next not already reconciled line",
|
||||
trigger: "div[name='line_ids'] td[field='name']:contains('line2')",
|
||||
},
|
||||
|
||||
// Test 3: Test manual operations tab.
|
||||
{
|
||||
content: "Click on 'credit'",
|
||||
trigger: "div[name='line_ids'] td[field='credit']:last",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content:
|
||||
"The 'manual_operations_tab' should be active now and the auto_balance line mounted in edit",
|
||||
trigger: "a.active[name='manual_operations_tab']",
|
||||
},
|
||||
{
|
||||
content: "The last line should be selected",
|
||||
trigger: "div[name='line_ids'] tr.o_bank_rec_selected_line",
|
||||
},
|
||||
{
|
||||
content: "Search for 'partner_a'",
|
||||
trigger: "div[name='partner_id'] input",
|
||||
run: "edit partner_a",
|
||||
},
|
||||
{
|
||||
trigger: ".ui-autocomplete .o_m2o_dropdown_option a:contains('Create')",
|
||||
},
|
||||
{
|
||||
content: "Select 'partner_a'",
|
||||
trigger: ".ui-autocomplete:visible li:contains('partner_a')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger:
|
||||
"tr:not(.o_bank_rec_auto_balance_line) td[field='partner_id']:contains('partner_a')",
|
||||
},
|
||||
{
|
||||
content: "Select the payable account",
|
||||
trigger: "button:contains('Payable')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger:
|
||||
"tr:not(.o_bank_rec_auto_balance_line) td[field='account_id']:contains('Payable')",
|
||||
},
|
||||
{
|
||||
content: "Enter a tax",
|
||||
trigger: "div[name='tax_ids'] input",
|
||||
run: "edit 15",
|
||||
},
|
||||
{
|
||||
trigger: ".ui-autocomplete",
|
||||
},
|
||||
{
|
||||
content: "Select 'Tax 15% (Sales)'",
|
||||
trigger: ".ui-autocomplete:visible li:contains('Sales')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Tax column appears in list of lines",
|
||||
trigger: "div[name='line_ids'] td[field='tax_ids']",
|
||||
},
|
||||
{
|
||||
content: "Wait to avoid non-deterministic errors on the next step",
|
||||
trigger: "div[name='line_ids'] td:contains('Tax Received')",
|
||||
},
|
||||
{
|
||||
trigger: "button.btn-primary:contains('Validate')",
|
||||
},
|
||||
{
|
||||
content: "Validate",
|
||||
trigger: "button:contains('Validate')",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: "div[name='line_ids'] td[field='name']:contains('line3')",
|
||||
},
|
||||
{
|
||||
content: "The 'line3' is the next not already reconciled line",
|
||||
trigger: "div[name='line_ids'] td[field='name']:contains('line3')",
|
||||
},
|
||||
...stepUtils.toggleHomeMenu(),
|
||||
...accountTourSteps.goToAccountMenu("Reset back to accounting module"),
|
||||
{
|
||||
content: "check that we're back on the dashboard",
|
||||
trigger: 'a:contains("Customer Invoices")',
|
||||
},
|
||||
],
|
||||
});
|
||||
56
Fusion Accounting/static/tests/util.test.js
Normal file
56
Fusion Accounting/static/tests/util.test.js
Normal file
@@ -0,0 +1,56 @@
|
||||
import { expect, test } from "@odoo/hoot";
|
||||
|
||||
import { buildLineId, parseLineId, removeTaxGroupingFromLineId } from "@fusion_accounting/js/util";
|
||||
|
||||
test("can build a line id from a list of [markup, res_model, res_id]", () => {
|
||||
const values = [
|
||||
[false, "account.account", 72],
|
||||
[null, "account.move", "10"],
|
||||
[undefined, "account.move.line", "22"],
|
||||
["name", false, null],
|
||||
['{"groupby": "account"}', false, null],
|
||||
];
|
||||
expect(buildLineId(values)).toBe(
|
||||
'~account.account~72|~account.move~10|~account.move.line~22|name~~|{"groupby": "account"}~~'
|
||||
);
|
||||
});
|
||||
|
||||
test("can parse a line id from a generic id with a markup as object", () => {
|
||||
const genericId =
|
||||
'~account.account~72|~account.move~10|~account.move.line~22|name~~|{"groupby": "account"}~~';
|
||||
expect(parseLineId(genericId)).toEqual([
|
||||
[null, "account.account", 72],
|
||||
[null, "account.move", 10],
|
||||
[null, "account.move.line", 22],
|
||||
["name", null, null],
|
||||
[{ groupby: "account" }, null, null],
|
||||
]);
|
||||
});
|
||||
|
||||
test("can parse a line id from a generic id with a markup as string", () => {
|
||||
const genericId =
|
||||
'~account.account~72|~account.move~10|~account.move.line~22|name~~|{"groupby": "account"}~~';
|
||||
expect(parseLineId(genericId, true)).toEqual([
|
||||
[null, "account.account", 72],
|
||||
[null, "account.move", 10],
|
||||
[null, "account.move.line", 22],
|
||||
["name", null, null],
|
||||
['{"groupby": "account"}', null, null],
|
||||
]);
|
||||
});
|
||||
|
||||
test("can parse and rebuild a line id to have the same one", () => {
|
||||
const genericId =
|
||||
'~account.account~72|~account.move~10|~account.move.line~22|name~~|{"groupby": "account"}~~';
|
||||
const parsedLineId = parseLineId(genericId);
|
||||
const buildedGenericId = buildLineId(parsedLineId);
|
||||
expect(buildedGenericId).toBe(genericId);
|
||||
});
|
||||
|
||||
test("can remove tax grouping by account group", () => {
|
||||
const genericId =
|
||||
'{"groupby": "account_group_id"}~account.group~22|~account.account~21|~account.move.line~20';
|
||||
expect(removeTaxGroupingFromLineId(genericId)).toBe(
|
||||
"~account.account~21|~account.move.line~20"
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user