@@ -235,7 +235,7 @@ QUnit.module("Form Compiler", (hooks) => {
const expected = /*xml*/ `
-
+
someDiv
@@ -298,7 +298,6 @@ QUnit.module("Form Renderer", (hooks) => {
resId: 1,
});
- await click(target.querySelector(".o_form_button_edit"));
assert.containsN(target, ".o_form_editable input", 2);
});
diff --git a/addons/web/static/tests/views/form/form_view_tests.js b/addons/web/static/tests/views/form/form_view_tests.js
index 41e0556dc4b..e79115f7a6a 100644
--- a/addons/web/static/tests/views/form/form_view_tests.js
+++ b/addons/web/static/tests/views/form/form_view_tests.js
@@ -5,7 +5,7 @@ import { makeFakeNotificationService } from "@web/../tests/helpers/mock_services
import {
addRow,
click,
- clickEdit,
+ clickDiscard,
clickSave,
dragAndDrop,
editInput,
@@ -273,7 +273,8 @@ QUnit.module("Views", (hooks) => {
"should keep the inline style on html elements"
);
assert.containsOnce(target, "label:contains(Foo)");
- assert.containsOnce(target, "span:contains(blip)");
+ assert.containsOnce(target, ".o_field_char input");
+ assert.strictEqual(target.querySelector(".o_field_char input").value, "blip");
assert.hasAttrValue(
target.querySelector(".o_group .o_group"),
"style",
@@ -518,8 +519,6 @@ QUnit.module("Views", (hooks) => {
resId: 6,
});
- await clickEdit(target);
-
assert.containsN(target, ".o_field_one2many", 2);
assert.doesNotHaveClass(
target.querySelectorAll(".o_field_one2many")[0],
@@ -657,7 +656,7 @@ QUnit.module("Views", (hooks) => {
resModel: "user",
serverData,
arch: `
-
`,
resId: 2,
});
- await click(target.querySelector(".o_form_button_edit"));
assert.doesNotHaveClass(
target.querySelector('.o_field_widget[name="display_name"]'),
"text-danger"
@@ -777,7 +775,6 @@ QUnit.module("Views", (hooks) => {
arch: `
`,
resId: 2,
});
- await click(target.querySelector(".o_form_button_edit"));
assert.doesNotHaveClass(
target.querySelector('.o_field_widget[name="int_field"]'),
"text-danger"
@@ -940,7 +937,7 @@ QUnit.module("Views", (hooks) => {
views: [[false, "form"]],
});
- await click(target.querySelector('.o_field_widget[name="product_id"] a'));
+ await click(target.querySelector('.o_field_widget[name="product_id"] .o_external_button'));
});
QUnit.test("invisible fields are properly hidden", async function (assert) {
@@ -1065,7 +1062,6 @@ QUnit.module("Views", (hooks) => {
`,
resId: 1,
});
- await click(target.querySelector(".o_form_button_edit"));
assert.containsOnce(target, ".o_field_widget[name=int_field]");
assert.containsNone(target, ".o_field_widget[name=timmy]");
@@ -1102,8 +1098,6 @@ QUnit.module("Views", (hooks) => {
});
assert.containsNone(target, ".o_notebook");
-
- await click(target.querySelector(".o_form_button_edit"));
await editInput(target, ".o_field_widget[name=int_field] input", 44);
assert.containsOnce(target, ".o_notebook");
@@ -1125,14 +1119,6 @@ QUnit.module("Views", (hooks) => {
resId: 1,
});
- // Does not change when switching state
- await click(target.querySelector(".o_form_button_edit"));
-
- assert.containsNone(target, ":scope .o_notebook .nav");
-
- // Does not change when coming back to initial state
- await click(target.querySelector(".o_form_button_save"));
-
assert.containsNone(target, ":scope .o_notebook .nav");
});
@@ -1181,18 +1167,6 @@ QUnit.module("Views", (hooks) => {
assert.containsNone(target, ".o_notebook_headers .nav-item");
assert.containsNone(target, ".tab-content .tab-pane");
-
- // Does not change when switching state
- await click(target.querySelector(".o_form_button_edit"));
-
- assert.containsNone(target, ".o_notebook_headers .nav-item");
- assert.containsNone(target, ".tab-content .tab-pane");
-
- // Does not change when coming back to initial state
- await click(target.querySelector(".o_form_button_save"));
-
- assert.containsNone(target, ".o_notebook_headers .nav-item");
- assert.containsNone(target, ".tab-content .tab-pane");
});
QUnit.test("notebook: pages with invisible modifiers", async function (assert) {
@@ -1220,8 +1194,6 @@ QUnit.module("Views", (hooks) => {
resId: 1,
});
- await click(target.querySelector(".o_form_button_edit"));
-
assert.containsN(target, ".o_notebook .nav-link", 2);
assert.containsOnce(target, ".o_notebook .nav .nav-link.active");
assert.hasClass(target.querySelector(".o_notebook .nav .nav-link"), "active");
@@ -1257,7 +1229,6 @@ QUnit.module("Views", (hooks) => {
resId: 1,
});
- await click(target.querySelector(".o_form_button_edit"));
assert.containsN(target, ".o_notebook .nav .nav-link", 2);
assert.hasClass(target.querySelector(".o_notebook .nav .nav-link"), "active");
assert.hasClass(target.querySelector(".o_notebook .tab-content .tab-pane"), "active");
@@ -1288,7 +1259,6 @@ QUnit.module("Views", (hooks) => {
resId: 1,
});
- await click(target.querySelector(".o_form_button_edit"));
assert.containsNone(target, ".o_notebook");
// enable checkbox
@@ -1522,8 +1492,6 @@ QUnit.module("Views", (hooks) => {
resId: 1,
});
- await click(target.querySelector(".o_form_button_edit"));
-
assert.containsOnce(target, "div.o_group");
await click(target.querySelector(".o_field_boolean input"));
assert.containsNone(target, "div.o_group");
@@ -2058,7 +2026,7 @@ QUnit.module("Views", (hooks) => {
`,
});
- await click(target.querySelector(".o_form_button_save"));
+ await clickSave(target);
assert.containsN(target, ".o_form_label.o_field_invalid", 2);
assert.containsN(target, ".o_field_many2one.o_field_invalid", 2);
@@ -2139,7 +2107,6 @@ QUnit.module("Views", (hooks) => {
`,
resId: 1,
});
- await click(target.querySelector(".o_form_button_edit"));
assert.containsOnce(
target,
@@ -2186,11 +2153,12 @@ QUnit.module("Views", (hooks) => {
);
await editInput(target, ".o_field_widget[name=int_field] input", "34");
- await click(target.querySelector(".o_form_button_save"));
- assert.containsOnce(target, ".o_form_readonly");
- assert.strictEqual(target.querySelector(".o_field_widget[name=int_field]").innerText, "34");
+ await clickSave(target);
+ assert.strictEqual(
+ target.querySelector(".o_field_widget[name=int_field]").textContent,
+ "34"
+ );
- await click(target.querySelector(".o_form_button_edit"));
assert.containsOnce(target, ".o_form_editable");
assert.containsNone(target, ".o_field_widget[name=int_field] input");
assert.hasClass(
@@ -2237,7 +2205,6 @@ QUnit.module("Views", (hooks) => {
`,
resId: 1,
});
- await click(target.querySelector(".o_form_button_edit"));
let m2oName = "first record";
for (const value of [true, false, true, false]) {
@@ -2287,21 +2254,6 @@ QUnit.module("Views", (hooks) => {
resId: 2,
});
- assert.containsN(
- target,
- ".o_field_widget.o_field_empty",
- 2,
- "should have 2 empty fields with correct class"
- );
- assert.containsN(
- target,
- ".o_form_label_empty",
- 2,
- "should have 2 muted labels (for the empty fieds) in readonly"
- );
-
- await click(target.querySelector(".o_form_button_edit"));
-
assert.containsOnce(
target,
".o_field_empty",
@@ -2361,16 +2313,6 @@ QUnit.module("Views", (hooks) => {
resId: 2,
});
- assert.containsN(target, ".o_field_widget.o_field_empty", 2);
- assert.containsN(
- target,
- ".o_form_label_empty",
- 2,
- "should have 1 muted label (for the empty fied) in readonly"
- );
-
- await click(target.querySelector(".o_form_button_edit"));
-
assert.containsNone(
target,
".o_field_empty",
@@ -2455,11 +2397,6 @@ QUnit.module("Views", (hooks) => {
resId: 2,
});
- assert.containsN(target, ".o_field_widget.o_field_empty", 2);
- assert.containsN(target, ".o_form_label_empty", 2);
-
- await clickEdit(target);
-
assert.containsOnce(target, ".o_field_empty");
assert.containsOnce(target, ".o_form_label_empty");
@@ -2475,27 +2412,6 @@ QUnit.module("Views", (hooks) => {
}
);
- QUnit.test("form view can switch to edit mode", async function (assert) {
- await makeView({
- type: "form",
- resModel: "partner",
- serverData,
- arch: '
',
- resId: 1,
- });
-
- assert.containsOnce(target, ".o_form_readonly");
- assert.isVisible(target.querySelector(".o_form_buttons_view"));
- assert.isNotVisible(target.querySelector(".o_form_buttons_edit"));
-
- await click(target.querySelector(".o_form_button_edit"));
-
- assert.containsOnce(target, ".o_form_editable");
- assert.containsNone(target, ".o_form_readonly");
- assert.isNotVisible(target.querySelector(".o_form_buttons_view"));
- assert.isVisible(target.querySelector(".o_form_buttons_edit"));
- });
-
QUnit.test(
"required attrs on fields are re-evaluated on field change",
async function (assert) {
@@ -2514,7 +2430,6 @@ QUnit.module("Views", (hooks) => {
`,
resId: 1,
});
- await click(target.querySelector(".o_form_button_edit"));
assert.containsOnce(
target,
@@ -2552,10 +2467,6 @@ QUnit.module("Views", (hooks) => {
`,
resId: 1,
});
-
- assert.containsOnce(target, ".o_field_widget.o_required_modifier");
-
- await click(target.querySelector(".o_form_button_edit"));
assert.containsOnce(target, ".o_field_widget.o_required_modifier");
});
@@ -2585,21 +2496,10 @@ QUnit.module("Views", (hooks) => {
"qux input is 0 by default (float field)"
);
- await click(target.querySelector(".o_form_button_save"));
-
- assert.containsNone(
- target,
- '.o_field_widget[name="qux"] input',
- "should have switched to readonly"
- );
-
- await click(target.querySelector(".o_form_button_edit"));
+ await clickSave(target);
await editInput(target, ".o_field_widget[name=qux] input", "1");
-
- await click(target.querySelector(".o_form_button_save"));
-
- await click(target.querySelector(".o_form_button_edit"));
+ await clickSave(target);
assert.strictEqual(
target.querySelector('.o_field_widget[name="qux"] input').value,
@@ -2907,10 +2807,10 @@ QUnit.module("Views", (hooks) => {
assert.verifySteps(["read1", "willStart"]);
await click(target.querySelector(".o_form_statusbar button.p"));
- assert.verifySteps(["willUpdateProps", "read2", "willUpdateProps"]);
+ assert.verifySteps(["read2", "willUpdateProps", "willUpdateProps"]);
await click(target.querySelector(".o_form_statusbar button.p"));
- assert.verifySteps(["willUpdateProps", "read3", "willUpdateProps"]);
+ assert.verifySteps(["willUpdateProps", "read3", "willUpdateProps", "willUpdateProps"]);
});
QUnit.test("buttons in form view, new record", async function (assert) {
@@ -3037,14 +2937,14 @@ QUnit.module("Views", (hooks) => {
resId: 2,
});
- assert.containsOnce(target, ".o_form_readonly button[data-hotkey=v]");
+ assert.containsOnce(target, ".o_form_view button[data-hotkey=v]");
triggerHotkey("alt+v");
await nextTick();
assert.verifySteps(["validate"]);
});
QUnit.test("change and save char", async function (assert) {
- assert.expect(6);
+ assert.expect(3);
await makeView({
type: "form",
@@ -3054,26 +2954,15 @@ QUnit.module("Views", (hooks) => {
mockRPC(route, args) {
if (args.method === "write") {
assert.ok(true, "should call the /write route");
+ assert.strictEqual(args.args[1].foo, "tralala");
}
},
resId: 2,
});
- assert.containsOnce(target, ".o_form_readonly", "form view should be in readonly mode");
- assert.containsOnce(target, "span:contains(blip)", "should contain span with field value");
-
- await click(target.querySelector(".o_form_button_edit"));
-
assert.containsOnce(target, ".o_form_editable", "form view should be in edit mode");
await editInput(target, ".o_field_widget[name=foo] input", "tralala");
- await click(target.querySelector(".o_form_button_save"));
-
- assert.containsOnce(target, ".o_form_readonly", "form view should be in readonly mode");
- assert.containsOnce(
- target,
- "span:contains(tralala)",
- "should contain span with field value"
- );
+ await clickSave(target);
});
QUnit.test("properly reload data from server", async function (assert) {
@@ -3090,10 +2979,9 @@ QUnit.module("Views", (hooks) => {
resId: 2,
});
- await click(target.querySelector(".o_form_button_edit"));
await editInput(target, ".o_field_widget[name=foo] input", "tralala");
- await click(target.querySelector(".o_form_button_save"));
- assert.containsOnce(target, "span:contains(apple)", "should contain span with field value");
+ await clickSave(target);
+ assert.strictEqual(target.querySelector(".o_field_widget[name=foo] input").value, "apple");
});
QUnit.test("disable buttons until reload data from server", async function (assert) {
@@ -3115,18 +3003,19 @@ QUnit.module("Views", (hooks) => {
});
def = makeDeferred();
- await click(target.querySelector(".o_form_button_edit"));
await editInput(target, ".o_field_widget[name=foo] input", "tralala");
- await click(target.querySelector(".o_form_button_save"));
+ await clickSave(target);
// Save button should be disabled
assert.hasAttrValue(target.querySelector(".o_form_button_save"), "disabled", "disabled");
+ assert.hasAttrValue(target.querySelector(".o_form_button_cancel"), "disabled", "disabled");
// Release the 'read' call
def.resolve();
await nextTick();
- // Edit button should be enabled after the reload
- assert.hasAttrValue(target.querySelector(".o_form_button_edit"), "disabled", undefined);
+ // Save button should be enabled after the reload
+ assert.hasAttrValue(target.querySelector(".o_form_button_save"), "disabled", undefined);
+ assert.hasAttrValue(target.querySelector(".o_form_button_cancel"), "disabled", undefined);
});
QUnit.test("properly apply onchange in simple case", async function (assert) {
@@ -3143,8 +3032,6 @@ QUnit.module("Views", (hooks) => {
resId: 2,
});
- await click(target.querySelector(".o_form_button_edit"));
-
assert.strictEqual(
target.querySelector(".o_field_widget[name=int_field] input").value,
"9",
@@ -3176,8 +3063,6 @@ QUnit.module("Views", (hooks) => {
resId: 2,
});
- await click(target.querySelector(".o_form_button_edit"));
-
assert.strictEqual(
target.querySelector(".o_field_widget[name=int_field] input").value,
"9",
@@ -3192,10 +3077,10 @@ QUnit.module("Views", (hooks) => {
"value should have been set to 14 by onchange"
);
- await click(target.querySelector(".o_form_button_save"));
+ await clickSave(target);
assert.strictEqual(
- target.querySelector(".o_field_widget[name=int_field]").textContent,
+ target.querySelector(".o_field_widget[name=int_field] input").value,
"14",
"value should still be 14"
);
@@ -3246,7 +3131,6 @@ QUnit.module("Views", (hooks) => {
},
});
- await click(target.querySelector(".o_form_button_edit"));
await editInput(target, ".o_field_widget[name=foo] input", "tralala");
});
@@ -3294,8 +3178,6 @@ QUnit.module("Views", (hooks) => {
},
});
- await click(target.querySelector(".o_form_button_edit"));
-
// add a o2m row
await click(target.querySelector(".o_field_x2many_list_row_add a"));
await editInput(
@@ -3368,10 +3250,13 @@ QUnit.module("Views", (hooks) => {
await click(target.querySelector(".o_form_button_create"));
assert.containsOnce(target, ".o_form_editable");
- assert.strictEqual(target.querySelector("input").value, "My little Foo Value");
+ assert.strictEqual(
+ target.querySelector(".o_field_char input").value,
+ "My little Foo Value"
+ );
- await click(target.querySelector(".o_form_button_save"));
- assert.containsOnce(target, ".o_form_readonly");
+ await clickSave(target);
+ assert.containsOnce(target, ".o_form_editable");
assert.strictEqual(serverData.models.partner.records.length, n + 1);
});
@@ -3465,7 +3350,7 @@ QUnit.module("Views", (hooks) => {
-
+
`,
@@ -3477,7 +3362,6 @@ QUnit.module("Views", (hooks) => {
resId: 17,
});
// current form
- await click(target.querySelector(".o_form_button_edit"));
// open the modal form view of the record pointed by the reference field
await click(target.querySelector('table td[data-tooltip="first record"]'));
@@ -3498,7 +3382,7 @@ QUnit.module("Views", (hooks) => {
);
});
- QUnit.test("there is no Actions menu when creating a new record", async function (assert) {
+ QUnit.test("there is an Actions menu when creating a new record", async function (assert) {
await makeView({
type: "form",
resModel: "partner",
@@ -3512,9 +3396,9 @@ QUnit.module("Views", (hooks) => {
await click(target.querySelector(".o_form_button_create"));
- assert.containsNone(target, ".o_cp_action_menus");
+ assert.containsOnce(target, ".o_cp_action_menus");
- await click(target.querySelector(".o_form_button_save"));
+ await clickSave(target);
assert.containsOnce(target, ".o_cp_action_menus");
});
@@ -3816,8 +3700,6 @@ QUnit.module("Views", (hooks) => {
},
});
- await click(target.querySelector(".o_form_button_edit"));
-
await click(target.querySelector(".oe_stat_button"));
assert.strictEqual(count, 1, "should have triggered a execute action");
assert.containsOnce(target, ".o_form_editable", "form view should be in edit mode");
@@ -3872,7 +3754,6 @@ QUnit.module("Views", (hooks) => {
"second record",
"should have correct display_name"
);
- await click(target.querySelector(".o_form_button_edit"));
await editInput(target, ".o_field_widget[name=name] input", "some other name");
await click(target.querySelector(".oe_stat_button"));
@@ -3915,8 +3796,6 @@ QUnit.module("Views", (hooks) => {
},
});
- await click(target.querySelector(".o_form_button_edit"));
-
// make the record dirty
await editInput(target, ".o_field_widget[name=foo] input", "tralala");
await click(target.querySelector(".o_content button.btn-primary"));
@@ -3957,7 +3836,6 @@ QUnit.module("Views", (hooks) => {
},
});
- await click(target.querySelector(".o_form_button_edit"));
await editInput(target, ".o_field_widget[name=foo] input", "tralala");
await click(target.querySelector(".o_content button.btn-primary"));
assert.verifySteps(["get_views", "read", "write", "read", "execute_action"]);
@@ -4119,8 +3997,6 @@ QUnit.module("Views", (hooks) => {
},
});
- // switch to edit mode
- await click(target.querySelector(".o_form_button_edit"));
assert.strictEqual(
target.querySelector(".o_field_widget[name=foo] input").value,
"yop",
@@ -4128,12 +4004,12 @@ QUnit.module("Views", (hooks) => {
);
// click on discard
- await click(target.querySelector(".o_form_button_cancel"));
+ await clickDiscard(target);
assert.containsNone(document.body, ".modal", "no confirm modal should be displayed");
assert.strictEqual(
- target.querySelector(".o_field_widget").textContent,
+ target.querySelector(".o_field_widget[name=foo] input").value,
"yop",
- "field in readonly should display yop"
+ "field should display yop"
);
assert.strictEqual(nbWrite, 0, "no write RPC should have been done");
@@ -4154,8 +4030,7 @@ QUnit.module("Views", (hooks) => {
},
});
- // switch to edit mode and edit the foo field
- await click(target.querySelector(".o_form_button_edit"));
+ // edit the foo field
assert.strictEqual(
target.querySelector(".o_field_widget[name=foo] input").value,
"yop",
@@ -4169,12 +4044,12 @@ QUnit.module("Views", (hooks) => {
);
// click on discard
- await click(target.querySelector(".o_form_button_cancel"));
+ await clickDiscard(target);
assert.containsNone(document.body, ".modal", "no confirm modal should be displayed");
assert.strictEqual(
- target.querySelector(".o_field_widget").textContent,
+ target.querySelector(".o_field_widget input").value,
"yop",
- "field in readonly should display yop"
+ "field should display yop"
);
assert.strictEqual(nbWrite, 0, "no write RPC should have been done");
@@ -4199,11 +4074,11 @@ QUnit.module("Views", (hooks) => {
// event to properly focusout the input, otherwise it crashes later on
// when the 'blur' event is triggered by the re-rendering)
target.querySelector(".o_form_button_cancel").focus();
- await click(target.querySelector(".o_form_button_cancel"));
+ await clickDiscard(target);
target.querySelector(".o_form_button_save").focus();
- await click(target.querySelector(".o_form_button_save"));
- assert.containsOnce(target, "span:contains(2017)");
+ await clickSave(target);
+ assert.strictEqual(target.querySelector(".o_field_widget input").value, "01/25/2017");
});
QUnit.test("discard changes on relational data on new record", async function (assert) {
@@ -4232,7 +4107,7 @@ QUnit.module("Views", (hooks) => {
);
// click on discard
- await click(target.querySelector(".o_form_button_cancel"));
+ await clickDiscard(target);
assert.containsNone(target, ".modal", "modal should not be displayed");
assert.strictEqual(
target.querySelector(".o_field_widget[name=product_id] input").value,
@@ -4264,7 +4139,7 @@ QUnit.module("Views", (hooks) => {
"input should contain ABC"
);
- await click(target.querySelector(".o_form_button_cancel"));
+ await clickDiscard(target);
assert.containsNone(document.body, ".modal", "there should not be a confirm modal");
assert.verifySteps(["history-back"]);
@@ -4304,7 +4179,7 @@ QUnit.module("Views", (hooks) => {
"DEF",
"input should be DEF"
);
- await click(target.querySelector(".o_form_button_cancel"));
+ await clickDiscard(target);
assert.strictEqual(
target.querySelector(".o_field_widget[name=foo] input").value,
"ABC",
@@ -4319,7 +4194,7 @@ QUnit.module("Views", (hooks) => {
"GHI",
"input should be GHI"
);
- await click(target.querySelector(".o_form_button_cancel"));
+ await clickDiscard(target);
assert.strictEqual(
target.querySelector(".o_field_widget[name=foo] input").value,
"ABC",
@@ -4337,9 +4212,8 @@ QUnit.module("Views", (hooks) => {
resId: 1,
actionMenus: {},
});
- await click(target.querySelector(".o_form_button_edit"));
await editInput(target, ".o_field_widget[name=foo] input", "tralala");
- await click(target.querySelector(".o_form_button_save"));
+ await clickSave(target);
await toggleActionMenu(target);
await toggleMenuItem(target, "Duplicate");
@@ -4350,7 +4224,7 @@ QUnit.module("Views", (hooks) => {
"input should contain tralala"
);
- await click(target.querySelector(".o_form_button_cancel"));
+ await clickDiscard(target);
assert.containsNone(document.body, ".modal", "there should not be a confirm modal");
});
@@ -4400,7 +4274,6 @@ QUnit.module("Views", (hooks) => {
`,
resId: 1,
});
- await click(target.querySelector(".o_form_button_edit"));
assert.containsOnce(
target,
".o_statusbar_status button",
@@ -4413,7 +4286,7 @@ QUnit.module("Views", (hooks) => {
2,
"Must have only two statusbar buttons"
);
- await click(target.querySelector(".o_form_button_cancel"));
+ await clickDiscard(target);
assert.containsOnce(
target,
".o_statusbar_status button",
@@ -4450,8 +4323,6 @@ QUnit.module("Views", (hooks) => {
"pager limit should be 2"
);
- // switch to edit mode
- await click(target.querySelector(".o_form_button_edit"));
assert.strictEqual(
target.querySelector(".o_field_widget[name=foo] input").value,
"yop",
@@ -4519,7 +4390,6 @@ QUnit.module("Views", (hooks) => {
assert.strictEqual(target.querySelector(".o_pager_value").textContent, "1");
assert.strictEqual(target.querySelector(".o_pager_limit").textContent, "2");
- await click(target.querySelector(".o_form_button_edit"));
await editInput(target, ".o_field_widget[name=foo] input", "");
await click(target.querySelector(".o_pager_next"));
assert.strictEqual(target.querySelector(".breadcrumb").innerText, "first record");
@@ -4549,7 +4419,6 @@ QUnit.module("Views", (hooks) => {
assert.strictEqual(target.querySelector(".o_pager_value").textContent, "1");
assert.strictEqual(target.querySelector(".o_pager_limit").textContent, "2");
- await click(target.querySelector(".o_form_button_edit"));
await editInput(target, ".o_field_widget[name=foo] input", "");
triggerHotkey("alt+n");
await nextTick();
@@ -4590,15 +4459,6 @@ QUnit.module("Views", (hooks) => {
assert.strictEqual(target.querySelector(".breadcrumb").innerText, "first record");
assert.hasClass(target.querySelector(".o_field_widget[name=foo]"), "o_required_modifier");
assert.strictEqual(target.querySelector(".o_pager_value").textContent, "1");
-
- // same, but in edit mode
- await click(target.querySelector(".o_form_button_edit"));
- assert.containsOnce(target, ".o_form_editable");
-
- await click(target.querySelector(".o_pager_next"));
- assert.containsOnce(target, ".o_form_editable");
- assert.strictEqual(target.querySelector(".breadcrumb").innerText, "second record");
- assert.strictEqual(target.querySelector(".o_pager_value").textContent, "2");
});
QUnit.test("keynav: switching to another record from a dirty one", async function (assert) {
@@ -4628,8 +4488,6 @@ QUnit.module("Views", (hooks) => {
"pager limit should be 2"
);
- // switch to edit mode
- await click(target.querySelector(".o_form_button_edit"));
assert.strictEqual(
target.querySelector(".o_field_widget[name=foo] input").value,
"yop",
@@ -4693,8 +4551,6 @@ QUnit.module("Views", (hooks) => {
"pager value should be 1"
);
- // switch to edit mode
- await click(target.querySelector(".o_form_button_edit"));
assert.strictEqual(
target.querySelector(".o_field_widget[name=foo] input").value,
"yop",
@@ -4709,7 +4565,7 @@ QUnit.module("Views", (hooks) => {
"input should contain new value"
);
- await click(target.querySelector(".o_form_button_save"));
+ await clickSave(target);
// click on the pager to switch to the next record and cancel the confirm request
await click(target.querySelector(".o_pager_next"));
@@ -4747,8 +4603,6 @@ QUnit.module("Views", (hooks) => {
"pager value should be 1"
);
- // switch to edit mode
- await click(target.querySelector(".o_form_button_edit"));
assert.strictEqual(
target.querySelector(".o_field_widget[name=foo] input").value,
"new value",
@@ -4758,7 +4612,7 @@ QUnit.module("Views", (hooks) => {
// edit the foo field
await editInput(target, ".o_field_widget[name=foo] input", "wrong value");
- await click(target.querySelector(".o_form_button_cancel"));
+ await clickDiscard(target);
assert.containsNone(document.body, ".modal", "no confirm modal should be displayed");
await click(target.querySelector(".o_pager_next"));
assert.strictEqual(
@@ -4819,14 +4673,14 @@ QUnit.module("Views", (hooks) => {
assert.containsNone(target, ".o_pager");
- await click(target.querySelector(".o_form_button_save"));
+ await clickSave(target);
assert.containsOnce(target, ".o_pager");
assert.strictEqual(target.querySelector(".o_pager_value").textContent, "3");
assert.strictEqual(target.querySelector(".o_pager_limit").textContent, "3");
});
- QUnit.test("switching to another record, in readonly mode", async function (assert) {
+ QUnit.test("switching to another record", async function (assert) {
patchWithCleanup(browser, {
setTimeout(fn) {
return fn(); // update the router hash directly
@@ -4841,13 +4695,11 @@ QUnit.module("Views", (hooks) => {
resIds: [1, 2],
});
- assert.containsOnce(target, ".o_form_readonly");
assert.strictEqual(target.querySelector(".o_pager_value").textContent, "1");
assert.strictEqual(form.env.services.router.current.hash.id, 1);
await click(target.querySelector(".o_pager_next"));
assert.strictEqual(target.querySelector(".o_pager_value").textContent, "2");
- assert.containsOnce(target, ".o_form_readonly");
assert.strictEqual(form.env.services.router.current.hash.id, 2);
});
@@ -4946,9 +4798,9 @@ QUnit.module("Views", (hooks) => {
assert.strictEqual(target.querySelector(".o_pager_value").textContent, "1");
assert.strictEqual(target.querySelector(".o_pager_limit").textContent, "2");
- assert.containsOnce(
- target,
- ".o_field_widget[name=foo]:contains(blip)",
+ assert.strictEqual(
+ target.querySelector(".o_field_widget[name=foo] input").value,
+ "blip",
"should have a field with foo value for record 2"
);
});
@@ -4993,7 +4845,7 @@ QUnit.module("Views", (hooks) => {
arch: "
",
});
- await click(target.querySelector(".o_form_button_save"));
+ await clickSave(target);
assert.hasClass(target.querySelector("label.o_form_label"), "o_field_invalid");
assert.hasClass(target.querySelector(".o_field_widget[name=foo]"), "o_field_invalid");
assert.containsOnce(target, ".o_notification");
@@ -5011,82 +4863,6 @@ QUnit.module("Views", (hooks) => {
assert.containsNone(target, ".o_field_invalid");
});
- QUnit.test("changes in a readonly form view are saved directly", async function (assert) {
- let nbWrite = 0;
- await makeView({
- type: "form",
- resModel: "partner",
- serverData,
- arch: `
-
`,
- mockRPC(route) {
- if (route === "/web/dataset/call_kw/partner/write") {
- nbWrite++;
- }
- },
- resId: 1,
- });
-
- assert.containsN(
- target,
- ".o_priority .o_priority_star",
- 2,
- "priority widget should have been rendered"
- );
- assert.containsN(
- target,
- ".o_priority .fa-star-o",
- 2,
- "priority widget should have been rendered with correct value"
- );
-
- // edit the value in readonly
- await click(target.querySelector(".o_priority .fa-star-o"));
- assert.strictEqual(nbWrite, 1, "should have saved directly");
- assert.containsOnce(
- target,
- ".o_priority .fa-star",
- "priority widget should have been updated"
- );
-
- // switch to edit mode and edit the value again
- await click(target.querySelector(".o_form_button_edit"));
- assert.containsN(
- target,
- ".o_priority .o_priority_star",
- 2,
- "priority widget should have been correctly rendered"
- );
- assert.containsOnce(
- target,
- ".o_priority .fa-star",
- "priority widget should have correct value"
- );
- await click(target.querySelector(".o_priority .fa-star-o"));
- assert.strictEqual(nbWrite, 1, "should not have saved directly");
- assert.containsN(
- target,
- ".o_priority .fa-star",
- 2,
- "priority widget should have been updated"
- );
-
- // save
- await click(target.querySelector(".o_form_button_save"));
- assert.strictEqual(nbWrite, 2, "should not have saved directly");
- assert.containsN(
- target,
- ".o_priority .fa-star",
- 2,
- "priority widget should have correct value"
- );
- });
-
QUnit.test("display a dialog if onchange result is a warning", async function (assert) {
serverData.models.partner.onchanges = { foo: true };
@@ -5110,8 +4886,6 @@ QUnit.module("Views", (hooks) => {
},
});
- await click(target.querySelector(".o_form_button_edit"));
-
assert.strictEqual(
target.querySelector(".o_field_widget[name=int_field] input").value,
"9"
@@ -5158,8 +4932,6 @@ QUnit.module("Views", (hooks) => {
},
});
- await click(target.querySelector(".o_form_button_edit"));
-
assert.strictEqual(
target.querySelector(".o_field_widget[name=int_field] input").value,
"9"
@@ -5244,15 +5016,14 @@ QUnit.module("Views", (hooks) => {
},
});
- // go to edit mode, click to add a record in the o2m
- await click(target.querySelector(".o_form_button_edit"));
+ // click to add a record in the o2m
await click(target.querySelector(".o_field_x2many_list_row_add a"));
assert.containsNone(target, "tr.o_data_row", "should not have added a line");
assert.containsOnce(target, ".o_notification .text-warning");
}
);
- QUnit.test("button box is rendered in create mode", async function (assert) {
+ QUnit.skip("button box is rendered in create mode", async function (assert) {
await makeView({
type: "form",
resModel: "partner",
@@ -5268,16 +5039,6 @@ QUnit.module("Views", (hooks) => {
resId: 2,
});
- // readonly mode
- assert.containsOnce(
- target,
- ".oe_stat_button",
- "button box should be displayed in readonly"
- );
-
- // edit mode
- await click(target.querySelector(".o_form_button_edit"));
-
assert.containsOnce(
target,
".oe_stat_button",
@@ -5285,7 +5046,7 @@ QUnit.module("Views", (hooks) => {
);
// create mode (leave edition first!)
- await click(target.querySelector(".o_form_button_cancel"));
+ await clickDiscard(target);
await click(target.querySelector(".o_form_button_create"));
assert.containsOnce(
target,
@@ -5330,8 +5091,6 @@ QUnit.module("Views", (hooks) => {
"the 'display_name' of the one2many record should be correct"
);
- // switch to edit mode
- await click(target.querySelector(".o_form_button_edit"));
await editInput(target, ".o_field_widget[name=foo] input", "let us trigger an onchange");
assert.containsN(target, ".o_data_row", 2, "there should be two linked record");
assert.strictEqual(
@@ -5390,7 +5149,6 @@ QUnit.module("Views", (hooks) => {
},
});
- await click(target.querySelector(".o_form_button_edit"));
// Trigger the onchange
await editInput(target, ".o_field_widget[name=int_field] input", "2");
// Open first record in one2many
@@ -5445,7 +5203,6 @@ QUnit.module("Views", (hooks) => {
["aaa", "No records"],
"should have proper initial content"
);
- await click(target.querySelector(".o_form_button_edit"));
await editInput(target, ".o_field_widget[name=foo] input", "tralala");
@@ -5474,7 +5231,6 @@ QUnit.module("Views", (hooks) => {
resId: 1,
});
- await click(target.querySelector(".o_form_button_edit"));
await click(target.querySelector(".o_data_cell"));
await editInput(target, ".o_field_widget[name=display_name] input", "");
await click(target.querySelectorAll(".fa-trash-o")[1]);
@@ -5528,8 +5284,6 @@ QUnit.module("Views", (hooks) => {
"there should be no many2many record linked at first"
);
- // switch to edit mode
- await click(target.querySelector(".o_form_button_edit"));
await editInput(target, ".o_field_widget[name=foo] input", "let us trigger an onchange");
assert.containsN(target, ".o_data_row", 2, "there should be two linked records");
assert.strictEqual(
@@ -5543,7 +5297,7 @@ QUnit.module("Views", (hooks) => {
"the 'display_name' of the second m2m record should be correctly displayed"
);
- await click(target.querySelector(".o_form_button_save"));
+ await clickSave(target);
assert.verifySteps(["get_views", "read", "onchange", "read", "write", "read", "read"]);
});
@@ -5577,9 +5331,6 @@ QUnit.module("Views", (hooks) => {
resId: 1,
});
- // switch to edit mode
- await click(target.querySelector(".o_form_button_edit"));
-
// open a form view and save many2many record
await click(target.querySelector(".o_data_row .o_data_cell"));
await click(target.querySelector(".modal-dialog footer .btn-primary"));
@@ -5681,8 +5432,6 @@ QUnit.module("Views", (hooks) => {
resId: 1,
});
- await click(target.querySelector(".o_form_button_edit"));
-
// trigger the onchange
await editInput(target, ".o_field_widget[name=foo] input", "coucou");
@@ -5714,17 +5463,6 @@ QUnit.module("Views", (hooks) => {
resId: 1,
});
- assert.strictEqual(
- target.querySelector(".o_field_widget[name=date]").textContent,
- "01/25/2017"
- );
- assert.strictEqual(
- target.querySelector(".o_field_widget[name=datetime]").textContent,
- "12/12/2016 12:55:05"
- );
-
- await click(target.querySelector(".o_form_button_edit"));
-
assert.strictEqual(
target.querySelector(".o_field_widget[name=date] input").value,
"01/25/2017"
@@ -5764,8 +5502,6 @@ QUnit.module("Views", (hooks) => {
},
});
- await click(target.querySelector(".o_form_button_edit"));
-
// edit int_field, and check that an onchange has been applied
await editInput(target, '.o_field_widget[name="int_field"] input', "123");
assert.strictEqual(
@@ -5784,7 +5520,7 @@ QUnit.module("Views", (hooks) => {
);
// save, and check that the int_field input is marked as invalid
- await click(target.querySelector(".o_form_button_save"));
+ await clickSave(target);
assert.hasClass(
target.querySelector('.o_field_widget[name="int_field"]'),
"o_field_invalid",
@@ -5869,19 +5605,17 @@ QUnit.module("Views", (hooks) => {
});
assert.strictEqual(
- target.querySelector('.o_field_widget[name="foo"]').textContent,
+ target.querySelector('.o_field_widget[name="foo"] input').value,
"blip",
"field foo should be displayed to initial value"
);
- await click(target.querySelector(".o_form_button_edit"));
-
// edit a field and discard
await editInput(target, ".o_field_widget[name=foo] input", "1234");
- await click(target.querySelector(".o_form_button_cancel"));
+ await clickDiscard(target);
assert.containsNone(target, ".modal");
assert.strictEqual(
- target.querySelector('.o_field_widget[name="foo"]').textContent,
+ target.querySelector('.o_field_widget[name="foo"] input').value,
"blip",
"field foo should still be displayed to initial value"
);
@@ -5890,7 +5624,7 @@ QUnit.module("Views", (hooks) => {
def.resolve();
await nextTick();
assert.strictEqual(
- target.querySelector('.o_field_widget[name="foo"]').textContent,
+ target.querySelector('.o_field_widget[name="foo"] input').value,
"blip",
"field foo should still be displayed to initial value"
);
@@ -5920,13 +5654,11 @@ QUnit.module("Views", (hooks) => {
},
});
- await click(target.querySelector(".o_form_button_edit"));
assert.containsOnce(target, ".o_form_view .o_form_editable");
-
await editInput(target, ".o_field_widget[name=foo] input", "1234");
// save the value and discard directly
- await click(target.querySelector(".o_form_button_save"));
+ await clickSave(target);
assert.ok(target.querySelector(".o_form_button_cancel").disabled);
// with form view extensions, it may happen that someone tries to discard
// while there is a pending save, so we simulate this here
@@ -5945,9 +5677,8 @@ QUnit.module("Views", (hooks) => {
def.resolve();
await nextTick();
assert.containsNone(target, ".modal", "Confirm dialog should not be displayed");
- assert.containsOnce(target, ".o_form_view .o_form_readonly");
assert.strictEqual(
- target.querySelector('.o_field_widget[name="foo"]').textContent,
+ target.querySelector('.o_field_widget[name="foo"] input').value,
"1234",
"value should have been saved and rerendered in readonly"
);
@@ -5988,8 +5719,6 @@ QUnit.module("Views", (hooks) => {
}
},
});
-
- await click(target.querySelector(".o_form_button_edit"));
await editInput(target, ".o_field_widget[name=foo] input", "trigger an onchange");
});
@@ -6060,7 +5789,6 @@ QUnit.module("Views", (hooks) => {
},
});
- await click(target.querySelector(".o_form_button_edit"));
await editInput(target, ".o_field_widget[name=foo] input", "trigger an onchange");
assert.strictEqual(
@@ -6069,7 +5797,7 @@ QUnit.module("Views", (hooks) => {
"onchange should have been correctly applied on field in o2m list"
);
- await click(target.querySelector(".o_form_button_save"));
+ await clickSave(target);
});
QUnit.test("onchange value are not discarded on o2m edition", async function (assert) {
@@ -6125,8 +5853,6 @@ QUnit.module("Views", (hooks) => {
},
});
- await click(target.querySelector(".o_form_button_edit"));
-
assert.strictEqual(
target.querySelector(".o_data_row td").textContent,
"My little Foo Value",
@@ -6182,8 +5908,6 @@ QUnit.module("Views", (hooks) => {
resId: 2,
});
- await click(target.querySelector(".o_form_button_edit"));
-
assert.strictEqual(
target.querySelector(".o_data_row td").textContent,
"My little Foo Value",
@@ -6240,8 +5964,6 @@ QUnit.module("Views", (hooks) => {
resId: 2,
});
- await click(target.querySelector(".o_form_button_edit"));
-
assert.strictEqual(
target.querySelector(".o_data_row td").textContent,
"My little Foo Value",
@@ -6316,8 +6038,6 @@ QUnit.module("Views", (hooks) => {
},
resId: 2,
});
-
- await click(target.querySelector(".o_form_button_edit"));
await editInput(target, ".o_field_widget[name=foo] input", "coucou");
}
);
@@ -6647,7 +6367,7 @@ QUnit.module("Views", (hooks) => {
}
},
});
- await click(target.querySelector(".o_form_button_save"));
+ await clickSave(target);
});
QUnit.test("many2manys inside one2manys are saved correctly", async function (assert) {
@@ -6688,7 +6408,7 @@ QUnit.module("Views", (hooks) => {
// add a o2m subrecord with a m2m tag
await click(target.querySelector(".o_field_x2many_list_row_add a"));
await selectDropdownItem(target, "timmy", "gold");
- await click(target.querySelector(".o_form_button_save"));
+ await clickSave(target);
});
QUnit.test(
@@ -6750,160 +6470,10 @@ QUnit.module("Views", (hooks) => {
"the cell should contains the number of record: 1"
);
- await click(target.querySelector(".o_form_button_save"));
+ await clickSave(target);
}
);
- QUnit.test(
- "oe_read_only and oe_edit_only classNames on fields inside groups",
- async function (assert) {
- await makeView({
- type: "form",
- resModel: "partner",
- serverData,
- arch: `
-
`,
- resId: 1,
- });
-
- assert.containsOnce(
- target,
- ".o_form_view .o_form_readonly",
- "form should be in readonly mode"
- );
- assert.isVisible(target.querySelector(".o_field_widget[name=foo]"));
- assert.isVisible(target.querySelector(".o_form_label"));
- assert.isNotVisible(target.querySelector(".o_field_widget[name=bar]"));
- assert.isNotVisible(target.querySelectorAll(".o_form_label")[1]);
-
- await click(target.querySelector(".o_form_button_edit"));
- assert.containsOnce(
- target,
- ".o_form_view .o_form_editable",
- "form should be in readonly mode"
- );
- assert.isNotVisible(target.querySelector(".o_field_widget[name=foo]"));
- assert.isNotVisible(target.querySelector(".o_form_label"));
- assert.isVisible(target.querySelector(".o_field_widget[name=bar]"));
- assert.isVisible(target.querySelectorAll(".o_form_label")[1]);
- }
- );
-
- QUnit.test("oe_read_only className is handled in list views", async function (assert) {
- await makeView({
- type: "form",
- resModel: "partner",
- serverData,
- arch: `
-
`,
- resId: 1,
- });
-
- assert.containsOnce(
- target,
- ".o_form_view .o_form_readonly",
- "form should be in readonly mode"
- );
- assert.isVisible(
- target.querySelector('.o_field_one2many thead th[data-name="display_name"]'),
- "display_name cell should be visible in readonly mode"
- );
-
- await click(target.querySelector(".o_form_button_edit"));
-
- assert.strictEqual(
- target.querySelector('th[data-name="foo"]').style.width,
- "100%",
- 'As the only visible char field, "foo" should take 100% of the remaining space'
- );
-
- assert.containsNone(
- target,
- "th.oe_read_only",
- 'the column with "oe_read_only" should not be visible in edit mode'
- );
- assert.containsOnce(target, ".o_form_view .o_form_editable", "form should be in edit mode");
- assert.isNotVisible(
- target.querySelector('th[data-name="display_name"]'),
- "display_name cell should not be visible in edit mode"
- );
-
- await click(target.querySelector(".o_field_x2many_list_row_add a"));
-
- assert.containsNone(
- target,
- "th.oe_read_only",
- 'the column with "oe_read_only" should not be visible in edit mode'
- );
-
- await clickSave(target);
-
- assert.hasClass(
- target.querySelector('[name="display_name"]'),
- "oe_read_only",
- "display_name input should have oe_read_only class"
- );
- });
-
- QUnit.test("oe_edit_only className is handled in list views", async function (assert) {
- await makeView({
- type: "form",
- resModel: "partner",
- serverData,
- arch: `
-
`,
- resId: 1,
- });
-
- assert.containsOnce(
- target,
- ".o_form_view .o_form_readonly",
- "form should be in readonly mode"
- );
- assert.isNotVisible(
- target.querySelector('.o_field_one2many thead th[data-name="display_name"]'),
- "display_name cell should not be visible in readonly mode"
- );
-
- await click(target.querySelector(".o_form_button_edit"));
- assert.containsOnce(target, ".o_form_view .o_form_editable", "form should be in edit mode");
- assert.isVisible(
- target.querySelector('.o_field_one2many thead th[data-name="display_name"]'),
- "display_name cell should be visible in edit mode"
- );
-
- await click(target.querySelector(".o_field_x2many_list_row_add a"));
- assert.isVisible(
- target.querySelector(".o_selected_row .o_data_cell.oe_edit_only"),
- "display_name cell should be visible in edit mode"
- );
- });
-
QUnit.test("*_view_ref in context are passed correctly", async function (assert) {
serverData.views = {
"partner_type,module.tree_view_ref,list": "
",
@@ -6963,7 +6533,6 @@ QUnit.module("Views", (hooks) => {
});
assert.containsNone(target, ".o_form_button_create");
- await click(target.querySelector(".o_form_button_edit"));
assert.containsOnce(target, ".o-kanban-button-new");
});
@@ -6994,8 +6563,6 @@ QUnit.module("Views", (hooks) => {
// bar being set to true, foo shouldn't be readonly and thus its value
// could be saved, even if in its field description it is readonly
- await click(target.querySelector(".o_form_button_edit"));
-
assert.containsOnce(
target,
'.o_field_widget[name="foo"] input',
@@ -7003,10 +6570,10 @@ QUnit.module("Views", (hooks) => {
);
await editInput(target, '.o_field_widget[name="foo"] input', "New foo value");
- await click(target.querySelector(".o_form_button_save"));
+ await clickSave(target);
assert.strictEqual(
- target.querySelector(".o_field_widget[name=foo]").textContent,
+ target.querySelector(".o_field_widget[name=foo] input").value,
"New foo value",
"new value for foo field should have been saved"
);
@@ -7048,7 +6615,7 @@ QUnit.module("Views", (hooks) => {
},
});
- await click(target.querySelector(".o_form_button_save"));
+ await clickSave(target);
});
QUnit.test("readonly set by modifier do not break many2many_tags", async function (assert) {
@@ -7070,7 +6637,6 @@ QUnit.module("Views", (hooks) => {
});
assert.containsNone(target, ".o_field_widget[name=timmy] .o_tag");
- await click(target.querySelector(".o_form_button_edit"));
await click(target.querySelector(".o_field_widget[name=bar] input"));
assert.containsOnce(target, ".o_field_widget[name=timmy] .o_tag");
});
@@ -7209,7 +6775,6 @@ QUnit.module("Views", (hooks) => {
}
},
});
- await click(target.querySelector(".o_form_button_edit"));
assert.strictEqual(
target.querySelector(".o_field_widget[name=foo] input").value,
"blip",
@@ -7222,7 +6787,7 @@ QUnit.module("Views", (hooks) => {
"input should contain new value"
);
- await click(target.querySelector(".o_form_button_cancel"));
+ await clickDiscard(target);
await click(target.querySelector(".o_form_button_create"));
assert.strictEqual(
target.querySelector(".o_field_widget[name=foo] input").value,
@@ -7295,7 +6860,6 @@ QUnit.module("Views", (hooks) => {
},
});
- await click(target.querySelector(".o_form_button_edit"));
assert.strictEqual(
target.querySelectorAll(".o_data_row .o_data_cell")[1].textContent,
"1 record",
@@ -7319,7 +6883,7 @@ QUnit.module("Views", (hooks) => {
);
});
- QUnit.test("in edit mode, first field is focused", async function (assert) {
+ QUnit.test("no field should be focused", async function (assert) {
await makeView({
type: "form",
resModel: "partner",
@@ -7327,7 +6891,17 @@ QUnit.module("Views", (hooks) => {
arch: '
',
resId: 1,
});
- await click(target.querySelector(".o_form_button_edit"));
+
+ assert.strictEqual(document.activeElement, document.body);
+ });
+
+ QUnit.test("in create mode, first field is focused", async function (assert) {
+ await makeView({
+ type: "form",
+ resModel: "partner",
+ serverData,
+ arch: '
',
+ });
assert.strictEqual(
document.activeElement,
@@ -7335,7 +6909,7 @@ QUnit.module("Views", (hooks) => {
);
assert.strictEqual(
target.querySelector('.o_field_widget[name="foo"] input').selectionStart,
- 3,
+ target.querySelector('.o_field_widget[name="foo"] input').value.length,
"cursor should be at the end"
);
});
@@ -7346,9 +6920,7 @@ QUnit.module("Views", (hooks) => {
resModel: "partner",
serverData,
arch: '
',
- resId: 1,
});
- await click(target.querySelector(".o_form_button_edit"));
assert.strictEqual(
document.activeElement,
target.querySelector('.o_field_widget[name="foo"] input')
@@ -7395,8 +6967,7 @@ QUnit.module("Views", (hooks) => {
document.activeElement,
target.querySelector('.o_field_widget[name="int_field"] input')
);
- await click(target.querySelector(".o_form_button_save"));
- await click(target.querySelector(".o_form_button_edit"));
+ await clickSave(target);
assert.notStrictEqual(
document.activeElement,
target.querySelector('.o_field_widget[name="int_field"] input')
@@ -7410,7 +6981,7 @@ QUnit.module("Views", (hooks) => {
resModel: "partner",
serverData,
arch: `
-
`,
mockRPC(route, args) {
@@ -7493,7 +7036,6 @@ QUnit.module("Views", (hooks) => {
$(".o_content").css({ overflow: "auto", "max-height": "300px" });
// Open many2one modal, lastActivatedFieldIndex will not set as we directly click on external button
- await clickEdit(target);
assert.strictEqual($(".o_content").scrollTop(), 0, "scroll position should be 0");
// simply triggerEvent focus doesn't do the trick (doesn't scroll).
target.querySelector("[name='trululu'] input").focus();
@@ -7612,7 +7154,7 @@ QUnit.module("Views", (hooks) => {
},
});
- await click(target.querySelector(".o_form_button_save"));
+ await clickSave(target);
});
QUnit.test("open one2many form containing many2many_tags", async function (assert) {
@@ -7679,9 +7221,8 @@ QUnit.module("Views", (hooks) => {
},
});
- await click(target.querySelector(".o_form_button_edit"));
await editInput(target, ".o_field_widget[name=foo] input", "");
- await click(target.querySelector(".o_form_button_save"));
+ await clickSave(target);
def.resolve();
await nextTick();
@@ -7803,7 +7344,7 @@ QUnit.module("Views", (hooks) => {
resModel: "partner",
resId: 1,
serverData,
- arch: `
`,
+ arch: `
`,
mockRPC(route, args) {
if (route === "/web/dataset/call_kw/product/get_formview_id") {
return false;
@@ -7811,7 +7352,6 @@ QUnit.module("Views", (hooks) => {
},
});
- await click(target.querySelector(".o_form_button_edit"));
await click(target.querySelector(".o_external_button"));
assert.containsOnce(target, ".modal");
assert.containsOnce(
@@ -7850,7 +7390,7 @@ QUnit.module("Views", (hooks) => {
resModel: "partner",
resId: 1,
serverData,
- arch: `
`,
+ arch: `
`,
mockRPC(route, args) {
if (route === "/web/dataset/call_kw/product/get_formview_id") {
return false;
@@ -7861,7 +7401,6 @@ QUnit.module("Views", (hooks) => {
},
});
- await click(target.querySelector(".o_form_button_edit"));
// Open first dialog
await click(target.querySelector(".o_external_button"));
assert.containsOnce(target, ".modal");
@@ -7908,8 +7447,6 @@ QUnit.module("Views", (hooks) => {
resId: 2,
context: { mainContext: 3 },
});
-
- await click(target.querySelector(".o_form_button_edit"));
await click(target.querySelector(".o_field_widget[name=trululu] input"));
});
@@ -8069,7 +7606,6 @@ QUnit.module("Views", (hooks) => {
assert.deepEqual(getFooValues(), ["yop", "My little Foo Value"]);
- await click(target.querySelector(".o_form_button_edit"));
await click(target.querySelector(".o_field_x2many_list_row_add a"));
assert.containsOnce(target, ".modal");
await editInput(target, ".modal .o_field_widget[name=foo] input", "xop");
@@ -8081,11 +7617,10 @@ QUnit.module("Views", (hooks) => {
assert.deepEqual(getFooValues(), ["zop", "yop", "xop", "My little Foo Value"]);
// server-side sort
- await click(target.querySelector(".o_form_button_save"));
+ await clickSave(target);
assert.deepEqual(getFooValues(), ["zop", "yop", "xop", "My little Foo Value"]);
// client-side sort on edit
- await click(target.querySelector(".o_form_button_edit"));
await click(target.querySelectorAll(".o_data_row")[1].querySelector(".o_data_cell"));
await editInput(target, ".modal .o_field_widget[name=foo] input", "zzz");
await click(target.querySelector(".modal-footer .o_form_button_save"));
@@ -8115,7 +7650,6 @@ QUnit.module("Views", (hooks) => {
}
},
});
- await click(target.querySelector(".o_form_button_edit"));
await click(target.querySelector('.o_field_widget[name="trululu"] input'));
});
@@ -8564,7 +8098,6 @@ QUnit.module("Views", (hooks) => {
resId: 1,
});
- await clickEdit(target);
await editInput(target, '[name="foo"] input', "test");
await clickSave(target);
assert.containsOnce(
@@ -8573,7 +8106,6 @@ QUnit.module("Views", (hooks) => {
"should have single translation alert"
);
- await clickEdit(target);
await editInput(target, '[name="foo"] input', "test2");
await editInput(target, '[name="display_name"] input', "test3");
await clickSave(target);
@@ -8614,7 +8146,6 @@ QUnit.module("Views", (hooks) => {
});
assert.verifySteps(["get_views", "read"]);
- await clickEdit(target);
assert.containsOnce(target, ".o_form_editable");
// o_field_translate is on the input and on the translate button
assert.containsN(target, "div[name='foo'] > .o_field_translate", 2);
@@ -8624,7 +8155,7 @@ QUnit.module("Views", (hooks) => {
".alert .o_field_translate",
"should not have a translation alert"
);
- assert.containsOnce(target, ".o_form_readonly");
+ assert.containsOnce(target, ".o_form_saved");
assert.verifySteps([]);
});
@@ -8664,7 +8195,6 @@ QUnit.module("Views", (hooks) => {
}
},
});
- await clickEdit(target);
await click(target, ".o_field_translate.btn-link");
assert.verifySteps([
@@ -8784,7 +8314,6 @@ QUnit.module("Views", (hooks) => {
},
});
assert.verifySteps(["get_views", "read"]);
- await clickEdit(target);
await click(target, ".o_field_legacy_char .o_field_translate.btn-link");
assert.verifySteps(["get_installed", "get_field_translations"]);
assert.containsOnce(target, ".modal");
@@ -8807,7 +8336,6 @@ QUnit.module("Views", (hooks) => {
resId: 1,
});
- await clickEdit(target);
await editInput(target, '[name="foo"] input', "test");
await clickSave(target);
@@ -8891,7 +8419,7 @@ QUnit.module("Views", (hooks) => {
-
+
`,
@@ -8906,7 +8434,7 @@ QUnit.module("Views", (hooks) => {
`,
@@ -8934,7 +8462,6 @@ QUnit.module("Views", (hooks) => {
},
});
- await clickEdit(target);
await click(target.querySelector('[name="product_id"] .o_external_button'));
assert.containsOnce(
target.querySelector(".modal-body"),
@@ -8986,8 +8513,8 @@ QUnit.module("Views", (hooks) => {
assert.containsN(
target,
- ".o_form_buttons_view button:not(:disabled)",
- 2,
+ ".o_control_panel button:not(.fa):not(:disabled)",
+ 3,
"control panel buttons should be enabled"
);
assert.containsN(
@@ -9007,8 +8534,8 @@ QUnit.module("Views", (hooks) => {
// The unresolved promise lets us check the state of the buttons
assert.containsN(
target,
- ".o_form_buttons_view button:disabled",
- 2,
+ ".o_control_panel button:not(.fa):disabled",
+ 3,
"control panel buttons should be disabled"
);
assert.containsN(
@@ -9027,8 +8554,8 @@ QUnit.module("Views", (hooks) => {
await nextTick();
assert.containsN(
target,
- ".o_form_buttons_view button:not(:disabled)",
- 2,
+ ".o_control_panel button:not(.fa):not(:disabled)",
+ 3,
"control panel buttons should be enabled"
);
assert.containsN(
@@ -9083,8 +8610,8 @@ QUnit.module("Views", (hooks) => {
assert.containsN(
target,
- ".o_form_buttons_view button:not(:disabled)",
- 2,
+ ".o_control_panel button:not(.fa):not(:disabled)",
+ 3,
"control panel buttons should be enabled"
);
assert.containsN(
@@ -9104,8 +8631,8 @@ QUnit.module("Views", (hooks) => {
// The unresolved promise lets us check the state of the buttons
assert.containsN(
target,
- ".o_form_buttons_view button:disabled",
- 2,
+ ".o_control_panel button:not(.fa):disabled",
+ 3,
"control panel buttons should be disabled"
);
assert.containsN(
@@ -9124,8 +8651,8 @@ QUnit.module("Views", (hooks) => {
await nextTick();
assert.containsN(
target,
- ".o_form_buttons_view button:not(:disabled)",
- 2,
+ ".o_control_panel button:not(.fa):not(:disabled)",
+ 3,
"control panel buttons should be enabled"
);
assert.containsN(
@@ -9229,7 +8756,7 @@ QUnit.module("Views", (hooks) => {
type: "form",
resModel: "partner",
serverData,
- arch: `
`,
+ arch: `
`,
resId: 1,
mockRPC(route, args) {
if (args.method === "get_formview_id") {
@@ -9238,7 +8765,6 @@ QUnit.module("Views", (hooks) => {
},
});
- await click(target.querySelector(".o_form_button_edit"));
await click(target.querySelector(".o_external_button"));
assert.notOk(target.querySelector(".modal .oe_button_box button").disabled);
@@ -9268,10 +8794,9 @@ QUnit.module("Views", (hooks) => {
},
});
- await click(target.querySelector(".o_form_button_edit"));
await editInput(target, '.o_field_widget[name="foo"] input', "test");
- await click(target.querySelector(".o_form_button_save"));
- await click(target.querySelector(".o_form_button_save"));
+ await clickSave(target);
+ await clickSave(target);
def.resolve();
await nextTick();
@@ -9298,11 +8823,10 @@ QUnit.module("Views", (hooks) => {
},
});
- await click(target.querySelector(".o_form_button_edit"));
await editInput(target, ".o_field_widget[name=foo] input", "incorrect value");
- await click(target.querySelector(".o_form_button_save"));
+ await clickSave(target);
await editInput(target, ".o_field_widget[name=foo] input", "correct value");
- await click(target.querySelector(".o_form_button_save"));
+ await clickSave(target);
assert.verifySteps([
"get_views",
@@ -9327,6 +8851,7 @@ QUnit.module("Views", (hooks) => {
`,
+ mode: "readonly",
resId: 1,
mockRPC(route, args) {
if (args.method === "write") {
@@ -9393,7 +8918,6 @@ QUnit.module("Views", (hooks) => {
}
},
});
- await click(target.querySelector(".o_form_button_edit"));
await click(target.querySelector(".o_field_x2many_list_row_add a"));
assert.containsOnce(target, ".modal");
@@ -9493,7 +9017,7 @@ QUnit.module("Views", (hooks) => {
);
await click(target.querySelector(".modal-footer .btn-primary"));
- await click(target.querySelector(".o_form_button_save"));
+ await clickSave(target);
});
QUnit.test("id is False in evalContext for new records", async function (assert) {
@@ -9514,8 +9038,7 @@ QUnit.module("Views", (hooks) => {
"foo should be readonly in 'Create' mode"
);
- await click(target.querySelector(".o_form_button_save"));
- await click(target.querySelector(".o_form_button_edit"));
+ await clickSave(target);
assert.doesNotHaveClass(
target.querySelector(".o_field_widget[name=foo]"),
@@ -9552,7 +9075,7 @@ QUnit.module("Views", (hooks) => {
"first record (copy)",
"duplicated record should have correct name"
);
- await click(target.querySelector(".o_form_button_save")); // save duplicated record
+ await clickSave(target); // save duplicated record
// delete duplicated record
await toggleActionMenu(target);
@@ -9562,7 +9085,7 @@ QUnit.module("Views", (hooks) => {
await click(target.querySelector(".modal-footer .btn-primary"));
assert.strictEqual(
- target.querySelector(".o_field_widget").textContent,
+ target.querySelector(".o_field_widget input").value,
"first record",
"should have come back to previous record"
);
@@ -9662,7 +9185,7 @@ QUnit.module("Views", (hooks) => {
// parent view. If this event isn't stopPropagated by the first controller
// catching it, it will crash when the other one will try to handle it,
// as this one doesn't know at all the dataPointID to reload.
- const arch = `
`;
+ const arch = `
`;
serverData.views = {
"partner,false,form": arch,
};
@@ -9680,7 +9203,6 @@ QUnit.module("Views", (hooks) => {
},
});
- await click(target.querySelector(".o_form_button_edit"));
await click(target.querySelector(".o_external_button"));
await click(target.querySelector(".modal .o_external_button"));
@@ -9777,7 +9299,7 @@ QUnit.module("Views", (hooks) => {
type: "form",
resModel: "partner",
serverData,
- arch: `
`,
+ arch: `
`,
resId: 1,
mockRPC(route, args) {
if (route === "/web/dataset/call_kw/partner/get_formview_id") {
@@ -9785,7 +9307,6 @@ QUnit.module("Views", (hooks) => {
}
},
});
- await click(target.querySelector(".o_form_button_edit"));
await click(target.querySelector(".o_external_button"));
assert.deepEqual(getNodesTextContent(target.querySelectorAll(".modal-body .o_data_cell")), [
"yop",
@@ -9909,36 +9430,6 @@ QUnit.module("Views", (hooks) => {
widgetRegistry.remove("test_widget");
});
- QUnit.test("bounce edit button in readonly mode", async function (assert) {
- await makeView({
- type: "form",
- resModel: "partner",
- serverData,
- arch: `
-
`,
- resId: 1,
- });
-
- // in readonly
- await click(target.querySelector(".nav-tabs .nav-item"));
- assert.containsNone(target, ".o_catch_attention");
-
- await click(target.querySelector("div.oe_title"));
- assert.hasClass(target.querySelector(".o_form_button_edit"), "o_catch_attention");
-
- // in edit
- await click(target.querySelector(".o_form_button_edit"));
- await click(target.querySelector('[name="display_name"]'));
- assert.containsNone(target, ".o_catch_attention");
- });
-
QUnit.test("proper stringification in debug mode tooltip", async function (assert) {
patchWithCleanup(odoo, { debug: true });
@@ -10017,8 +9508,7 @@ QUnit.module("Views", (hooks) => {
"pager should indicate that we are on second record"
);
- await click(target.querySelector(".o_form_button_edit"));
- await click(target.querySelector(".o_form_button_cancel"));
+ await clickDiscard(target);
assert.strictEqual(
target.querySelector(".o_pager_value").textContent,
@@ -10147,8 +9637,6 @@ QUnit.module("Views", (hooks) => {
},
});
- await clickEdit(target);
-
form.env.bus.on("CLEAR-CACHES", target, assert.step.bind(assert, "clear_cache"));
await editInput(target, "[name=display_name] input", "new value");
@@ -10175,8 +9663,6 @@ QUnit.module("Views", (hooks) => {
},
});
- await clickEdit(target);
-
form.env.bus.on("CLEAR-CACHES", target, assert.step.bind(assert, "clear_cache"));
await editInput(target, "[name=display_name] input", "new value");
@@ -10237,8 +9723,6 @@ QUnit.module("Views", (hooks) => {
},
});
- await clickEdit(target);
-
await editInput(target.querySelector("[name=display_name]"), "input", "new value");
await clickSave(target);
assert.verifySteps(["get_views", "read", "write", "reload currencies", "read"]);
@@ -10287,9 +9771,6 @@ QUnit.module("Views", (hooks) => {
},
});
- // switch to edit mode
- await click(target.querySelector(".o_form_button_edit"));
-
// add a row and partially fill it
await click(target.querySelector(".o_field_x2many_list_row_add a"));
await editInput(target, ".o_field_widget[name=display_name] input", "abc");
@@ -10316,7 +9797,7 @@ QUnit.module("Views", (hooks) => {
values = {
product_id: 37,
};
- await click(target.querySelector(".o_form_button_save"));
+ await clickSave(target);
});
QUnit.test("no deadlock when saving with uncommitted changes", async function (assert) {
@@ -10341,11 +9822,11 @@ QUnit.module("Views", (hooks) => {
});
await editInput(target, ".o_field_widget[name=foo] input", "some foo value");
- await click(target.querySelector(".o_form_button_save"));
+ await clickSave(target);
- assert.containsOnce(target, ".o_form_readonly", "form view should be in readonly");
+ assert.containsOnce(target, ".o_form_editable", "form view should be in edit");
assert.strictEqual(
- target.querySelector(".o_form_view .o_form_readonly").textContent.trim(),
+ target.querySelector(".o_field_widget[name=foo] input").value,
"some foo value",
"foo field should have correct value"
);
@@ -10366,7 +9847,7 @@ QUnit.module("Views", (hooks) => {
await editInput(target, ".o_field_widget[name=qux] input", "some qux value");
- await click(target.querySelector(".o_form_button_save"));
+ await clickSave(target);
assert.containsOnce(target, ".o_form_editable", "form view should stay in edit mode");
assert.strictEqual(
@@ -10442,7 +9923,7 @@ QUnit.module("Views", (hooks) => {
await editInput(target, ".o_field_widget[name=display_name] input", "some value");
- await click(target.querySelector(".o_form_button_save"));
+ await clickSave(target);
assert.step("resolve");
onchangeDef.resolve();
@@ -10511,7 +9992,7 @@ QUnit.module("Views", (hooks) => {
);
// save (will wait for the onchange to return), and will be delayed as well
- await click(target.querySelector(".o_form_button_save"));
+ await clickSave(target);
assert.containsOnce(target, ".o_form_editable");
assert.strictEqual(
@@ -10595,9 +10076,6 @@ QUnit.module("Views", (hooks) => {
// switch to form view
await click(target.querySelector(".o_list_table .o_data_row .o_data_cell"));
- // switch to edit mode
- await click(target.querySelector(".o_form_button_edit"));
-
assert.containsOnce(target, ".o_form_editable");
await editInput(target, ".o_field_widget[name=foo] input", "some value");
@@ -10648,9 +10126,6 @@ QUnit.module("Views", (hooks) => {
resIds: [1, 2],
});
- // switch to edit mode
- await click(target.querySelector(".o_form_button_edit"));
-
assert.strictEqual(
target.querySelector(".o_field_widget[name=foo] input").value,
"yop",
@@ -10705,7 +10180,6 @@ QUnit.module("Views", (hooks) => {
const webClient = await createWebClient({ serverData });
await doAction(webClient, 1);
-
await click(target.querySelector(".o_control_panel .o-kanban-button-new"));
//cannot save because there is a required field
@@ -10750,46 +10224,6 @@ QUnit.module("Views", (hooks) => {
}
);
- QUnit.test(
- "edit a record in readonly and switch to edit before it is actually saved",
- async function (assert) {
- assert.expect(3);
-
- const def = makeDeferred();
- await makeView({
- type: "form",
- resModel: "partner",
- serverData,
- arch: `
-
`,
- async mockRPC(route, args) {
- if (args.method === "write") {
- assert.deepEqual(args.args[1], { bar: false });
- await def;
- }
- },
- resId: 1,
- });
-
- // edit the record (in readonly) with toogle_button widget (and delay the write RPC)
- await click(target.querySelector(".o_field_widget[name=bar] button"));
-
- // switch to edit mode
- await click(target.querySelector(".o_form_button_edit"));
-
- assert.containsOnce(target, ".o_form_readonly"); // should wait for the RPC to return
-
- // make write RPC return
- def.resolve();
- await nextTick();
-
- assert.containsOnce(target, ".o_form_editable");
- }
- );
-
QUnit.test(
'"bare" buttons in template should not trigger button click',
async function (assert) {
@@ -11112,7 +10546,7 @@ QUnit.module("Views", (hooks) => {
});
await editInput(target, '.o_field_widget[name="name"] input', "Test Company");
- await click(target.querySelector(".o_form_button_save"));
+ await clickSave(target);
assert.verifySteps(["get_views", "onchange", "create", "reload company", "read"]);
}
@@ -11156,9 +10590,8 @@ QUnit.module("Views", (hooks) => {
},
});
- await click(target.querySelector(".o_form_button_edit"));
await editInput(target, '.o_field_widget[name="name"] input', "Test Company2");
- await click(target.querySelector(".o_form_button_save"));
+ await clickSave(target);
assert.verifySteps(["get_views", "read", "write", "reload company", "read"]);
}
@@ -11315,7 +10748,6 @@ QUnit.module("Views", (hooks) => {
"first record",
]);
- await click(target.querySelector(".o_form_button_edit"));
await editInput(target, ".o_field_widget[name='name'] input", "aaa");
await click(target.querySelector(`.o_pager button.o_pager_next`));
@@ -11329,23 +10761,23 @@ QUnit.module("Views", (hooks) => {
"name"
);
- await click(target.querySelector(".o_form_button_cancel"));
+ await clickDiscard(target);
assert.deepEqual(getNodesTextContent(target.querySelectorAll(".breadcrumb li")), [
"Partner",
"second record",
]);
assert.strictEqual(
- target.querySelector('.o_field_widget[name="name"]').textContent,
+ target.querySelector('.o_field_widget[name="name"] input').value,
"name"
);
await click(target.querySelector(`.o_pager button.o_pager_previous`));
- assert.containsOnce(target, ".o_form_readonly");
+ assert.containsOnce(target, ".o_form_saved");
assert.deepEqual(getNodesTextContent(target.querySelectorAll(".breadcrumb li")), [
"Partner",
"first record",
]);
- assert.strictEqual(target.querySelector('.o_field_widget[name="name"]').textContent, "aaa");
+ assert.strictEqual(target.querySelector('.o_field_widget[name="name"] input').value, "aaa");
});
QUnit.test("Auto save: save when breadcrumb clicked", async function (assert) {
@@ -11392,7 +10824,6 @@ QUnit.module("Views", (hooks) => {
"first record",
]);
- await click(target.querySelector(".o_form_button_edit"));
await editInput(target, ".o_field_widget[name='name'] input", "aaa");
await click(target.querySelector(".breadcrumb-item.o_back_button"));
@@ -11401,12 +10832,12 @@ QUnit.module("Views", (hooks) => {
assert.strictEqual(target.querySelector(".o_field_cell").textContent, "aaa");
await click(target.querySelector(".o_data_row td.o_data_cell"));
- assert.containsOnce(target, ".o_form_readonly");
+ assert.containsOnce(target, ".o_form_editable");
assert.deepEqual(getNodesTextContent(target.querySelectorAll(".breadcrumb li")), [
"Partner",
"first record",
]);
- assert.strictEqual(target.querySelector('.o_field_widget[name="name"]').textContent, "aaa");
+ assert.strictEqual(target.querySelector('.o_field_widget[name="name"] input').value, "aaa");
});
QUnit.test("Auto save: save when action changed", async function (assert) {
@@ -11470,7 +10901,6 @@ QUnit.module("Views", (hooks) => {
"first record",
]);
- await click(target.querySelector(".o_form_button_edit"));
await editInput(target, ".o_field_widget[name='name'] input", "aaa");
await doAction(webClient, 2, { clearBreadcrumbs: true });
@@ -11480,12 +10910,12 @@ QUnit.module("Views", (hooks) => {
await doAction(webClient, 1, { clearBreadcrumbs: true });
await click(target.querySelector(".o_data_row td.o_data_cell"));
- assert.containsOnce(target, ".o_form_readonly");
+ assert.containsOnce(target, ".o_form_editable");
assert.deepEqual(getNodesTextContent(target.querySelectorAll(".breadcrumb li")), [
"Partner",
"first record",
]);
- assert.strictEqual(target.querySelector('.o_field_widget[name="name"]').textContent, "aaa");
+ assert.strictEqual(target.querySelector('.o_field_widget[name="name"] input').value, "aaa");
});
QUnit.test("Auto save: save on closing tab/browser", async function (assert) {
@@ -11509,7 +10939,6 @@ QUnit.module("Views", (hooks) => {
},
});
- await click(target.querySelector(".o_form_button_edit"));
assert.notStrictEqual(
target.querySelector('.o_field_widget[name="display_name"]').value,
"test"
@@ -11539,7 +10968,6 @@ QUnit.module("Views", (hooks) => {
},
});
- await click(target.querySelector(".o_form_button_edit"));
await editInput(target, '.o_field_widget[name="display_name"] input', "");
window.dispatchEvent(new Event("beforeunload"));
await nextTick();
@@ -11566,8 +10994,6 @@ QUnit.module("Views", (hooks) => {
},
});
- await click(target.querySelector(".o_form_button_edit"));
-
window.dispatchEvent(new Event("beforeunload"));
await nextTick();
@@ -11662,7 +11088,6 @@ QUnit.module("Views", (hooks) => {
},
});
- await click(target.querySelector(".o_form_button_edit"));
await editInput(target, '.o_field_widget[name="display_name"] input', "test");
window.dispatchEvent(new Event("beforeunload"));
@@ -11699,7 +11124,6 @@ QUnit.module("Views", (hooks) => {
},
});
- await click(target.querySelector(".o_form_button_edit"));
await editInput(target, '.o_field_widget[name="display_name"] input', "test1");
await editInput(target, '.o_field_widget[name="name"] input', "test2");
@@ -11724,8 +11148,6 @@ QUnit.module("Views", (hooks) => {
},
});
- await click(target.querySelector(".o_form_button_edit"));
-
// edit 'foo' but do not focusout -> the model isn't aware of the change
// until the 'beforeunload' event is triggered
const input = target.querySelector(".o_field_widget[name='foo'] input");
@@ -11775,7 +11197,6 @@ QUnit.module("Views", (hooks) => {
},
});
- await click(target.querySelector(".o_form_button_edit"));
// edit 'display_name' and simulate a focusout (trigger the 'change' event)
await editInput(target, '.o_field_widget[name="display_name"] input', "test");
@@ -11815,8 +11236,6 @@ QUnit.module("Views", (hooks) => {
},
});
- await click(target.querySelector(".o_form_button_edit"));
-
// edit 'foo' but do not focusout -> the model isn't aware of the change
// until the 'beforeunload' event is triggered
const input = target.querySelector(".o_field_widget[name='qux'] input");
@@ -11863,7 +11282,6 @@ QUnit.module("Views", (hooks) => {
},
});
- await click(target.querySelector(".o_form_button_edit"));
await editInput(target, '.o_field_widget[name="display_name"] input', "test");
await editInput(target, '.o_field_widget[name="name"] input', "");
@@ -11960,9 +11378,9 @@ QUnit.module("Views", (hooks) => {
".modal .o_field_widget[name=foo] span",
"foo should be readonly"
);
- await click(target.querySelector(".modal-footer .btn-primary.o_form_button_save"));
+ await clickSave(target.querySelector(".modal"));
- await click(target.querySelector(".o_form_button_save")); // save the record
+ await clickSave(target); // save the record
}
);
@@ -12215,7 +11633,6 @@ QUnit.module("Views", (hooks) => {
});
assert.containsOnce(target, ".o_form_readonly");
- assert.containsOnce(target, ".o_form_button_edit");
assert.containsOnce(target, ".o_form_button_create");
await click(target, ".o_form_button_create");
@@ -12225,22 +11642,19 @@ QUnit.module("Views", (hooks) => {
}
);
- QUnit.test(
- "form with an initial mode (readonly) -- new record from scratch",
- async (assert) => {
- await makeView({
- type: "form",
- resModel: "partner", // no resId: important
- serverData,
- arch: `
`,
- mode: "readonly", // important
- });
+ QUnit.test("form with an initial mode (edit) -- new record from scratch", async (assert) => {
+ await makeView({
+ type: "form",
+ resModel: "partner", // no resId: important
+ serverData,
+ arch: `
`,
+ mode: "readonly", // important
+ });
- assert.containsOnce(target, ".o_form_editable");
- assert.containsOnce(target, ".o_form_button_save");
- assert.containsOnce(target, ".o_form_button_cancel");
- }
- );
+ assert.containsOnce(target, ".o_form_editable");
+ assert.containsOnce(target, ".o_form_button_save");
+ assert.containsOnce(target, ".o_form_button_cancel");
+ });
QUnit.test("save a form view with an invisible required field", async function (assert) {
serverData.models.partner.fields.text = { string: "Text", type: "char", required: 1 };
@@ -12342,10 +11756,10 @@ QUnit.module("Views", (hooks) => {
onDiscard: () => assert.step("discard"),
});
- await click(target, ".o_form_button_edit");
- await click(target, ".o_form_button_save");
- await click(target, ".o_form_button_edit");
- await click(target, ".o_form_button_cancel");
+ await editInput(target, ".o_field_widget input", "test");
+ await clickSave(target);
+ await editInput(target, ".o_field_widget input", "test");
+ await clickDiscard(target);
assert.verifySteps(["save", "discard"]);
});
@@ -12408,4 +11822,125 @@ QUnit.module("Views", (hooks) => {
assert.containsOnce(target, ".o_form_view .o_field_x2many .o_kanban_renderer");
assert.containsNone(target, ".o_view_nocontent");
});
+
+ QUnit.test("status indicator: saved state", async (assert) => {
+ await makeView({
+ type: "form",
+ resModel: "partner",
+ resId: 1,
+ serverData,
+ arch: `
`,
+ });
+
+ assert.containsOnce(target, ".o_form_status_indicator");
+ assert.containsOnce(target, ".o_form_status_indicator_buttons");
+ assert.containsOnce(target, ".o_form_status_indicator_buttons_hidden");
+ assert.containsN(target, ".o_form_status_indicator_buttons button", 2);
+ assert.strictEqual(
+ target.querySelector(".o_form_status_indicator").textContent,
+ "SaveDiscard"
+ );
+ });
+
+ QUnit.test("status indicator: dirty state", async (assert) => {
+ await makeView({
+ type: "form",
+ resModel: "partner",
+ resId: 1,
+ serverData,
+ arch: `
`,
+ });
+
+ assert.strictEqual(
+ target.querySelector(".o_form_status_indicator").textContent,
+ "SaveDiscard"
+ );
+ assert.containsOnce(target, ".o_form_status_indicator_buttons_hidden");
+ await editInput(target, ".o_field_widget input", "dirty");
+ assert.strictEqual(
+ target.querySelector(".o_form_status_indicator").textContent,
+ "Unsaved changesSaveDiscard"
+ );
+ assert.containsNone(target, ".o_form_status_indicator_buttons_hidden");
+ });
+
+ QUnit.test("status indicator: save dirty state", async (assert) => {
+ await makeView({
+ type: "form",
+ resModel: "partner",
+ resId: 1,
+ serverData,
+ arch: `
`,
+ });
+
+ assert.strictEqual(target.querySelector(".o_field_widget input").value, "yop");
+ await editInput(target, ".o_field_widget input", "dirty");
+ assert.containsNone(target, ".o_form_status_indicator_buttons_hidden");
+ assert.strictEqual(
+ target.querySelector(".o_form_status_indicator").textContent,
+ "Unsaved changesSaveDiscard"
+ );
+ await clickSave(target);
+ assert.containsOnce(target, ".o_form_status_indicator_buttons_hidden");
+ assert.strictEqual(
+ target.querySelector(".o_form_status_indicator").textContent,
+ "SaveDiscard"
+ );
+ assert.strictEqual(target.querySelector(".o_field_widget input").value, "dirty");
+ });
+
+ QUnit.test("status indicator: discard dirty state", async (assert) => {
+ await makeView({
+ type: "form",
+ resModel: "partner",
+ resId: 1,
+ serverData,
+ arch: `
`,
+ });
+
+ assert.strictEqual(target.querySelector(".o_field_widget input").value, "yop");
+ await editInput(target, ".o_field_widget input", "dirty");
+ assert.containsNone(target, ".o_form_status_indicator_buttons_hidden");
+ assert.strictEqual(
+ target.querySelector(".o_form_status_indicator").textContent,
+ "Unsaved changesSaveDiscard"
+ );
+ await clickDiscard(target);
+ assert.containsOnce(target, ".o_form_status_indicator_buttons_hidden");
+ assert.strictEqual(
+ target.querySelector(".o_form_status_indicator").textContent,
+ "SaveDiscard"
+ );
+ assert.strictEqual(target.querySelector(".o_field_widget input").value, "yop");
+ });
+
+ QUnit.test("status indicator: invalid state", async (assert) => {
+ await makeView({
+ type: "form",
+ resModel: "partner",
+ resId: 1,
+ serverData,
+ arch: `
`,
+ mockRPC(route, { method }) {
+ if (method === "write") {
+ return Promise.reject(false);
+ }
+ },
+ });
+
+ assert.strictEqual(
+ target.querySelector(".o_form_status_indicator").textContent,
+ "SaveDiscard"
+ );
+ await editInput(target, ".o_field_widget input", "");
+ assert.strictEqual(
+ target.querySelector(".o_form_status_indicator").textContent,
+ "Unsaved changesSaveDiscard"
+ );
+ await clickSave(target);
+ assert.strictEqual(
+ target.querySelector(".o_form_status_indicator").textContent,
+ "Unable to saveSaveDiscard"
+ );
+ });
});
diff --git a/addons/web/static/tests/views/list_view_tests.js b/addons/web/static/tests/views/list_view_tests.js
index 22f968d8820..f40c7ed87a6 100644
--- a/addons/web/static/tests/views/list_view_tests.js
+++ b/addons/web/static/tests/views/list_view_tests.js
@@ -14,7 +14,6 @@ import {
addRow,
click,
clickDiscard,
- clickEdit,
clickOpenedDropdownItem,
clickOpenM2ODropdown,
clickSave,
@@ -1897,7 +1896,6 @@ QUnit.module("Views", (hooks) => {
}
},
});
- await clickEdit(target);
assert.hasClass(target.querySelectorAll(".o_data_cell")[1], "o_boolean_toggle_cell");
@@ -1943,7 +1941,6 @@ QUnit.module("Views", (hooks) => {
`,
});
- await clickEdit(target);
await addRow(target);
await click(
[...target.querySelectorAll(".o_data_row")].pop().querySelector("td.o_list_char")
@@ -3245,7 +3242,7 @@ QUnit.module("Views", (hooks) => {
}
);
- QUnit.test("colspan of empty lines is correct in readonly and edit", async function (assert) {
+ QUnit.test("colspan of empty lines is correct in readonly", async function (assert) {
serverData.models.foo.fields.foo_o2m = {
string: "Foo O2M",
type: "one2many",
@@ -3268,10 +3265,33 @@ QUnit.module("Views", (hooks) => {
`,
});
- // in edit mode, the delete action is available and the empty lines should cover that col
+ // in readonly mode, the delete action is available and the empty lines should cover that col
assert.strictEqual(target.querySelector("tbody td").getAttribute("colspan"), "2");
- await clickEdit(target);
- // in edit mode, the colspan shouldn't change
+ });
+
+ QUnit.test("colspan of empty lines is correct in edit", async function (assert) {
+ serverData.models.foo.fields.foo_o2m = {
+ string: "Foo O2M",
+ type: "one2many",
+ relation: "foo",
+ };
+ await makeView({
+ type: "form",
+ resModel: "foo",
+ serverData,
+ resId: 1,
+ arch: `
+
`,
+ });
+ // in edit mode, the delete action is available and the empty lines should cover that col
assert.strictEqual(target.querySelector("tbody td").getAttribute("colspan"), "2");
});
@@ -3543,7 +3563,6 @@ QUnit.module("Views", (hooks) => {
`,
});
- await clickEdit(target);
assert.containsNone(target, ".o_field_one2many");
await click(target.querySelector(".nav-item:last-child .nav-link"));
@@ -3593,7 +3612,6 @@ QUnit.module("Views", (hooks) => {
`,
});
- await clickEdit(target);
assert.containsNone(target, ".o_field_one2many");
await click(target.querySelector(".o_field_boolean input"));
@@ -3634,7 +3652,6 @@ QUnit.module("Views", (hooks) => {
`,
});
- await clickEdit(target);
assert.containsNone(target, ".o_field_one2many");
await click(target.querySelector(".o_field_boolean input"));
@@ -4912,7 +4929,6 @@ QUnit.module("Views", (hooks) => {
resId: 1,
});
- await clickEdit(target);
assert.deepEqual(
[...target.querySelectorAll(".o_field_x2many_list .o_data_row")].map(
(el) => el.textContent
@@ -4964,7 +4980,6 @@ QUnit.module("Views", (hooks) => {
resId: 1,
});
- await clickEdit(target);
assert.deepEqual(
[...target.querySelectorAll(".o_field_x2many_list .o_data_row")].map(
(el) => el.textContent
@@ -6982,7 +6997,6 @@ QUnit.module("Views", (hooks) => {
`,
resId: 1,
});
- await clickEdit(target);
assert.deepEqual(
[
...target.querySelectorAll(
@@ -7875,8 +7889,6 @@ QUnit.module("Views", (hooks) => {
},
});
- await clickEdit(target);
-
await click(target.querySelector(".o_data_cell"));
assert.strictEqual(
document.activeElement,
@@ -10374,7 +10386,7 @@ QUnit.module("Views", (hooks) => {
await makeView({
arch: `
-
+
`,
serverData,
mockRPC: async function (route, args) {
@@ -14502,8 +14514,6 @@ QUnit.module("Views", (hooks) => {
},
});
- await clickEdit(target);
-
await click(target.querySelector(".o_data_cell"));
assert.strictEqual(
document.activeElement,
diff --git a/addons/web/static/tests/views/view_dialogs/form_view_dialog_tests.js b/addons/web/static/tests/views/view_dialogs/form_view_dialog_tests.js
index 3233f922a67..e6cb2a48ec6 100644
--- a/addons/web/static/tests/views/view_dialogs/form_view_dialog_tests.js
+++ b/addons/web/static/tests/views/view_dialogs/form_view_dialog_tests.js
@@ -209,7 +209,7 @@ QUnit.module("ViewDialogs", (hooks) => {
serverData,
arch: `
`,
mockRPC: function (route, args) {
if (args.method === "get_formview_id") {
@@ -242,7 +242,6 @@ QUnit.module("ViewDialogs", (hooks) => {
}
},
});
- await click(target, ".o_form_button_edit");
await click(target, '.o_field_widget[name="instrument"] button.o_external_button');
});
diff --git a/addons/web/static/tests/views/view_dialogs/select_create_dialog_tests.js b/addons/web/static/tests/views/view_dialogs/select_create_dialog_tests.js
index 3692d3638bf..d921bee7ba3 100644
--- a/addons/web/static/tests/views/view_dialogs/select_create_dialog_tests.js
+++ b/addons/web/static/tests/views/view_dialogs/select_create_dialog_tests.js
@@ -319,7 +319,6 @@ QUnit.module("ViewDialogs", (hooks) => {
},
});
- await click(target, ".o_form_button_edit");
await click(target, ".o_field_x2many_list_row_add a");
await editInput(target, ".o_field_widget[name=instrument] input", "ABC");
diff --git a/addons/web/static/tests/views/widgets/attach_document_tests.js b/addons/web/static/tests/views/widgets/attach_document_tests.js
index 6603b8094b7..c76eb9a9d34 100644
--- a/addons/web/static/tests/views/widgets/attach_document_tests.js
+++ b/addons/web/static/tests/views/widgets/attach_document_tests.js
@@ -1,6 +1,6 @@
/** @odoo-module **/
-import { click, clickEdit, editInput, getFixture, triggerEvent } from "@web/../tests/helpers/utils";
+import { click, editInput, getFixture, triggerEvent } from "@web/../tests/helpers/utils";
import { makeView, setupViewRegistries } from "@web/../tests/views/helpers";
import { registry } from "@web/core/registry";
@@ -72,7 +72,6 @@ QUnit.module("Widgets", (hooks) => {
`,
});
- await clickEdit(target);
await editInput(target, "[name='display_name'] input", "yop");
await click(target, ".o_attach_document");
await triggerEvent(
diff --git a/addons/web/static/tests/views/widgets/week_days_tests.js b/addons/web/static/tests/views/widgets/week_days_tests.js
index 21e506b4d93..0e3b07bb3d4 100644
--- a/addons/web/static/tests/views/widgets/week_days_tests.js
+++ b/addons/web/static/tests/views/widgets/week_days_tests.js
@@ -2,7 +2,7 @@
import { registry } from "@web/core/registry";
import { makeFakeLocalizationService } from "../../helpers/mock_services";
-import { getFixture, click, clickEdit, clickSave } from "../../helpers/utils";
+import { getFixture, click, clickSave } from "../../helpers/utils";
import { makeView, setupViewRegistries } from "../helpers";
let serverData;
@@ -46,7 +46,7 @@ QUnit.module("Widgets", ({ beforeEach }) => {
QUnit.module("WeekDays");
QUnit.test("simple week recurrence widget", async (assert) => {
- assert.expect(14);
+ assert.expect(13);
let writeCall = 0;
registry.category("services", makeFakeLocalizationService({ weekStart: 1 }));
@@ -80,12 +80,6 @@ QUnit.module("Widgets", ({ beforeEach }) => {
},
});
- assert.containsN(
- fixture,
- "input:disabled",
- 7,
- "all inputs should be disabled in readonly mode"
- );
const labelsTexts = [...fixture.querySelectorAll(".o_recurrent_weekday_label")].map((el) =>
el.innerText.trim()
);
@@ -95,7 +89,6 @@ QUnit.module("Widgets", ({ beforeEach }) => {
"labels should be short week names"
);
- await clickEdit(fixture);
assert.containsNone(
fixture,
".form-check input:disabled",
@@ -109,7 +102,6 @@ QUnit.module("Widgets", ({ beforeEach }) => {
);
await clickSave(fixture);
- await clickEdit(fixture);
await click(fixture.querySelector("td:nth-child(1) input"));
assert.ok(
fixture.querySelector("td:nth-child(1) input").checked,
diff --git a/addons/web/static/tests/webclient/actions/concurrency_tests.js b/addons/web/static/tests/webclient/actions/concurrency_tests.js
index 21db298a081..3d7aa35a57a 100644
--- a/addons/web/static/tests/webclient/actions/concurrency_tests.js
+++ b/addons/web/static/tests/webclient/actions/concurrency_tests.js
@@ -387,7 +387,7 @@ QUnit.module("ActionManager", (hooks) => {
});
QUnit.test("open a record while reloading the list view", async function (assert) {
- assert.expect(12);
+ assert.expect(10);
let def;
const mockRPC = async function (route) {
if (route === "/web/dataset/search_read") {
@@ -408,14 +408,12 @@ QUnit.module("ActionManager", (hooks) => {
await click(target.querySelector(".o_list_view .o_data_cell"));
assert.containsOnce(target, ".o_form_view");
assert.containsNone(target, ".o_control_panel .o_list_buttons");
- assert.containsOnce(target, ".o_control_panel .o_form_buttons_view");
// unblock the search_read RPC
def.resolve();
await nextTick();
assert.containsOnce(target, ".o_form_view");
assert.containsNone(target, ".o_list_view");
assert.containsNone(target, ".o_control_panel .o_list_buttons");
- assert.containsOnce(target, ".o_control_panel .o_form_buttons_view");
});
QUnit.test(
diff --git a/addons/web/static/tests/webclient/actions/window_action_tests.js b/addons/web/static/tests/webclient/actions/window_action_tests.js
index 284a47b79c3..cb562138f4a 100644
--- a/addons/web/static/tests/webclient/actions/window_action_tests.js
+++ b/addons/web/static/tests/webclient/actions/window_action_tests.js
@@ -17,6 +17,7 @@ import {
makeDeferred,
nextTick,
patchWithCleanup,
+ clickSave,
} from "../../helpers/utils";
import { createWebClient, doAction, getActionManagerServerData, loadState } from "./../helpers";
import { errorService } from "../../../src/core/errors/error_service";
@@ -111,7 +112,7 @@ QUnit.module("ActionManager", (hooks) => {
assert.containsNone(target, ".o_list_view", "should no longer display the list view");
assert.containsOnce(target, ".o_form_view", "should display the form view");
assert.strictEqual(
- $(target).find(".o_field_widget[name=foo]").text(),
+ $(target).find(".o_field_widget[name=foo] input").val(),
"yop",
"should have opened the correct record"
);
@@ -489,7 +490,7 @@ QUnit.module("ActionManager", (hooks) => {
`;
@@ -514,42 +515,42 @@ QUnit.module("ActionManager", (hooks) => {
await click(target, ".o_data_row:first-of-type .o_data_cell");
// Open 1 / 5
- assert.strictEqual(target.querySelector(".o_field_char").innerText, "First record");
+ assert.strictEqual(target.querySelector(".o_field_char input").value, "First record");
assert.deepEqual(cpHelpers.getPagerValue(target), [1]);
assert.strictEqual(cpHelpers.getPagerLimit(target), 5);
- await click(target, ".o_field_many2one a");
+ await click(target, ".o_field_many2one .o_external_button");
// Click on M2O -> 1 / 1
- assert.strictEqual(target.querySelector(".o_field_char").innerText, "Third record");
+ assert.strictEqual(target.querySelector(".o_field_char input").value, "Third record");
assert.deepEqual(cpHelpers.getPagerValue(target), [1]);
assert.strictEqual(cpHelpers.getPagerLimit(target), 1);
await click(target, ".o_back_button");
// Back to 1 / 5
- assert.strictEqual(target.querySelector(".o_field_char").innerText, "First record");
+ assert.strictEqual(target.querySelector(".o_field_char input").value, "First record");
assert.deepEqual(cpHelpers.getPagerValue(target), [1]);
assert.strictEqual(cpHelpers.getPagerLimit(target), 5);
await cpHelpers.pagerNext(target);
// Next page -> 2 / 5
- assert.strictEqual(target.querySelector(".o_field_char").innerText, "Second record");
+ assert.strictEqual(target.querySelector(".o_field_char input").value, "Second record");
assert.deepEqual(cpHelpers.getPagerValue(target), [2]);
assert.strictEqual(cpHelpers.getPagerLimit(target), 5);
- await click(target, ".o_field_many2one a");
+ await click(target, ".o_field_many2one .o_external_button");
// Click on M2O -> still 1 / 1
- assert.strictEqual(target.querySelector(".o_field_char").innerText, "Third record");
+ assert.strictEqual(target.querySelector(".o_field_char input").value, "Third record");
assert.deepEqual(cpHelpers.getPagerValue(target), [1]);
assert.strictEqual(cpHelpers.getPagerLimit(target), 1);
await click(target, ".o_back_button");
// Back to 2 / 5
- assert.strictEqual(target.querySelector(".o_field_char").innerText, "Second record");
+ assert.strictEqual(target.querySelector(".o_field_char input").value, "Second record");
assert.deepEqual(cpHelpers.getPagerValue(target), [2]);
assert.strictEqual(cpHelpers.getPagerLimit(target), 5);
});
@@ -674,9 +675,8 @@ QUnit.module("ActionManager", (hooks) => {
"breadcrumbs should contain the display_name of the opened record"
);
// switch to edit mode and change the display_name
- await click(target.querySelector(".o_control_panel .o_form_button_edit"));
await editInput(target, ".o_field_widget[name=display_name] input", "New name");
- await click(target.querySelector(".o_control_panel .o_form_button_save"));
+ await clickSave(target);
assert.containsN(
target,
".o_control_panel .breadcrumb-item",
@@ -780,7 +780,7 @@ QUnit.module("ActionManager", (hooks) => {
await click(target.querySelector(".o_list_view .o_data_cell"));
await legacyExtraNextTick();
assert.strictEqual(
- $(target).find(".o_field_widget[name=foo]").text(),
+ $(target).find(".o_field_widget[name=foo] input").val(),
"yop",
"check initial value of 'yop' field"
);
@@ -788,7 +788,7 @@ QUnit.module("ActionManager", (hooks) => {
await testUtils.dom.click($(target).find(".o_form_view button:contains(Call method)"));
await legacyExtraNextTick();
assert.strictEqual(
- $(target).find(".o_field_widget[name=foo]").text(),
+ $(target).find(".o_field_widget[name=foo] input").val(),
"value changed",
"'yop' has been changed by the server, and should be updated in the UI"
);
@@ -838,7 +838,7 @@ QUnit.module("ActionManager", (hooks) => {
await testUtils.dom.click(target.querySelector('.o_form_view button[name="4"]'));
await legacyExtraNextTick();
assert.ok(
- target.querySelector(".o_cp_buttons .o_form_button_edit").disabled,
+ target.querySelector(".o_form_button_create").disabled,
"control panel buttons should be disabled"
);
def.resolve();
@@ -846,13 +846,13 @@ QUnit.module("ActionManager", (hooks) => {
await legacyExtraNextTick();
assert.containsOnce(target, ".modal .o_form_view");
assert.notOk(
- target.querySelector(".o_cp_buttons .o_form_button_edit").disabled,
+ target.querySelector(".o_form_button_create").disabled,
"control panel buttons should have been re-enabled"
);
await testUtils.dom.click(target.querySelector(".modal .cancel-btn"));
await legacyExtraNextTick();
assert.notOk(
- target.querySelector(".o_cp_buttons .o_form_button_edit").disabled,
+ target.querySelector(".o_form_button_create").disabled,
"control panel buttons should still be enabled"
);
}
@@ -870,12 +870,14 @@ QUnit.module("ActionManager", (hooks) => {
const webClient = await createWebClient({ serverData, mockRPC });
await doAction(webClient, 3, { viewType: "form" });
assert.containsOnce(target, ".o_form_view");
- // click on 'Execute action', to execute action 4 in a dialog
- testUtils.dom.click(target.querySelector('.o_form_view button[name="object"]'));
- assert.ok(target.querySelector(".o_cp_buttons button").disabled);
+ // save to ensure the presence of the create button
+ await click(target.querySelector(".o_form_button_save"));
+ // click on 'Execute action', to execute action 4 in a dialogdebugger
+ click(target.querySelector('.o_form_view button[name="object"]'));
+ assert.ok(target.querySelector(".o_form_button_create").disabled);
await nextTick();
await legacyExtraNextTick();
- assert.notOk(target.querySelector(".o_cp_buttons button").disabled);
+ assert.notOk(target.querySelector(".o_form_button_create").disabled);
}
);
@@ -965,14 +967,14 @@ QUnit.module("ActionManager", (hooks) => {
const webClient = await createWebClient({ serverData, mockRPC });
await doAction(webClient, 24);
assert.containsOnce(target, ".o_form_view");
- assert.containsN(target, ".o_form_buttons_view button:not([disabled])", 2);
+ assert.containsOnce(target, ".o_form_button_create:not([disabled])");
await testUtils.dom.click(target.querySelector(".oe_stat_button"));
await legacyExtraNextTick();
assert.containsOnce(target, ".o_kanban_view");
await testUtils.dom.click(target.querySelector(".breadcrumb-item"));
await legacyExtraNextTick();
assert.containsOnce(target, ".o_form_view");
- assert.containsN(target, ".o_form_buttons_view button:not([disabled])", 2);
+ assert.containsOnce(target, ".o_form_button_create:not([disabled])");
assert.verifySteps(["read", "web_search_read", "read"]);
});
@@ -987,11 +989,11 @@ QUnit.module("ActionManager", (hooks) => {
const webClient = await createWebClient({ serverData, mockRPC });
await doAction(webClient, 24);
assert.containsOnce(target, ".o_form_view");
- assert.containsN(target, ".o_form_buttons_view button:not([disabled])", 2);
+ assert.containsOnce(target, ".o_form_button_create:not([disabled])");
await testUtils.dom.click(target.querySelector(".oe_stat_button"));
await legacyExtraNextTick();
assert.containsOnce(target, ".o_form_view");
- assert.containsN(target, ".o_form_buttons_view button:not([disabled])", 2);
+ assert.containsOnce(target, ".o_form_button_create:not([disabled])");
assert.verifySteps([
"/web/webclient/load_menus",
"/web/action/load",
@@ -1085,7 +1087,7 @@ QUnit.module("ActionManager", (hooks) => {
"breadcrumbs should contain the display_name of the opened record"
);
assert.strictEqual(
- $(target).find(".o_field_widget[name=foo]").text(),
+ $(target).find(".o_field_widget[name=foo] input").val(),
"yop",
"should have opened the correct record"
);
@@ -1103,7 +1105,7 @@ QUnit.module("ActionManager", (hooks) => {
"breadcrumbs should contain the display_name of the opened record"
);
assert.strictEqual(
- $(target).find(".o_field_widget[name=foo]").text(),
+ $(target).find(".o_field_widget[name=foo] input").val(),
"blip",
"should have opened the correct record"
);
@@ -1247,7 +1249,7 @@ QUnit.module("ActionManager", (hooks) => {
serverData.views["partner,false,form"] = `
`;
const mockRPC = async (route, args) => {
assert.step(route);
@@ -1259,8 +1261,6 @@ QUnit.module("ActionManager", (hooks) => {
await doAction(webClient, 3);
// open first record in form view
await testUtils.dom.click(target.querySelector(".o_data_row .o_data_cell"));
- // click on edit
- await testUtils.dom.click(target.querySelector(".o_control_panel .o_form_button_edit"));
// click on external button for m2o
await testUtils.dom.click(target.querySelector(".o_external_button"));
assert.verifySteps([
@@ -1286,8 +1286,6 @@ QUnit.module("ActionManager", (hooks) => {
await doAction(webClient, 4);
// open record in form view
await click(target.querySelector(".o_kanban_record"));
- // edit record
- await click(target.querySelector(".o_control_panel button.o_form_button_edit"));
await editInput(target, '.o_field_widget[name="foo"] input', "pinkypie");
// go back to kanban view
await click(target.querySelector(".o_control_panel .breadcrumb-item a"));
@@ -1383,7 +1381,7 @@ QUnit.module("ActionManager", (hooks) => {
});
QUnit.test(
- "form views are restored in readonly when coming back in breadcrumbs",
+ "form views are restored in edit when coming back in breadcrumbs",
async function (assert) {
assert.expect(2);
const webClient = await createWebClient({ serverData });
@@ -1391,16 +1389,13 @@ QUnit.module("ActionManager", (hooks) => {
// open a record in form view
await click(target.querySelector(".o_list_view .o_data_cell"));
await legacyExtraNextTick();
- // switch to edit mode
- await click(target.querySelector(".o_control_panel .o_form_button_edit"));
- await legacyExtraNextTick();
assert.containsOnce(target, ".o_form_view .o_form_editable");
// do some other action
await doAction(webClient, 4);
// go back to form view
await click(target.querySelectorAll(".o_control_panel .breadcrumb a")[1]);
await legacyExtraNextTick();
- assert.containsOnce(target, ".o_form_view .o_form_readonly");
+ assert.containsOnce(target, ".o_form_view .o_form_editable");
}
);
@@ -1796,7 +1791,7 @@ QUnit.module("ActionManager", (hooks) => {
await editInput(target, '.o_field_widget[name="display_name"] input', "test");
await editInput(target, ".o_field_widget[name=foo] input", "val");
await click(target.querySelector(".o_form_uri"));
- assert.containsOnce(target, ".o_form_view .o_form_readonly");
+ assert.containsOnce(target, ".o_form_view .o_form_editable");
assert.deepEqual(
getNodesTextContent(target.querySelectorAll(".o_control_panel .breadcrumb-item")),
["Partners", "test", "First record"]
@@ -1805,8 +1800,7 @@ QUnit.module("ActionManager", (hooks) => {
await testUtils.dom.click(
target.querySelectorAll(".o_control_panel .breadcrumb-item a")[1]
);
- // should be readonly and so saved
- assert.containsOnce(target, ".o_form_view .o_form_readonly");
+ assert.containsOnce(target, ".o_form_view .o_form_editable");
assert.deepEqual(
getNodesTextContent(target.querySelectorAll(".o_control_panel .breadcrumb-item")),
["Partners", "test"]
@@ -1865,7 +1859,8 @@ QUnit.module("ActionManager", (hooks) => {
res_id: 2,
views: [[44, "form"]],
};
- serverData.views["partner,44,form"] = '
';
+ serverData.views["partner,44,form"] =
+ '
';
const mockRPC = async (route, args) => {
if (args.method === "get_formview_action") {
return Promise.resolve({
@@ -1878,20 +1873,20 @@ QUnit.module("ActionManager", (hooks) => {
};
const webClient = await createWebClient({ serverData, mockRPC });
await doAction(webClient, 999);
- assert.containsOnce(target, ".o_form_view .o_form_readonly");
+ assert.containsOnce(target, ".o_form_view .o_form_editable");
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb").textContent,
"Second record"
);
// push another action in the breadcrumb
- await click(target, ".o_field_many2one .o_form_uri");
+ await click(target, ".o_field_many2one .o_external_button");
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb").textContent,
"Second recordThird record"
);
// go back to the form view
await click(target.querySelector(".o_control_panel .breadcrumb a"));
- assert.containsOnce(target, ".o_form_view .o_form_readonly");
+ assert.containsOnce(target, ".o_form_view .o_form_editable");
assert.strictEqual(
target.querySelector(".o_control_panel .breadcrumb-item").textContent,
"Second record"
@@ -1908,7 +1903,7 @@ QUnit.module("ActionManager", (hooks) => {
assert.containsN(target, ".o_list_view .o_data_row", 5);
await click(target.querySelector(".o_list_view .o_data_cell"));
assert.containsOnce(target, ".o_form_view");
- assert.containsOnce(target, ".o_form_view .o_form_readonly");
+ assert.containsOnce(target, ".o_form_view .o_form_editable");
// go back using the breadcrumbs
await click(target.querySelector(".o_control_panel .breadcrumb-item a"));
assert.containsOnce(target, ".o_list_view");
@@ -1930,13 +1925,13 @@ QUnit.module("ActionManager", (hooks) => {
await click(target.querySelector(".o_list_view .o_data_cell"));
assert.containsOnce(target, ".o_form_view");
assert.strictEqual(
- $(target).find(".o_field_widget[name=display_name]").text(),
+ $(target).find(".o_field_widget[name=display_name] input").val(),
"First record"
);
// switch to second record
await click(target.querySelector(".o_pager_next"));
assert.strictEqual(
- $(target).find(".o_field_widget[name=display_name]").text(),
+ $(target).find(".o_field_widget[name=display_name] input").val(),
"Second record"
);
// execute an action from the second record
@@ -1946,7 +1941,7 @@ QUnit.module("ActionManager", (hooks) => {
await testUtils.dom.click($(target).find(".o_control_panel .breadcrumb-item:nth(1) a"));
assert.containsOnce(target, ".o_form_view");
assert.strictEqual(
- $(target).find(".o_field_widget[name=display_name]").text(),
+ $(target).find(".o_field_widget[name=display_name] input").val(),
"Second record"
);
}
@@ -1965,16 +1960,16 @@ QUnit.module("ActionManager", (hooks) => {
assert.containsOnce(target, ".o_form_view .o_form_editable");
await editInput(target, ".o_field_widget[name=display_name] input", "another record");
await click(target.querySelector(".o_form_button_save"));
- assert.containsOnce(target, ".o_form_view .o_form_readonly");
+ assert.containsOnce(target, ".o_form_view .o_form_editable");
// execute an action from the second record
await testUtils.dom.click($(target).find(".o_statusbar_buttons button[name=4]"));
assert.containsOnce(target, ".o_kanban_view");
// go back using the breadcrumbs
await testUtils.dom.click($(target).find(".o_control_panel .breadcrumb-item:nth(1) a"));
assert.containsOnce(target, ".o_form_view");
- assert.containsOnce(target, ".o_form_view .o_form_readonly");
+ assert.containsOnce(target, ".o_form_view .o_form_editable");
assert.strictEqual(
- $(target).find(".o_field_widget[name=display_name]").text(),
+ $(target).find(".o_field_widget[name=display_name] input").val(),
"another record"
);
}
@@ -2034,7 +2029,7 @@ QUnit.module("ActionManager", (hooks) => {
QUnit.test(
"Call twice clearUncommittedChanges in a row does not save twice",
async function (assert) {
- assert.expect(5);
+ assert.expect(4);
let writeCalls = 0;
const mockRPC = async (route, { method }) => {
if (method === "write") {
@@ -2045,8 +2040,6 @@ QUnit.module("ActionManager", (hooks) => {
// execute an action and edit existing record
await doAction(webClient, 3);
await click(target.querySelector(".o_list_view .o_data_cell"));
- assert.containsOnce(target, ".o_form_view .o_form_readonly");
- await click(target.querySelector(".o_control_panel .o_form_button_edit"));
assert.containsOnce(target, ".o_form_view .o_form_editable");
await editInput(target, ".o_field_widget[name=foo] input", "val");
clearUncommittedChanges(webClient.env);
@@ -2133,7 +2126,7 @@ QUnit.module("ActionManager", (hooks) => {
});
QUnit.test("do not restore after action button clicked", async function (assert) {
- assert.expect(5);
+ assert.expect(4);
const mockRPC = async (route, args) => {
if (route === "/web/dataset/call_button" && args.method === "do_something") {
return true;
@@ -2149,17 +2142,15 @@ QUnit.module("ActionManager", (hooks) => {
const webClient = await createWebClient({ serverData, mockRPC });
await doAction(webClient, 3, { viewType: "form", props: { resId: 1 } });
await legacyExtraNextTick();
- assert.isVisible(target.querySelector(".o_form_buttons_view .o_form_button_edit"));
- await click(target.querySelector(".o_form_buttons_view .o_form_button_edit"));
- await legacyExtraNextTick();
- assert.isVisible(target.querySelector(".o_form_buttons_edit .o_form_button_save"));
+ await editInput(target, "div[name='display_name'] input", "Edited value");
+ assert.isVisible(target.querySelector(".o_form_button_save"));
assert.isVisible(target.querySelector(".o_statusbar_buttons button[name=do_something]"));
await click(target.querySelector(".o_statusbar_buttons button[name=do_something]"));
await legacyExtraNextTick();
- assert.isVisible(target.querySelector(".o_form_buttons_edit .o_form_button_save"));
- await click(target.querySelector(".o_form_buttons_edit .o_form_button_save"));
+ assert.isVisible(target.querySelector(".o_form_button_save"));
+ await click(target.querySelector(".o_form_button_save"));
await legacyExtraNextTick();
- assert.isVisible(target.querySelector(".o_form_buttons_view .o_form_button_edit"));
+ assert.isNotVisible(target.querySelector(".o_form_buttons_view .o_form_button_save"));
});
QUnit.test("debugManager is active for (legacy) views", async function (assert) {
diff --git a/addons/web_tour/static/src/js/tour_step_utils.js b/addons/web_tour/static/src/js/tour_step_utils.js
index 83adb1f842b..d321898de92 100644
--- a/addons/web_tour/static/src/js/tour_step_utils.js
+++ b/addons/web_tour/static/src/js/tour_step_utils.js
@@ -61,7 +61,7 @@ return Class.extend({
goBackBreadcrumbsMobile(description, ...extraTrigger) {
return extraTrigger.map(element => ({
mobile: true,
- trigger: '.breadcrumb-item:not(.d-none):first',
+ trigger: '.breadcrumb-item.o_back_button',
extra_trigger: element,
content: description,
position: 'bottom',
@@ -160,18 +160,20 @@ return Class.extend({
/**
* Utility steps to save a form and wait for the save to complete
*
- * @param extra_trigger additional save-condition selector
+ * @param {object} [options]
+ * @param {string} [options.content]
+ * @param {string} [options.extra_trigger] additional save-condition selector
*/
- saveForm(extra_trigger) {
+ saveForm(options = {}) {
return [{
- content: "save form",
- trigger: '.o_form_button_save:contains("Save")',
- extra_trigger,
- run: 'click',
+ content: options.content || "save form",
+ trigger: ".o_form_button_save",
+ extra_trigger: options.extra_trigger,
+ run: "click",
auto: true,
}, {
content: "wait for save completion",
- trigger: '.o_form_readonly',
+ trigger: '.o_form_readonly, .o_form_saved',
run() {},
auto: true,
}];
@@ -182,15 +184,16 @@ return Class.extend({
* Supports creation/edition from either a form or a list view (so checks
* for both states).
*/
- discardForm() {
+ discardForm(options = {}) {
return [{
- content: "exit the form",
+ content: options.content || "exit the form",
trigger: ".o_form_button_cancel",
- run: 'click',
+ extra_trigger: options.extra_trigger,
+ run: "click",
auto: true,
}, {
content: "wait for cancellation to complete",
- trigger: ".o_list_renderer, .o_form_readonly",
+ trigger: ".o_list_renderer, .o_form_readonly, .o_form_saved",
run() {},
auto: true,
}];
diff --git a/addons/website_slides/static/tests/qunit_suite_tests/components/slide_category_one2many_field_tests.js b/addons/website_slides/static/tests/qunit_suite_tests/components/slide_category_one2many_field_tests.js
index e90a863ec7e..65d384e92b8 100644
--- a/addons/website_slides/static/tests/qunit_suite_tests/components/slide_category_one2many_field_tests.js
+++ b/addons/website_slides/static/tests/qunit_suite_tests/components/slide_category_one2many_field_tests.js
@@ -1,6 +1,6 @@
/** @odoo-module */
-import { click, clickEdit, getFixture } from "@web/../tests/helpers/utils";
+import { click, getFixture } from "@web/../tests/helpers/utils";
import { makeView, setupViewRegistries } from "@web/../tests/views/helpers";
QUnit.module("SlideCategoryOneToManyField", (hooks) => {
@@ -92,6 +92,7 @@ QUnit.module("SlideCategoryOneToManyField", (hooks) => {
resModel: "partner",
resId: 1,
serverData,
+ mode: "readonly",
arch: `
`,
});
- await clickEdit(target);
await click(target.querySelector(".o_data_cell"));
assert.hasClass(target.querySelector(".o_is_section"), "o_selected_row");
assert.containsNone(target, ".modal .o_form_view");
@@ -150,7 +150,6 @@ QUnit.module("SlideCategoryOneToManyField", (hooks) => {
`,
});
- await clickEdit(target);
await click(target.querySelector(".o_data_row:nth-child(2) .o_data_cell"));
assert.containsNone(target, ".o_selected_row");
assert.containsOnce(target, ".modal .o_form_view");
@@ -179,7 +178,6 @@ QUnit.module("SlideCategoryOneToManyField", (hooks) => {
`,
});
- await clickEdit(target);
assert.containsNone(target, ".o_selected_row.o_is_section");
await click(target.querySelectorAll(".o_field_x2many_list_row_add a")[1]);
@@ -210,7 +208,6 @@ QUnit.module("SlideCategoryOneToManyField", (hooks) => {
`,
});
- await clickEdit(target);
await click(target.querySelector(".o_field_x2many_list_row_add a"));
assert.containsNone(target, ".o_selected_row");
assert.containsOnce(target, ".modal .o_form_view");
diff --git a/odoo/addons/test_main_flows/static/tests/tours/main_flow.js b/odoo/addons/test_main_flows/static/tests/tours/main_flow.js
index 20ab5d7a9dc..2c178f73a92 100644
--- a/odoo/addons/test_main_flows/static/tests/tours/main_flow.js
+++ b/odoo/addons/test_main_flows/static/tests/tours/main_flow.js
@@ -76,10 +76,10 @@ tour.stepUtils.openBuggerMenu("li.breadcrumb-item.active:contains('Quotations')"
content: _t("Save this product and the modifications you've made to it."),
position: 'bottom',
},
-tour.stepUtils.autoExpandMoreButtons('.o_form_readonly'),
+tour.stepUtils.autoExpandMoreButtons('.o_form_saved'),
{
trigger: ".oe_button_box .oe_stat_button div[name=bom_count]",
- extra_trigger: '.o_form_readonly',
+ extra_trigger: '.o_form_saved',
content: _t('See Bill of material'),
position: 'bottom',
}, {
@@ -148,7 +148,7 @@ tour.stepUtils.autoExpandMoreButtons('.o_form_readonly'),
}, {
mobile: false,
trigger: ".o_field_widget[name=partner_id] input",
- extra_trigger: ".modal-dialog",
+ extra_trigger: ".breadcrumb-item.active:contains(the_flow.component1)",
content: _t('Select a seller'),
position: 'top',
run: "text the_flow.vendor",
@@ -206,23 +206,21 @@ tour.stepUtils.autoExpandMoreButtons('.o_form_readonly'),
}, {
mobile: true,
trigger: '.o_field_widget[name=code] input',
- extra_trigger: ".o_field_widget[name=product_id] .o_external_button", // Wait name_create
// click somewhere else to exit cell focus
}, {
mobile: false,
trigger: 'label:contains("Vendor Taxes")',
- extra_trigger: ".o_field_widget[name=partner_id] .o_external_button", // Wait name_create
// click somewhere else to exit cell focus
}, {
mobile: false,
- trigger: ".modal-footer .o_form_button_save",
- content: _t('Save'),
+ trigger: '.breadcrumb .o_back_button',
+ content: _t('Go back'),
position: 'bottom',
}, {
// Add second component
mobile: false,
trigger: ".o_field_x2many_list_row_add > a",
- extra_trigger: "body:not(:has(table.o_list_table div.o_field_widget[name='product_id'] input))",
+ extra_trigger: ".breadcrumb-item.active:contains('the_flow.product')",
content: _t("Click here to add some lines."),
position: "bottom",
}, {
@@ -290,7 +288,7 @@ tour.stepUtils.autoExpandMoreButtons('.o_form_readonly'),
}, {
mobile: false,
trigger: ".o_field_widget[name=partner_id] input",
- extra_trigger: ".modal-dialog",
+ extra_trigger: ".breadcrumb-item.active:contains(the_flow.component2)",
content: _t('Select a seller'),
position: 'top',
run: "text the_flow.vendor",
@@ -320,7 +318,6 @@ tour.stepUtils.autoExpandMoreButtons('.o_form_readonly'),
}, {
mobile: true,
trigger: '.o_field_widget[name=code] input',
- extra_trigger: ".o_field_widget[name=product_id] .o_external_button", // Wait name_create
// click somewhere else to exit cell focus
}, {
mobile: false,
@@ -328,13 +325,8 @@ tour.stepUtils.autoExpandMoreButtons('.o_form_readonly'),
// click somewhere else to exit cell focus
}, {
mobile: false,
- trigger: ".modal-footer .o_form_button_save",
- content: _t('Save'),
- position: 'bottom',
-}, {
- trigger: '.o_form_button_save',
- extra_trigger: ".o_field_widget[name=bom_line_ids] tr:nth-child(3):has(.o_field_x2many_list_row_add)",
- content: _t('Save the bom.'),
+ trigger: '.breadcrumb .o_back_button',
+ content: _t('Go back'),
position: 'bottom',
}, {
mobile: false,
@@ -424,7 +416,6 @@ tour.stepUtils.autoExpandMoreButtons('.o_form_readonly'),
position: 'right',
}, {
trigger: '.o_form_button_save',
- extra_trigger: '.o_field_widget[name=project_id] .o_external_button', // Wait name_create
content: _t("Save this product and the modifications you've made to it."),
position: 'bottom',
}, {
@@ -486,18 +477,18 @@ tour.stepUtils.autoExpandMoreButtons('.o_form_readonly'),
position: "right",
}, {
mobile: false,
- trigger: ".o_kanban_group:first .o_kanban_record:has(span:contains('the_flow.opportunity'))",
+ trigger: ".o_kanban_group:first .o_kanban_record span:contains('the_flow.opportunity')",
content: Markup(_t("
Drag & drop opportunities between columns as you progress in your sales cycle.")),
position: "right",
run: "drag_and_drop_native .o_opportunity_kanban .o_kanban_group:eq(2) ",
}, {
mobile: false,
- trigger: ".o_kanban_group:eq(2) > .o_kanban_record:has(span:contains('the_flow.opportunity'))",
+ trigger: ".o_kanban_group:eq(2) > .o_kanban_record span:contains('the_flow.opportunity')",
content: _t("Click on an opportunity to zoom to it."),
position: "bottom",
}, {
mobile: true,
- trigger: ".o_kanban_group:first .o_kanban_record:has(span:contains('the_flow.opportunity'))",
+ trigger: ".o_kanban_group:first .o_kanban_record span:contains('the_flow.opportunity')",
content: _t("Open the_flow.opportunity"),
position: "bottom",
}, {
@@ -615,12 +606,6 @@ tour.stepUtils.autoExpandMoreButtons('.o_form_readonly'),
},
...tour.stepUtils.statusbarButtonsSteps('Confirm', Markup(_t("
Confirm this quotation
"))),
{
- trigger: ".o_form_button_save",
- extra_trigger: ".o_statusbar_status .btn-primary:contains('Sales Order')",
- content: Markup(_t("
Save this quotation
")),
- position: "bottom"
-// Reordering rule
-}, {
edition: "enterprise",
trigger: '.o_menu_toggle',
content: _t('Go back to the home menu'),
@@ -704,7 +689,7 @@ tour.stepUtils.openBuggerMenu("li.breadcrumb-item.active:contains('OP/')"),
position: 'bottom',
}, {
mobile: true,
- trigger: '.o_kanban_record:has(.o_kanban_record_title:contains("the_flow.vendor"))',
+ trigger: '.o_kanban_record .o_kanban_record_title:contains("the_flow.vendor")',
content: _t('Select the generated request for quotation'),
position: 'bottom',
},
@@ -723,11 +708,8 @@ tour.stepUtils.openBuggerMenu("li.breadcrumb-item.active:contains('OP/')"),
},
...tour.stepUtils.statusbarButtonsSteps('Create Bill', _t('go to Vendor Bills'), ".o_statusbar_status .btn.dropdown-toggle:contains('Purchase Order')"),
{
- trigger: '.o_form_button_edit',
- content: _t('Edit the vendor bill'),
- extra_trigger: ".o_form_label .o_field_widget:contains('Vendor Bill')",
-}, {
trigger:".o_field_widget[name=invoice_date] input",
+ extra_trigger: ".o_form_label .o_field_widget:contains('Vendor Bill')",
content: _t('Set the invoice date'),
run: "text 01/01/2020",
},
@@ -761,21 +743,28 @@ tour.stepUtils.openBuggerMenu("li.breadcrumb-item.active:contains('Manufacturing
position: 'bottom',
}, {
mobile: true,
- trigger: '.o_kanban_record:has(.o_kanban_record_title:contains("the_flow.product")):first',
+ trigger: '.o_kanban_record .o_kanban_record_title:contains("the_flow.product"):first',
extra_trigger: "li.breadcrumb-item.active:contains('Manufacturing Orders')",
content: _t('Select the generated manufacturing order'),
position: 'bottom',
},
-...tour.stepUtils.statusbarButtonsSteps('Check availability', _t("Check availability")),
+...tour.stepUtils.statusbarButtonsSteps('Unreserve', _t("Unreserve")),
{
- trigger: ".o_form_button_edit:not(:disabled)",
- content: _t('Edit the production order'),
-}, {
trigger: ".o_field_widget[name=qty_producing] input",
+ extra_trigger: ".o_field_widget[name=move_raw_ids] tr[data-id]:first .o_field_widget[name=forecast_availability]:contains('Available')",
position: 'left',
content: _t("Produce"),
run: "text 1",
},
+...tour.stepUtils.statusbarButtonsSteps('Check availability', _t("Check availability")),
+{
+ trigger: ".o_field_widget[name=qty_producing] input",
+ extra_trigger: ".o_field_widget[name=move_raw_ids] tr[data-id]:first .o_field_widget[name=forecast_availability]:contains('1')",
+ position: 'left',
+ content: _t("Produce"),
+ run: "text 1",
+},
+
...tour.stepUtils.statusbarButtonsSteps('Mark as Done', _t("Mark as Done"), ".o_statusbar_status .btn.dropdown-toggle:contains('To Close')"),
{
edition: "enterprise",
@@ -823,9 +812,6 @@ tour.stepUtils.mobileModifier(tour.stepUtils.autoExpandMoreButtons('.o_control_p
trigger: 'a.nav-link:contains(Timesheets)',
extra_trigger: 'div.o_notebook_headers',
content: 'Click on Timesheets page to log a timesheet',
-}, {
- trigger: '.o_form_button_edit',
- content: _t('Click on Edit button to enter to the form view of the task.'),
}, {
mobile: false,
trigger: 'div[name="timesheet_ids"] td.o_field_x2many_list_row_add a[role="button"]',
@@ -833,7 +819,7 @@ tour.stepUtils.mobileModifier(tour.stepUtils.autoExpandMoreButtons('.o_control_p
}, {
mobile: true,
trigger: '.o-kanban-button-new',
- content: _t("Click on Add in order to add a timesheet."),
+ content: _t('Open the full search field'),
position: 'bottom',
}, {
mobile: false,
@@ -856,9 +842,8 @@ tour.stepUtils.mobileModifier(tour.stepUtils.autoExpandMoreButtons('.o_control_p
content: 'Enter one hour for this timesheet',
run: 'text 10',
}, {
- trigger: '.o_form_button_save',
- content: _t('Save'),
- position: 'bottom',
+ content: "save",
+ trigger: ".o_form_button_save",
},
...tour.stepUtils.goBackBreadcrumbsMobile(
_t('Back to the sale order'),
diff --git a/odoo/addons/test_new_api/static/tests/tours/constraint.js b/odoo/addons/test_new_api/static/tests/tours/constraint.js
index e273d14ae32..892adbc7e96 100644
--- a/odoo/addons/test_new_api/static/tests/tours/constraint.js
+++ b/odoo/addons/test_new_api/static/tests/tours/constraint.js
@@ -30,7 +30,7 @@ odoo.define('web.test.constraint', function (require) {
run() {}
}, {
content: "close notification box",
- trigger: '.modal-footer .o-default-button',
+ trigger: '.modal-footer .btn-primary',
},
...tour.stepUtils.discardForm(),
]);
diff --git a/odoo/addons/test_new_api/static/tests/tours/x2many.js b/odoo/addons/test_new_api/static/tests/tours/x2many.js
index 04d161bb84e..5687013e26e 100644
--- a/odoo/addons/test_new_api/static/tests/tours/x2many.js
+++ b/odoo/addons/test_new_api/static/tests/tours/x2many.js
@@ -69,14 +69,10 @@ odoo.define('web.test.x2many', function (require) {
content: "save selected participants",
trigger: '.o_select_button',
extra_trigger: 'tr:has(td:containsExact(Mitchell Admin)) .o_list_record_selector input[type="checkbox"]:propChecked',
- }, { // save
+ }, ...tour.stepUtils.saveForm({
content: "save discussion",
- trigger: 'button.o_form_button_save',
extra_trigger: '.o_field_widget[name=participants] .o_data_cell:containsExact(Mitchell Admin)',
- }, { // edit
- content: "edit discussion",
- trigger: 'button.o_form_button_edit',
- }, { // add message a
+ }), { // add message a
content: "Select First Tab",
trigger: '.o_notebook_headers .nav-item a:contains(Messages)',
}, {
@@ -168,9 +164,6 @@ odoo.define('web.test.x2many', function (require) {
trigger: '.o_content:has(.o_field_widget[name=participants] tbody .o_data_row:eq(2))',
extra_trigger: 'body:not(:has(.o_field_widget[name=participants] tbody .o_data_row:eq(3)))',
run: function () {}, // it's a check
- }, { // edit
- content: "edit discussion",
- trigger: 'button.o_form_button_edit',
}, {
content: "change tab to Messages",
trigger: '.o_notebook_headers .nav-item a:contains(Messages)',
@@ -269,9 +262,6 @@ odoo.define('web.test.x2many', function (require) {
trigger: '.o_content:has(.o_field_widget[name=participants] tbody .o_data_row:eq(2))',
extra_trigger: '.o_content:not(:has(.o_field_widget[name=participants] tbody .o_data_row:eq(3)))',
run: function () {}, // it's a check
- }, { // edit
- content: "edit discussion",
- trigger: 'button.o_form_button_edit',
}, {
content: "go to Messages",
trigger: '.o_notebook_headers .nav-item a:contains(Messages)',
@@ -306,12 +296,10 @@ odoo.define('web.test.x2many', function (require) {
trigger: '.o_content:has(.o_field_widget[name=messages] .o_data_row:eq(3))',
extra_trigger: 'body:not(:has(.o_field_widget[name=messages] .o_data_row:eq(4)))',
run: function () {}, // it's a check
- }, { // cancel
+ }, ...tour.stepUtils.discardForm({ // cancel
content: "cancel change",
- trigger: '.o_cp_buttons .o_form_button_cancel',
extra_trigger: '.o_field_widget[name=messages]:has(tr td:containsExact(ddd))',
- run: 'click',
- },
+ }),
/////////////////////////////////////////////////////////////////////////////////////////////
// Discussions 2
@@ -327,9 +315,6 @@ odoo.define('web.test.x2many', function (require) {
content: "select previous created record",
trigger: 'td:contains(test_trigger):last',
extra_trigger: '.breadcrumb-item:contains(Discussions 2)',
- }, {
- content: "click on edit",
- trigger: '.o_cp_buttons .o_form_button_edit',
}, {
content: "edit content",
trigger: '.o_field_widget[name=name] input',
@@ -390,22 +375,18 @@ odoo.define('web.test.x2many', function (require) {
content: "test one2many onchange after delete",
trigger: '.o_content:not(:has(.o_field_widget[name="message_concat"] textarea:propValueContains(Mitchell Admin:d)))',
run: function () {},
- }, { // save
+ }, ...tour.stepUtils.saveForm({ // save
content: "save discussion",
- trigger: 'button.o_form_button_save',
extra_trigger: 'body:not(:has(tr:has(td:containsExact(d))))',
- }, { // check saved data
+ }), { // check saved data
content: "check data 10",
- trigger: '.o_field_widget[name=message_concat] span:containsExact([test_trigger2] Mitchell Admin:aaa\n[test_trigger2] Marc Demo:ccccc)',
+ trigger: '.o_field_widget[name=message_concat] textarea:propValueContains([test_trigger2] Mitchell Admin:aaa\n[test_trigger2] Marc Demo:ccccc)',
run: function () {}, // don't change texarea content
}, {
content: "check data 11",
trigger: '.o_field_widget[name=messages] tbody .o_data_row:eq(1)',
extra_trigger: 'body:not(:has(.o_field_widget[name=messages] tbody .o_data_row:eq(2)))',
run: function () {},
- }, { // edit
- content: "edit discussion",
- trigger: 'button.o_form_button_edit'
}, { // add message eee
content: "create new message eee",
trigger: '.o_field_widget[name=messages] .o_field_x2many_list_row_add a',
@@ -414,13 +395,12 @@ odoo.define('web.test.x2many', function (require) {
content: "change text value",
trigger: '.o_field_widget[name="body"] textarea',
run: 'text eee'
- }, { // save
+ }, ...tour.stepUtils.saveForm({ // save
content: "save discussion",
- trigger: 'button.o_form_button_save',
extra_trigger: '.o_field_widget[name="body"] textarea:propValueContains(eee)',
- }, { // check saved data
+ }), { // check saved data
content: "check data 12",
- trigger: '.o_field_widget[name="message_concat"] span:containsExact([test_trigger2] Mitchell Admin:aaa\n[test_trigger2] Marc Demo:ccccc\n[test_trigger2] Mitchell Admin:eee)',
+ trigger: '.o_field_widget[name="message_concat"] textarea:propValueContains([test_trigger2] Mitchell Admin:aaa\n[test_trigger2] Marc Demo:ccccc\n[test_trigger2] Mitchell Admin:eee)',
run: function () {}, // it's a check
}, {
content: "check data 13",
diff --git a/odoo/tests/common.py b/odoo/tests/common.py
index 58ef4a315ea..4002f07fbab 100644
--- a/odoo/tests/common.py
+++ b/odoo/tests/common.py
@@ -1299,7 +1299,7 @@ class ChromeBrowser:
self._websocket_send('DOM.getDocument', params={'depth': 0}, with_future=True),
lambda d: self._websocket_send("DOM.querySelector", params={
'nodeId': d['root']['nodeId'],
- 'selector': '.o_form_editable',
+ 'selector': '.o_legacy_form_view.o_form_editable, .o_form_dirty',
}, with_future=True)
)
@qs.add_done_callback