- Copy all OWL frontend assets (JS/CSS/XML/fonts/images) into frontend/ directory (2925 files, 43MB) — no more runtime reads from Python Odoo - Replace OdooAddonsPath config with FrontendDir pointing to local frontend/ - Rewire bundle.go, static.go, templates.go, webclient.go to read from frontend/ instead of external Python Odoo addons directory - Auto-detect frontend/ and build/ dirs relative to binary in main.go - Delete obsolete Python helper scripts (tools/*.py) The Go server is now fully self-contained: single binary + frontend/ folder. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
189 lines
5.6 KiB
JavaScript
189 lines
5.6 KiB
JavaScript
import { describe, expect, test } from "@odoo/hoot";
|
|
import { setInputFiles } from "@odoo/hoot-dom";
|
|
import {
|
|
contains,
|
|
defineModels,
|
|
fields,
|
|
mockService,
|
|
models,
|
|
mountView,
|
|
onRpc,
|
|
} from "@web/../tests/web_test_helpers";
|
|
import { defineMailModels } from "@mail/../tests/mail_test_helpers";
|
|
|
|
class Partner extends models.Model {
|
|
name = fields.Char();
|
|
type = fields.Char();
|
|
|
|
_records = [
|
|
{
|
|
id: 7,
|
|
name: "first record",
|
|
type: "purchase",
|
|
},
|
|
];
|
|
_views = {
|
|
form: `
|
|
<form>
|
|
<widget name="account_file_uploader"/>
|
|
<field name="name" required="1"/>
|
|
</form>
|
|
`,
|
|
list: `
|
|
<list>
|
|
<field name="id"/>
|
|
<field name="name"/>
|
|
</list>
|
|
`,
|
|
search: `<search/>`,
|
|
};
|
|
}
|
|
|
|
class AccountPaymentTerm extends models.Model {
|
|
_name = "account_payment_term";
|
|
|
|
line_ids = fields.One2many({
|
|
string: "Payment Term Lines",
|
|
relation: "account_payment_term_line",
|
|
});
|
|
_records = [
|
|
{
|
|
id: 1,
|
|
line_ids: [1, 2],
|
|
},
|
|
];
|
|
}
|
|
|
|
class AccountPaymentTermLine extends models.Model {
|
|
_name = "account_payment_term_line";
|
|
|
|
value_amount = fields.Float({ string: "Due" });
|
|
_records = [
|
|
{
|
|
id: 1,
|
|
value_amount: 0,
|
|
},
|
|
{
|
|
id: 2,
|
|
value_amount: 50,
|
|
},
|
|
];
|
|
}
|
|
|
|
defineModels([AccountPaymentTerm, AccountPaymentTermLine, Partner]);
|
|
defineMailModels();
|
|
|
|
describe("AccountFileUploader", () => {
|
|
test("widget contains context based on the record despite field not in view", async () => {
|
|
onRpc("ir.attachment", "create", () => {
|
|
expect.step("create ir.attachment");
|
|
return [99];
|
|
});
|
|
|
|
onRpc("account.journal", "create_document_from_attachment", ({ kwargs }) => {
|
|
expect.step("create_document_from_attachment");
|
|
expect(kwargs.context.default_journal_id).toBe(7, {
|
|
message: "create documents in correct journal",
|
|
});
|
|
expect(kwargs.context.default_move_type).toBe("in_invoice", {
|
|
message: "create documents with correct move type",
|
|
});
|
|
return {
|
|
name: "Generated Documents",
|
|
domain: [],
|
|
res_model: "partner",
|
|
type: "ir.actions.act_window",
|
|
context: {},
|
|
views: [
|
|
[false, "list"],
|
|
[false, "form"],
|
|
],
|
|
view_mode: "list, form",
|
|
};
|
|
});
|
|
mockService("action", {
|
|
doAction(action) {
|
|
expect.step("doAction");
|
|
expect(action.type).toBe("ir.actions.act_window", {
|
|
message: "do action after documents created",
|
|
});
|
|
},
|
|
});
|
|
await mountView({
|
|
type: "form",
|
|
resModel: "partner",
|
|
resId: 7,
|
|
});
|
|
|
|
expect(".o_widget_account_file_uploader").toHaveCount(1);
|
|
const file = new File(["test"], "fake_file.txt", { type: "text/plain" });
|
|
await contains(".o_widget_account_file_uploader a").click();
|
|
await setInputFiles([file]);
|
|
await expect.waitForSteps([
|
|
"create ir.attachment",
|
|
"create_document_from_attachment",
|
|
"doAction",
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe("AccountMoveUploadKanbanView", () => {
|
|
test.tags("desktop");
|
|
test("can render AccountMoveUploadKanbanView", async () => {
|
|
Partner._views.kanban = `
|
|
<kanban js_class="account_documents_kanban">
|
|
<templates>
|
|
<t t-name="card">
|
|
<field name="name"/>
|
|
</t>
|
|
</templates>
|
|
</kanban>
|
|
`;
|
|
onRpc("res.company", "search_read", () => [{ id: 1, country_code: "US" }]);
|
|
await mountView({
|
|
type: "kanban",
|
|
resModel: "partner",
|
|
});
|
|
|
|
expect(".o_control_panel .o_button_upload_bill:visible").toHaveCount(1);
|
|
expect(".o_kanban_record:not(.o_kanban_ghost)").toHaveCount(1);
|
|
});
|
|
});
|
|
|
|
describe("PaymentTermsLineWidget", () => {
|
|
test("records don't get abandoned after clicking globally or on an exisiting record", async () => {
|
|
await mountView({
|
|
type: "form",
|
|
resModel: "account_payment_term",
|
|
resId: 1,
|
|
arch: `
|
|
<form>
|
|
<field name="line_ids" widget="payment_term_line_ids">
|
|
<list string="Payment Terms" editable="top">
|
|
<field name="value_amount"/>
|
|
|
|
</list>
|
|
</field>
|
|
</form>
|
|
`,
|
|
});
|
|
expect(".o_data_row").toHaveCount(2);
|
|
// click the add button
|
|
await contains(".o_field_x2many_list_row_add > a").click();
|
|
// make sure the new record is added
|
|
expect(".o_data_row").toHaveCount(3);
|
|
// global click
|
|
await contains(".o_form_view").click();
|
|
// make sure the new record is still there
|
|
expect(".o_data_row").toHaveCount(3);
|
|
// click the add button again
|
|
await contains(".o_field_x2many_list_row_add > a").click();
|
|
// make sure the new record is added
|
|
expect(".o_data_row").toHaveCount(4);
|
|
// click on an existing record
|
|
await contains(".o_data_row .o_data_cell").click();
|
|
// make sure the new record is still there
|
|
expect(".o_data_row").toHaveCount(4);
|
|
});
|
|
});
|