Files
goodie/frontend/sale/static/tests/sale_product_field.test.js
Marc 8741282322 Eliminate Python dependency: embed frontend assets in odoo-go
- 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>
2026-03-31 23:09:12 +02:00

202 lines
6.6 KiB
JavaScript

import { expect, test } from "@odoo/hoot";
import { press, runAllTimers } from "@odoo/hoot-dom";
import {
clickSave,
Command,
contains,
defineModels,
fields,
makeMockServer,
models,
mountView,
onRpc,
serverState,
} from "@web/../tests/web_test_helpers";
import { saleModels } from "./sale_test_helpers";
class SaleOrderLine extends saleModels.SaleOrderLine {
product_template_attribute_value_ids = fields.Many2many({
string: "Product template attributes values",
relation: "product.template.attribute.value",
});
}
class ProductTemplateAttributeValue extends models.Model {
_name = "product.template.attribute.value";
name = fields.Char();
}
defineModels({ ...saleModels, SaleOrderLine, ProductTemplateAttributeValue });
saleModels.SaleOrder._views.form = /* xml */ `
<form>
<field name="order_line" widget="sol_o2m" mode="list">
<list editable="bottom">
<field name="product_id" widget="sol_product_many2one"/>
<field name="product_template_id" widget="sol_product_many2one"/>
<field name="name" widget="sol_text"/>
</list>
</field>
</form>
`;
test.tags("desktop");
test("pressing tab with incomplete text will create a product", async () => {
onRpc(({ method }) => {
expect.step(method);
});
await mountView({
type: "form",
resModel: "sale.order",
arch: `
<form>
<sheet>
<field name="order_line">
<list editable="bottom">
<field name="product_template_id" widget="sol_product_many2one"/>
<field name="product_id" optional="hide"/>
<field name="name" optional="show"/>
</list>
</field>
</sheet>
</form>`,
});
// add a line and enter new product name
await contains(".o_field_x2many_list .o_field_x2many_list_row_add a").click();
await contains("[name='product_template_id'] input").edit("new product");
await press("tab");
await runAllTimers();
expect.verifySteps([
"get_views",
"onchange",
"onchange",
"web_name_search",
"name_create",
"get_single_product_variant",
]);
});
test("Hide product name if its not translated", async () => {
const { env } = await makeMockServer();
const product = env["product.product"][0];
const soId = env["sale.order"].create({
partner_id: serverState.partnerId,
order_line: [
Command.create({
product_id: product.id,
name: [product.name, "A description"].join("\n"),
translated_product_name: "Produit de test",
}),
],
});
await mountView({
type: "form",
resModel: "sale.order",
resId: soId,
});
expect(".o_field_product_label_section_and_note_cell .o_input").toHaveText("A description");
});
test("If translated product name already in the SOL name, should not hide the translated product name", async () => {
const { env } = await makeMockServer();
const translatedProductName = "Produit de test";
const product = env["product.product"][0];
const soId = env["sale.order"].create({
partner_id: serverState.partnerId,
order_line: [
Command.create({
product_id: product.id,
name: [product.name, translatedProductName, "A description"].join("\n"),
translated_product_name: translatedProductName,
}),
],
});
await mountView({
type: "form",
resModel: "sale.order",
resId: soId,
});
expect(".o_field_product_label_section_and_note_cell .o_input").toHaveText(
[translatedProductName, "A description"].join("\n")
);
});
test("Editing the description shouldn't show the translated product name", async () => {
const { env } = await makeMockServer();
const translatedProductName = "Produit de test";
const product = env["product.product"][0];
const soId = env["sale.order"].create({
partner_id: serverState.partnerId,
order_line: [
Command.create({
product_id: product.id,
name: [product.name, "something wrong"].join("\n"),
translated_product_name: translatedProductName,
}),
],
});
const [so] = env["sale.order"].browse(soId);
const [sol] = env["sale.order.line"].browse(so.order_line);
await mountView({
type: "form",
resModel: "sale.order",
resId: soId,
});
await contains(".o_field_product_label_section_and_note_cell").click();
await contains(".o_field_product_label_section_and_note_cell textarea").edit("A description");
await clickSave();
expect(".o_field_product_label_section_and_note_cell .o_input").toHaveText("A description");
expect(sol.name).toBe([translatedProductName, "A description"].join("\n"));
});
test("No description should be shown if there does not exist one apart from the product name", async () => {
const { env } = await makeMockServer();
const translatedProductName = "Produit de test";
const product = env["product.product"][0];
const soId = env["sale.order"].create({
partner_id: serverState.partnerId,
order_line: [
Command.create({
product_id: product.id,
name: product.name,
translated_product_name: translatedProductName,
}),
],
});
await mountView({
type: "form",
resModel: "sale.order",
resId: soId,
});
expect(".o_field_product_label_section_and_note_cell .o_input").not.toBeVisible();
});
test("No description should be shown if there does not exist one apart from the translated product name", async () => {
const { env } = await makeMockServer();
const translatedProductName = "Produit de test";
const product = env["product.product"][0];
const soId = env["sale.order"].create({
partner_id: serverState.partnerId,
order_line: [
Command.create({
product_id: product.id,
name: translatedProductName,
translated_product_name: translatedProductName,
}),
],
});
await mountView({
type: "form",
resModel: "sale.order",
resId: soId,
});
expect(".o_field_product_label_section_and_note_cell .o_input").not.toBeVisible();
});