vanilla 17.0

This commit is contained in:
Ernad Husremovic 2025-10-08 10:47:08 +02:00
parent d72e748793
commit a9bcec8e91
1986 changed files with 1613876 additions and 568976 deletions

View file

@ -92,63 +92,55 @@ QUnit.module("Views", ({ beforeEach }) => {
assert.containsNone(target, ".o_calendar_button_prev", "prev button should be hidden");
assert.containsNone(target, ".o_calendar_button_next", "next button should be hidden");
await click(target, ".o_calendar_container .o_other_calendar_panel");
assert.isVisible(
target.querySelector(
".o_cp_bottom_left .o_calendar_buttons .o_calendar_scale_buttons + button.o_cp_today_button"
".o_calendar_container .o_calendar_header button.o_calendar_button_today"
),
"today button should be visible near the calendar buttons (bottom left corner)"
"today button should be visible"
);
// Test all views
// displays month mode by default
assert.containsOnce(
target,
".fc-view-container > .fc-timeGridWeek-view",
"should display the current week"
);
assert.equal(
target.querySelector(".breadcrumb-item").textContent,
"undefined (Dec 11 17, 2016)"
target.querySelector(".o_calendar_container .o_calendar_header .dropdown-toggle")
.textContent,
"Week",
"should display the current week"
);
// switch to day mode
await click(target, ".o_control_panel .scale_button_selection");
await click(target, ".o_control_panel .o_calendar_button_day");
await click(target, ".o_calendar_container .o_calendar_header .dropdown-toggle");
await click(target, ".o_calendar_container .o_calendar_header .o_scale_button_day");
await nextTick();
assert.containsOnce(
target,
".fc-view-container > .fc-timeGridDay-view",
"should display the current day"
);
assert.equal(
target.querySelector(".breadcrumb-item").textContent,
"undefined (December 12, 2016)"
target.querySelector(".o_calendar_container .o_calendar_header .dropdown-toggle")
.textContent,
"Day",
"should display the current day"
);
// switch to month mode
await click(target, ".o_control_panel .scale_button_selection");
await click(target, ".o_control_panel .o_calendar_button_month");
await click(target, ".o_calendar_container .o_calendar_header .dropdown-toggle");
await click(target, ".o_calendar_container .o_calendar_header .o_scale_button_month");
await nextTick();
assert.containsOnce(
target,
".fc-view-container > .fc-dayGridMonth-view",
"should display the current month"
);
assert.equal(
target.querySelector(".breadcrumb-item").textContent,
"undefined (December 2016)"
target.querySelector(".o_calendar_container .o_calendar_header .dropdown-toggle")
.textContent,
"Month",
"should display the current month"
);
// switch to year mode
await click(target, ".o_control_panel .scale_button_selection");
await click(target, ".o_control_panel .o_calendar_button_year");
await click(target, ".o_calendar_container .o_calendar_header .dropdown-toggle");
await click(target, ".o_calendar_container .o_calendar_header .o_scale_button_year");
await nextTick();
assert.containsOnce(
target,
".fc-view-container > .fc-dayGridYear-view",
assert.equal(
target.querySelector(".o_calendar_container .o_calendar_header .dropdown-toggle")
.textContent,
"Year",
"should display the current year"
);
assert.equal(target.querySelector(".breadcrumb-item").textContent, "undefined (2016)");
});
QUnit.test("calendar: popover is rendered as dialog in mobile", async function (assert) {
@ -186,7 +178,9 @@ QUnit.module("Views", ({ beforeEach }) => {
await swipeRight(target, ".o_calendar_widget");
assert.equal(target.querySelector(".fc-day-header[data-date]").dataset.date, "2016-12-11");
await click(target, ".o_other_calendar_panel");
await click(target, ".o_calendar_button_today");
await click(target, ".o_other_calendar_panel");
assert.equal(target.querySelector(".fc-day-header[data-date]").dataset.date, "2016-12-12");
});
@ -202,18 +196,21 @@ QUnit.module("Views", ({ beforeEach }) => {
</calendar>`,
});
assert.containsOnce(target, ".o_calendar_renderer");
assert.containsOnce(target, ".o_other_calendar_panel");
await click(target, ".o_other_calendar_panel");
assert.containsOnce(
target,
".o_calendar_filter_items_checkall",
"should contain one filter to check all"
);
assert.containsN(
target,
".o_other_calendar_panel .o_filter > *",
3,
"should contains 3 child nodes -> 1 label (USER) + 2 resources (user 1/2)"
".o_calendar_filter_item",
2,
"should contain 2 child nodes -> 2 resources"
);
assert.containsNone(target, ".o_calendar_sidebar");
assert.containsOnce(target, ".o_calendar_renderer");
// Toggle the other calendar panel should hide the calendar view and show the sidebar
await click(target, ".o_other_calendar_panel");
assert.containsOnce(target, ".o_calendar_sidebar");
assert.containsNone(target, ".o_calendar_renderer");
assert.containsOnce(target, ".o_calendar_filter");
@ -224,8 +221,8 @@ QUnit.module("Views", ({ beforeEach }) => {
assert.containsN(
target,
".o_other_calendar_panel .o_filter > *",
1,
"should contains 1 child node -> 1 label (USER)"
0,
"should contain 0 child nodes -> no filters selected"
);
// Toggle again the other calendar panel should hide the sidebar and show the calendar view
@ -238,11 +235,11 @@ QUnit.module("Views", ({ beforeEach }) => {
patchWithCleanup(CalendarCommonRenderer.prototype, {
onDateClick(...args) {
assert.step("dateClick");
return this._super(...args);
return super.onDateClick(...args);
},
onSelect(...args) {
assert.step("select");
return this._super(...args);
return super.onSelect(...args);
},
});
@ -268,20 +265,20 @@ QUnit.module("Views", ({ beforeEach }) => {
QUnit.test('calendar: select range on "Free Zone" opens quick create', async function (assert) {
patchWithCleanup(CalendarCommonRenderer.prototype, {
get options() {
return Object.assign({}, this._super(), {
return Object.assign({}, super.options, {
selectLongPressDelay: 0,
});
},
onDateClick(info) {
assert.step("dateClick");
return this._super(info);
return super.onDateClick(info);
},
onSelect(info) {
assert.step("select");
const { startStr, endStr } = info;
assert.equal(startStr, "2016-12-12T01:00:00+01:00");
assert.equal(endStr, "2016-12-12T02:00:00+01:00");
return this._super(info);
return super.onSelect(info);
},
});
@ -309,21 +306,21 @@ QUnit.module("Views", ({ beforeEach }) => {
QUnit.test("calendar (year): select date range opens quick create", async function (assert) {
patchWithCleanup(CalendarYearRenderer.prototype, {
get options() {
return Object.assign({}, this._super(), {
return Object.assign({}, super.options, {
longPressDelay: 0,
selectLongPressDelay: 0,
});
},
onDateClick(info) {
assert.step("dateClick");
return this._super(info);
return super.onDateClick(info);
},
onSelect(info) {
assert.step("select");
const { startStr, endStr } = info;
assert.equal(startStr, "2016-02-02");
assert.equal(endStr, "2016-02-06"); // end date is exclusive
return this._super(info);
return super.onSelect(info);
},
});
@ -358,34 +355,39 @@ QUnit.module("Views", ({ beforeEach }) => {
// Should display year view
assert.containsOnce(target, ".fc-dayGridYear-view");
assert.containsN(target, ".fc-month-container", 12);
assert.equal(target.querySelector(".breadcrumb-item").textContent, "undefined (2016)");
// Tap on a date
await tap(target, ".fc-day-top[data-date='2016-02-05']");
await nextTick(); // switch renderer
await nextTick(); // await breadcrumb update
assert.strictEqual(
document.querySelector(".o_calendar_container .o_calendar_header h5").textContent,
"5 February 2016"
);
// Should display day view
assert.containsNone(target, ".fc-dayGridYear-view");
assert.containsOnce(target, ".fc-timeGridDay-view");
assert.equal(
target.querySelector(".breadcrumb-item").textContent,
"undefined (February 5, 2016)"
);
assert.equal(target.querySelector(".fc-day-header[data-date]").dataset.date, "2016-02-05");
// Change scale to month
await changeScale(target, "month");
assert.containsOnce(target, ".o_calendar_container .o_calendar_header h5");
assert.strictEqual(
document.querySelector(".o_calendar_container .o_calendar_header h5").textContent,
"February 2016"
);
assert.containsNone(target, ".fc-timeGridDay-view");
assert.containsOnce(target, ".fc-dayGridMonth-view");
assert.equal(
target.querySelector(".breadcrumb-item").textContent,
"undefined (February 2016)"
);
// Tap on a date
await tap(target, ".fc-day-top[data-date='2016-02-10']");
await nextTick(); // await reload & render
await nextTick(); // await breadcrumb update
assert.strictEqual(
document.querySelector(".o_calendar_container .o_calendar_header h5").textContent,
"February 2016"
);
// should open a Quick create modal view in mobile on short tap on date in monthly view
assert.containsOnce(target, ".modal");

View file

@ -44,7 +44,7 @@ QUnit.module("Fields", (hooks) => {
<field name="timmy" widget="many2many_tags" placeholder="foo"/>
</form>`,
});
assert.strictEqual(target.querySelector("#timmy").placeholder, "foo");
assert.strictEqual(target.querySelector("#timmy_0").placeholder, "foo");
});
QUnit.test("Many2ManyTagsField placeholder should be empty", async function (assert) {
@ -57,6 +57,6 @@ QUnit.module("Fields", (hooks) => {
<field name="timmy" widget="many2many_tags"/>
</form>`,
});
assert.strictEqual(target.querySelector("#timmy").placeholder, "");
assert.strictEqual(target.querySelector("#timmy_0").placeholder, "");
});
});

View file

@ -10,7 +10,6 @@ import * as BarcodeScanner from "@web/webclient/barcode/barcode_scanner";
let serverData;
let target;
const CREATE = "create";
const NAME_SEARCH = "name_search";
const PRODUCT_PRODUCT = "product.product";
const SALE_ORDER_LINE = "sale_order_line";
@ -123,8 +122,8 @@ QUnit.module("Fields", (hooks) => {
<field name="${PRODUCT_FIELD_NAME}" options="{'can_scan_barcode': True}"/>
</form>`,
async mockRPC(route, args, performRPC) {
if (args.method === CREATE && args.model === SALE_ORDER_LINE) {
const selectedId = args.args[0][PRODUCT_FIELD_NAME];
if (args.method === "web_save" && args.model === SALE_ORDER_LINE) {
const selectedId = args.args[1][PRODUCT_FIELD_NAME];
assert.equal(
selectedId,
selectedRecordTest.id,

View file

@ -2,6 +2,7 @@
import { click, getFixture } from "@web/../tests/helpers/utils";
import { makeView, setupViewRegistries } from "@web/../tests/views/helpers";
import { registerCleanup } from "@web/../tests/helpers/cleanup";
let fixture;
let serverData;
@ -10,6 +11,8 @@ QUnit.module("Mobile Fields", ({ beforeEach }) => {
beforeEach(() => {
setupViewRegistries();
fixture = getFixture();
fixture.setAttribute("style", "width:100vw; height:100vh;");
registerCleanup(() => fixture.removeAttribute("style"));
serverData = {
models: {
partner: {
@ -20,6 +23,7 @@ QUnit.module("Mobile Fields", ({ beforeEach }) => {
records: [
{ id: 1, display_name: "first record", trululu: 4 },
{ id: 2, display_name: "second record", trululu: 1 },
{ id: 3, display_name: "third record" },
{ id: 4, display_name: "aaa" },
],
},
@ -29,7 +33,7 @@ QUnit.module("Mobile Fields", ({ beforeEach }) => {
QUnit.module("StatusBarField");
QUnit.test("statusbar is rendered correclty on small devices", async (assert) => {
QUnit.test("statusbar is rendered correctly on small devices", async (assert) => {
await makeView({
type: "form",
resModel: "partner",
@ -45,16 +49,9 @@ QUnit.module("Mobile Fields", ({ beforeEach }) => {
`,
});
assert.containsOnce(
fixture,
".o_statusbar_status > button",
"should have only one visible status in mobile, the active one"
);
assert.containsOnce(
fixture,
".o_statusbar_status .dropdown",
"should have a dropdown containing all status"
);
assert.containsN(fixture, ".o_statusbar_status .o_arrow_button:visible", 4);
assert.containsOnce(fixture, ".o_statusbar_status .o_arrow_button.dropdown-toggle:visible");
assert.containsOnce(fixture, ".o_statusbar_status .o_arrow_button.o_arrow_button_current");
assert.containsNone(
fixture,
".o_statusbar_status .dropdown-menu",
@ -62,34 +59,18 @@ QUnit.module("Mobile Fields", ({ beforeEach }) => {
);
assert.strictEqual(
fixture.querySelector(".o_statusbar_status button.dropdown-toggle").textContent.trim(),
"aaa",
"statusbar button should display current field value"
"..."
);
// open the dropdown
await click(fixture, ".o_statusbar_status > button");
await click(fixture, ".o_statusbar_status .dropdown-toggle.o_last");
assert.containsOnce(
fixture,
".o_statusbar_status .dropdown-menu",
"dropdown should be visible"
);
assert.containsN(
fixture,
".o_statusbar_status .dropdown-menu .btn",
3,
"should have 3 status"
);
assert.containsN(
fixture,
".o_statusbar_status .btn.disabled",
3,
"all status should be disabled"
);
assert.hasClass(
fixture.querySelector(".o_statusbar_status .btn:nth-child(3)"),
"btn-primary",
"active status should be btn-primary"
);
assert.containsOnce(fixture, ".o_statusbar_status .dropdown-menu .dropdown-item.disabled");
});
QUnit.test("statusbar with no status on extra small screens", async (assert) => {
@ -112,49 +93,19 @@ QUnit.module("Mobile Fields", ({ beforeEach }) => {
"o_field_empty",
"statusbar widget should have class o_field_empty in edit"
);
assert.containsOnce(
fixture,
".o_statusbar_status button.dropdown-toggle",
"statusbar widget should have a button"
);
assert.strictEqual(
fixture.querySelector(".o_statusbar_status button.dropdown-toggle").textContent.trim(),
"",
"statusbar button shouldn't have text for null field value"
);
assert.containsOnce(fixture, ".o_statusbar_status button.dropdown-toggle:visible");
assert.strictEqual($(".o_statusbar_status button.dropdown-toggle:visible").text(), "...");
await click(fixture, ".o_statusbar_status button.dropdown-toggle");
assert.containsOnce(
fixture,
".o_statusbar_status .dropdown-menu",
"statusbar widget should have a dropdown menu"
);
assert.containsN(
fixture,
".o_statusbar_status .dropdown-menu .btn",
3,
"statusbar widget dropdown menu should have 3 buttons"
);
await click($(".o_statusbar_status button.dropdown-toggle:visible")[0]);
assert.containsOnce(fixture, ".o_statusbar_status .dropdown-menu");
assert.containsOnce(fixture, ".o_statusbar_status .dropdown-menu .dropdown-item");
assert.strictEqual(
fixture
.querySelectorAll(".o_statusbar_status .dropdown-menu .btn")[0]
.querySelector(".o_statusbar_status .dropdown-menu .dropdown-item")
.textContent.trim(),
"first record",
"statusbar widget dropdown first button should display the first record display_name"
);
assert.strictEqual(
fixture
.querySelectorAll(".o_statusbar_status .dropdown-menu .btn")[1]
.textContent.trim(),
"second record",
"statusbar widget dropdown second button should display the second record display_name"
);
assert.strictEqual(
fixture
.querySelectorAll(".o_statusbar_status .dropdown-menu .btn")[2]
.textContent.trim(),
"aaa",
"statusbar widget dropdown third button should display the third record display_name"
"statusbar widget dropdown first item should display the first record display_name"
);
});
@ -173,37 +124,20 @@ QUnit.module("Mobile Fields", ({ beforeEach }) => {
`,
});
await click(fixture, ".o_statusbar_status .dropdown-toggle");
assert.hasClass(
fixture.querySelector(".o_statusbar_status .dropdown-menu .btn:nth-child(3)"),
"btn-primary"
);
assert.hasClass(
fixture.querySelector(".o_statusbar_status .dropdown-menu .btn:nth-child(3)"),
"disabled"
);
// Open dropdown
await click($(".o_statusbar_status .dropdown-toggle:visible")[0]);
assert.containsN(
fixture,
".o_statusbar_status .btn-secondary:not(.dropdown-toggle):not(.disabled)",
2,
"other status should be btn-secondary and not disabled"
);
assert.containsOnce(fixture, ".o_statusbar_status .dropdown-item");
await click(
fixture.querySelector(
".o_statusbar_status .btn-secondary:not(.dropdown-toggle):not(.disabled)"
)
);
await click(fixture, ".o_statusbar_status .dropdown-item");
await click(fixture, ".o_statusbar_status .dropdown-toggle");
assert.hasClass(
fixture.querySelector(".o_statusbar_status .dropdown-menu .btn:nth-child(1)"),
"btn-primary"
);
assert.hasClass(
fixture.querySelector(".o_statusbar_status .dropdown-menu .btn:nth-child(1)"),
"disabled"
);
assert.strictEqual($(".o_arrow_button_current").text(), "first record");
assert.containsN(fixture, ".o_statusbar_status .o_arrow_button:visible", 3);
assert.containsOnce(fixture, ".o_statusbar_status .dropdown-toggle:visible");
// Open second dropdown
await click($(".o_statusbar_status .dropdown-toggle:visible")[0]);
assert.containsN(fixture, ".o_statusbar_status .dropdown-item", 2);
});
});

View file

@ -28,6 +28,7 @@ QUnit.module("Mobile Views", ({ beforeEach }) => {
fields: {
display_name: { type: "char", string: "Display Name" },
trululu: { type: "many2one", string: "Trululu", relation: "partner" },
boolean: { type: "boolean", string: "Bool" },
},
records: [
{ id: 1, display_name: "first record", trululu: 4 },
@ -104,8 +105,8 @@ QUnit.module("Mobile Views", ({ beforeEach }) => {
arch: `
<form>
<header>
<button string="Confirm" attrs="{'invisible': [['display_name', '=', 'first record']]}" />
<button string="Do it" attrs="{'invisible': [['display_name', '=', 'first record']]}" />
<button string="Confirm" invisible="display_name == 'first record'" />
<button string="Do it" invisible="display_name == 'first record'" />
</header>
<sheet>
<group>
@ -145,7 +146,7 @@ QUnit.module("Mobile Views", ({ beforeEach }) => {
arch: `
<form>
<header>
<button string="Hola" attrs="{'invisible': [['display_name', '=', 'first record']]}" />
<button string="Hola" invisible="display_name == 'first record'" />
<button string="Ciao" />
</header>
<sheet>
@ -197,7 +198,7 @@ QUnit.module("Mobile Views", ({ beforeEach }) => {
<form>
<header>
<widget name="attach_document" string="Attach document" />
<button string="Ciao" attrs="{'invisible': [['display_name', '=', 'first record']]}" />
<button string="Ciao" invisible="display_name == 'first record'" />
</header>
<sheet>
<group>
@ -251,8 +252,8 @@ QUnit.module("Mobile Views", ({ beforeEach }) => {
<form>
<header>
<button string="Just more than one" />
<button string="Confirm" attrs="{'invisible': [['display_name', '=', '']]}" />
<button string="Do it" attrs="{'invisible': [['display_name', '!=', '']]}" />
<button string="Confirm" invisible="display_name == ''" />
<button string="Do it" invisible="display_name != ''" />
</header>
<sheet>
<field name="display_name" />
@ -319,8 +320,8 @@ QUnit.module("Mobile Views", ({ beforeEach }) => {
</sheet>
</form>
`,
mockRPC(route, { method, args: [, , changedField] }) {
if (method === "onchange" && changedField === "display_name") {
mockRPC(route, { method, args }) {
if (method === "onchange" && args[2][0] === "display_name") {
return onchangeDef;
}
},
@ -422,7 +423,7 @@ QUnit.module("Mobile Views", ({ beforeEach }) => {
);
// click on back button
await click(fixture, ".modal .modal-header .fa-arrow-left");
await click(fixture, ".modal .modal-header .oi-arrow-left");
assert.strictEqual(
window.scrollY,
265,
@ -436,7 +437,7 @@ QUnit.module("Mobile Views", ({ beforeEach }) => {
let fileInput;
patchWithCleanup(AttachDocumentWidget.prototype, {
setup() {
this._super();
super.setup();
fileInput = this.fileInput;
},
});
@ -479,4 +480,38 @@ QUnit.module("Mobile Views", ({ beforeEach }) => {
await nextTick();
assert.verifySteps(["post"]);
});
QUnit.test("button box with 3/4 buttons (close to threshold)", async (assert) => {
await makeView({
type: "form",
resModel: "partner",
serverData,
arch: `
<form>
<sheet>
<div name="button_box">
<button>MyButton</button>
<button>MyButton2</button>
<button>MyButton3</button>
<button invisible="not boolean">MyButton4</button>
</div>
<field name="boolean"/>
</sheet>
</form>`,
resId: 2,
});
// 3 buttons to display -> no "More" dropdown
assert.containsNone(fixture, ".o_field_widget[name=boolean] input:checked");
assert.containsN(fixture, ".o-form-buttonbox > .oe_stat_button", 3);
assert.containsNone(fixture, ".o-form-buttonbox .o_button_more");
// 4 buttons to display -> 2 buttons visible + 2 inside the "More" dropdown
await click(fixture.querySelector(".o_field_widget[name=boolean] input"));
assert.containsN(fixture, ".o-form-buttonbox > .oe_stat_button", 3);
assert.containsOnce(fixture, ".o-form-buttonbox .oe_stat_button .o_button_more");
await click(fixture.querySelector(".o_button_more"));
assert.containsN(fixture, ".o_dropdown_more .oe_stat_button", 2);
});
});

View file

@ -0,0 +1,103 @@
/** @odoo-module **/
import { makeView, setupViewRegistries } from "@web/../tests/views/helpers";
import { click, getFixture, patchWithCleanup } from "@web/../tests/helpers/utils";
import { AnimatedNumber } from "@web/views/view_components/animated_number";
let serverData;
let target;
QUnit.module("Views", (hooks) => {
hooks.beforeEach(() => {
patchWithCleanup(AnimatedNumber, { enableAnimations: false });
serverData = {
models: {
partner: {
fields: {
foo: { string: "Foo", type: "char" },
product_id: {
string: "something_id",
type: "many2one",
relation: "product",
},
},
records: [
{
id: 1,
foo: "yop",
product_id: 3,
},
{
id: 2,
foo: "blip",
product_id: 5,
},
{
id: 3,
foo: "gnap",
product_id: 3,
},
{
id: 4,
foo: "blip",
product_id: 5,
},
],
},
product: {
fields: {
id: { string: "ID", type: "integer" },
name: { string: "Display Name", type: "char" },
},
records: [
{ id: 3, name: "hello" },
{ id: 5, name: "xmo" },
],
},
},
views: {},
};
target = getFixture();
setupViewRegistries();
});
QUnit.module("KanbanView");
QUnit.test("Should load grouped kanban with folded column", async (assert) => {
await makeView({
type: "kanban",
resModel: "partner",
serverData,
arch: `
<kanban>
<progressbar field="foo" colors='{"yop": "success", "blip": "danger"}'/>
<field name="product_id"/>
<templates>
<t t-name="kanban-box">
<div><field name="foo"/></div>
</t>
</templates>
</kanban>`,
groupBy: ["product_id"],
async mockRPC(route, args, performRPC) {
if (args.method === "web_read_group") {
const result = await performRPC(route, args);
result.groups[1].__fold = true;
return result;
}
},
});
assert.containsN(target, ".o_column_progress", 2, "Should have 2 progress bar");
assert.containsN(target, ".o_kanban_group", 2, "Should have 2 grouped column");
assert.containsN(target, ".o_kanban_record", 2, "Should have 2 loaded record");
assert.containsOnce(
target,
".o_kanban_load_more",
"Should have a folded column with a load more button"
);
await click(target, ".o_kanban_load_more button");
assert.containsNone(target, ".o_kanban_load_more", "Shouldn't have a load more button");
assert.containsN(target, ".o_kanban_record", 4, "Should have 4 loaded record");
});
});

View file

@ -61,13 +61,13 @@ QUnit.module("Mobile Views", ({ beforeEach }) => {
assert.containsN(fixture, ".o_data_row", 4);
assert.containsNone(fixture, ".o_list_selection_box");
assert.containsOnce(fixture, ".o_control_panel .o_cp_bottom_right");
assert.containsOnce(fixture, ".o_control_panel .fa-search");
// select a record
await triggerEvents(fixture, ".o_data_row:nth-child(1)", ["touchstart", "touchend"]);
assert.containsOnce(fixture, ".o_list_selection_box");
assert.containsNone(fixture, ".o_list_selection_box .o_list_select_domain");
assert.containsNone(fixture, ".o_control_panel .o_cp_bottom_right");
assert.containsNone(fixture, ".o_control_panel .o_cp_searchview");
assert.ok(
fixture.querySelector(".o_list_selection_box").textContent.includes("1 selected")
);
@ -87,14 +87,14 @@ QUnit.module("Mobile Views", ({ beforeEach }) => {
await toggleActionMenu(fixture);
assert.deepEqual(
getMenuItemTexts(fixture.querySelector(".o_cp_action_menus")),
["Delete"],
"action menu should contain the Delete action"
["Duplicate", "Delete"],
"action menu should contain the Duplicate and Delete actions"
);
// unselect all
await click(fixture, ".o_discard_selection");
await click(fixture, ".o_list_unselect_all");
assert.containsNone(fixture, ".o_list_selection_box");
assert.containsOnce(fixture, ".o_control_panel .o_cp_bottom_right");
assert.containsOnce(fixture, ".o_control_panel .fa-search");
});
QUnit.test("selection box is properly displayed (multi pages)", async function (assert) {
@ -134,8 +134,8 @@ QUnit.module("Mobile Views", ({ beforeEach }) => {
await toggleActionMenu(fixture);
assert.deepEqual(
getMenuItemTexts(fixture.querySelector(".o_cp_action_menus")),
["Delete"],
"action menu should contain the Delete action"
["Duplicate", "Delete"],
"action menu should contain the Duplicate and Delete actions"
);
// select all records of first page

View file

@ -1,6 +1,6 @@
/** @odoo-module */
import { click, getFixture } from "@web/../tests/helpers/utils";
import { click, getFixture, editInput } from "@web/../tests/helpers/utils";
import { makeView, setupViewRegistries } from "@web/../tests/views/helpers";
QUnit.module("ViewDialogs", (hooks) => {
@ -76,8 +76,8 @@ QUnit.module("ViewDialogs", (hooks) => {
<field name="linked_sale_order_line" widget="many2many_tags"/>
</form>`,
async mockRPC(route, args) {
if (args.method === "create" && args.model === "sale_order_line") {
const { product_id: selectedId } = args.args[0];
if (args.method === "web_save" && args.model === "sale_order_line") {
const { product_id: selectedId } = args.args[1];
assert.strictEqual(selectedId, false, `there should be no product selected`);
}
},
@ -132,8 +132,8 @@ QUnit.module("ViewDialogs", (hooks) => {
<field name="linked_sale_order_line" widget="many2many_tags"/>
</form>`,
async mockRPC(route, args) {
if (args.method === "create" && args.model === "sale_order_line") {
const { product_id: selectedId } = args.args[0];
if (args.method === "web_save" && args.model === "sale_order_line") {
const { product_id: selectedId } = args.args[1];
assert.strictEqual(selectedId, 111, `the product should be selected`);
}
if (args.method === "some_action") {
@ -148,4 +148,42 @@ QUnit.module("ViewDialogs", (hooks) => {
await click(target, ".o_form_button_save");
assert.verifySteps([]);
});
QUnit.test("SelectCreateDialog: default props, create a record", async function (assert) {
assert.expect(9);
serverData.views["product,false,form"] = `<form><field name="display_name"/></form>`;
await makeView({
type: "form",
resModel: "sale_order_line",
serverData,
arch: `
<form>
<field name="product_id"/>
<field name="linked_sale_order_line" widget="many2many_tags"/>
</form>`,
});
await click(target, '.o_field_widget[name="product_id"] input');
assert.containsOnce(target, ".o_dialog");
assert.containsOnce(
target,
".o_dialog .o_kanban_view .o_kanban_record:not(.o_kanban_ghost)"
);
assert.containsN(target, ".o_dialog footer button", 2);
assert.containsOnce(target, ".o_dialog footer button.o_create_button");
assert.containsOnce(target, ".o_dialog footer button.o_form_button_cancel");
assert.containsNone(target, ".o_dialog .o_control_panel_main_buttons .o-kanban-button-new");
await click(target.querySelector(".o_dialog footer button.o_create_button"));
assert.containsN(target, ".o_dialog", 2);
assert.containsOnce(target, ".o_dialog .o_form_view");
await editInput(target, ".o_dialog .o_form_view .o_field_widget input", "hello");
await click(target.querySelector(".o_dialog .o_form_button_save"));
assert.containsNone(target, ".o_dialog");
});
});

View file

@ -53,11 +53,11 @@ QUnit.module("Widgets", (hooks) => {
assert.expect(7);
patchWithCleanup(SignatureWidget.prototype, {
async onClickSignature() {
await this._super.apply(this, arguments);
await super.onClickSignature(...arguments);
assert.step("onClickSignature");
},
async uploadSignature({signatureImage}) {
await this._super.apply(this, arguments);
await super.uploadSignature(...arguments);
assert.step("uploadSignature");
},
});