diff --git a/addons/board/static/tests/dashboard_tests.js b/addons/board/static/tests/dashboard_tests.js
index 86e203c7d9bf8..5510be32bd9f0 100644
--- a/addons/board/static/tests/dashboard_tests.js
+++ b/addons/board/static/tests/dashboard_tests.js
@@ -9,11 +9,16 @@ var ListRenderer = require('web.ListRenderer');
var pyUtils = require('web.py_utils');
const cpHelpers = testUtils.controlPanel;
-var createActionManager = testUtils.createActionManager;
+const {
+ createWebClient,
+ doAction,
+ getActionManagerTestConfig,
+} = require("@web/../tests/webclient/actions/helpers");
var createView = testUtils.createView;
const patchDate = testUtils.mock.patchDate;
+let testConfig;
QUnit.module('Dashboard', {
beforeEach: function () {
this.data = {
@@ -48,6 +53,9 @@ QUnit.module('Dashboard', {
}],
},
};
+ testConfig = getActionManagerTestConfig();
+ // map legacy test data
+ Object.assign(testConfig.serverData, { models: this.data });
},
});
@@ -696,143 +704,156 @@ QUnit.test('dashboard intercepts custom events triggered by sub controllers', as
board.destroy();
});
-QUnit.skip('save actions to dashboard', async function (assert) {
+QUnit.test("save actions to dashboard", async function (assert) {
assert.expect(6);
testUtils.patch(ListController, {
getOwnedQueryParams: function () {
var result = this._super.apply(this, arguments);
result.context = {
- 'fire': 'on the bayou',
+ fire: "on the bayou",
};
return result;
- }
+ },
});
- this.data['partner'].fields.foo.sortable = true;
-
- var actionManager = await createActionManager({
- data: this.data,
- archs: {
- 'partner,false,list': '
',
- 'partner,false,search': '',
- },
- mockRPC: function (route, args) {
- if (route === '/board/add_to_dashboard') {
- assert.deepEqual(args.context_to_save.group_by, ['foo'],
- 'The group_by should have been saved');
- assert.deepEqual(args.context_to_save.orderedBy,
- [{
- name: 'foo',
+ testConfig.serverData.models["partner"].fields.foo.sortable = true;
+
+ testConfig.serverData.views = {
+ "partner,false,list": '
',
+ "partner,false,search": "",
+ };
+
+ const mockRPC = (route, args) => {
+ if (route === "/board/add_to_dashboard") {
+ assert.deepEqual(
+ args.context_to_save.group_by,
+ ["foo"],
+ "The group_by should have been saved"
+ );
+ assert.deepEqual(
+ args.context_to_save.orderedBy,
+ [
+ {
+ name: "foo",
asc: true,
- }],
- 'The orderedBy should have been saved');
- assert.strictEqual(args.context_to_save.fire, 'on the bayou',
- 'The context of a controller should be passed and flattened');
- assert.strictEqual(args.action_id, 1,
- "should save the correct action");
- assert.strictEqual(args.view_mode, 'list',
- "should save the correct view type");
- return Promise.resolve(true);
- }
- return this._super.apply(this, arguments);
+ },
+ ],
+ "The orderedBy should have been saved"
+ );
+ assert.strictEqual(
+ args.context_to_save.fire,
+ "on the bayou",
+ "The context of a controller should be passed and flattened"
+ );
+ assert.strictEqual(args.action_id, 1, "should save the correct action");
+ assert.strictEqual(args.view_mode, "list", "should save the correct view type");
+ return Promise.resolve(true);
}
- });
+ };
- await actionManager.doAction({
+ const webClient = await createWebClient({ testConfig, mockRPC });
+
+ await doAction(webClient, {
id: 1,
- res_model: 'partner',
- type: 'ir.actions.act_window',
- views: [[false, 'list']],
+ res_model: "partner",
+ type: "ir.actions.act_window",
+ views: [[false, "list"]],
});
- assert.containsOnce(actionManager, '.o_list_view',
- "should display the list view");
+ assert.containsOnce(webClient, ".o_list_view", "should display the list view");
// Sort the list
- await testUtils.dom.click($('.o_column_sortable'));
+ await testUtils.dom.click($(".o_column_sortable"));
// Group It
- await cpHelpers.toggleGroupByMenu(actionManager);
- await cpHelpers.toggleAddCustomGroup(actionManager);
- await cpHelpers.applyGroup(actionManager);
+ await cpHelpers.toggleGroupByMenu(webClient);
+ await cpHelpers.toggleAddCustomGroup(webClient);
+ await cpHelpers.applyGroup(webClient);
// add this action to dashboard
- await cpHelpers.toggleFavoriteMenu(actionManager);
+ await cpHelpers.toggleFavoriteMenu(webClient);
- await testUtils.dom.click($('.o_add_to_board > button'));
- await testUtils.fields.editInput($('.o_add_to_board input'), 'a name');
- await testUtils.dom.click($('.o_add_to_board div button'));
+ await testUtils.dom.click($(".o_add_to_board > button"));
+ await testUtils.fields.editInput($(".o_add_to_board input"), "a name");
+ await testUtils.dom.click($(".o_add_to_board div button"));
testUtils.unpatch(ListController);
-
- actionManager.destroy();
});
-QUnit.skip('save two searches to dashboard', async function (assert) {
+QUnit.test("save two searches to dashboard", async function (assert) {
// the second search saved should not be influenced by the first
assert.expect(2);
- var actionManager = await createActionManager({
- data: this.data,
- archs: {
- 'partner,false,list': '
',
- 'partner,false,search': '',
- },
- mockRPC: function (route, args) {
- if (route === '/board/add_to_dashboard') {
- if (filter_count === 0) {
- assert.deepEqual(args.domain, [["display_name", "ilike", "a"]],
- "the correct domain should be sent");
- }
- if (filter_count === 1) {
- assert.deepEqual(args.domain, [["display_name", "ilike", "b"]],
- "the correct domain should be sent");
- }
-
- filter_count += 1;
- return Promise.resolve(true);
+ testConfig.serverData.views = {
+ "partner,false,list": '
',
+ "partner,false,search": "",
+ };
+
+ const mockRPC = (route, args) => {
+ if (route === "/board/add_to_dashboard") {
+ if (filter_count === 0) {
+ assert.deepEqual(
+ args.domain,
+ [["display_name", "ilike", "a"]],
+ "the correct domain should be sent"
+ );
}
- return this._super.apply(this, arguments);
- },
- });
+ if (filter_count === 1) {
+ assert.deepEqual(
+ args.domain,
+ [["display_name", "ilike", "b"]],
+ "the correct domain should be sent"
+ );
+ }
+
+ filter_count += 1;
+ return Promise.resolve(true);
+ }
+ };
+
+ const webClient = await createWebClient({ testConfig, mockRPC });
- await actionManager.doAction({
+ await doAction(webClient, {
id: 1,
- res_model: 'partner',
- type: 'ir.actions.act_window',
- views: [[false, 'list']],
+ res_model: "partner",
+ type: "ir.actions.act_window",
+ views: [[false, "list"]],
});
var filter_count = 0;
// Add a first filter
- await cpHelpers.toggleFilterMenu(actionManager);
- await cpHelpers.toggleAddCustomFilter(actionManager);
- await testUtils.fields.editInput(actionManager.el.querySelector('.o_generator_menu_value .o_input'), 'a');
- await cpHelpers.applyFilter(actionManager);
+ await cpHelpers.toggleFilterMenu(webClient);
+ await cpHelpers.toggleAddCustomFilter(webClient);
+ await testUtils.fields.editInput(
+ webClient.el.querySelector(".o_generator_menu_value .o_input"),
+ "a"
+ );
+ await cpHelpers.applyFilter(webClient);
// Add it to dashboard
- await cpHelpers.toggleFavoriteMenu(actionManager);
- await testUtils.dom.click($('.o_add_to_board > button'));
- await testUtils.dom.click($('.o_add_to_board div button'));
+ await cpHelpers.toggleFavoriteMenu(webClient);
+ await testUtils.dom.click($(".o_add_to_board > button"));
+ await testUtils.dom.click($(".o_add_to_board div button"));
// Remove it
- await testUtils.dom.click(actionManager.el.querySelector('.o_facet_remove'));
+ await testUtils.dom.click(webClient.el.querySelector(".o_facet_remove"));
// Add the second filter
- await cpHelpers.toggleFilterMenu(actionManager);
- await cpHelpers.toggleAddCustomFilter(actionManager);
- await testUtils.fields.editInput(actionManager.el.querySelector('.o_generator_menu_value .o_input'), "b");
- await cpHelpers.applyFilter(actionManager);
+ await cpHelpers.toggleFilterMenu(webClient);
+ await cpHelpers.toggleAddCustomFilter(webClient);
+ await testUtils.fields.editInput(
+ webClient.el.querySelector(".o_generator_menu_value .o_input"),
+ "b"
+ );
+ await cpHelpers.applyFilter(webClient);
// Add it to dashboard
- await cpHelpers.toggleFavoriteMenu(actionManager);
- await testUtils.dom.click(actionManager.el.querySelector('.o_add_to_board > button'));
- await testUtils.dom.click(actionManager.el.querySelector('.o_add_to_board div button'));
-
- actionManager.destroy();
+ await cpHelpers.toggleFavoriteMenu(webClient);
+ await testUtils.dom.click(webClient.el.querySelector(".o_add_to_board > button"));
+ await testUtils.dom.click(webClient.el.querySelector(".o_add_to_board div button"));
});
-QUnit.skip('save a action domain to dashboard', async function (assert) {
+QUnit.test("save a action domain to dashboard", async function (assert) {
// View domains are to be added to the dashboard domain
assert.expect(1);
@@ -840,47 +861,43 @@ QUnit.skip('save a action domain to dashboard', async function (assert) {
var filter_domain = ["display_name", "ilike", "b"];
// The filter domain already contains the view domain, but is always added by dashboard..,
- var expected_domain = ['&', view_domain, '&', view_domain, filter_domain];
+ var expected_domain = ["&", view_domain, "&", view_domain, filter_domain];
- var actionManager = await createActionManager({
- data: this.data,
- archs: {
- 'partner,false,list': '
',
- 'partner,false,search': '',
- },
- mockRPC: function (route, args) {
- if (route === '/board/add_to_dashboard') {
- assert.deepEqual(args.domain, expected_domain,
- "the correct domain should be sent");
- return Promise.resolve(true);
- }
- return this._super.apply(this, arguments);
- },
- });
+ testConfig.serverData.views = {
+ "partner,false,list": '
',
+ "partner,false,search": "",
+ };
+
+ const mockRPC = (route, args) => {
+ if (route === "/board/add_to_dashboard") {
+ assert.deepEqual(args.domain, expected_domain, "the correct domain should be sent");
+ return Promise.resolve(true);
+ }
+ };
+
+ const webClient = await createWebClient({ testConfig, mockRPC });
- await actionManager.doAction({
+ await doAction(webClient, {
id: 1,
- res_model: 'partner',
- type: 'ir.actions.act_window',
- views: [[false, 'list']],
+ res_model: "partner",
+ type: "ir.actions.act_window",
+ views: [[false, "list"]],
domain: [view_domain],
});
// Add a filter
- await cpHelpers.toggleFilterMenu(actionManager);
- await cpHelpers.toggleAddCustomFilter(actionManager);
+ await cpHelpers.toggleFilterMenu(webClient);
+ await cpHelpers.toggleAddCustomFilter(webClient);
await testUtils.fields.editInput(
- actionManager.el.querySelector('.o_generator_menu_value .o_input'),
+ webClient.el.querySelector(".o_generator_menu_value .o_input"),
"b"
);
- await cpHelpers.applyFilter(actionManager);
+ await cpHelpers.applyFilter(webClient);
// Add it to dashboard
- await cpHelpers.toggleFavoriteMenu(actionManager);
- await testUtils.dom.click(actionManager.el.querySelector('.o_add_to_board > button'));
+ await cpHelpers.toggleFavoriteMenu(webClient);
+ await testUtils.dom.click(webClient.el.querySelector(".o_add_to_board > button"));
// add
- await testUtils.dom.click(actionManager.el.querySelector('.o_add_to_board div button'));
-
- actionManager.destroy();
+ await testUtils.dom.click(webClient.el.querySelector(".o_add_to_board div button"));
});
QUnit.test("Views should be loaded in the user's language", async function (assert) {
@@ -1041,62 +1058,71 @@ QUnit.test('click on a cell of pivot view inside dashboard', async function (ass
form.destroy();
});
-QUnit.skip('correctly save the time ranges of a reporting view in comparison mode', async function (assert) {
- assert.expect(1);
+QUnit.test(
+ "correctly save the time ranges of a reporting view in comparison mode",
+ async function (assert) {
+ assert.expect(1);
- const unpatchDate = patchDate(2020, 6, 1, 11, 0, 0);
+ const unpatchDate = patchDate(2020, 6, 1, 11, 0, 0);
- this.data.partner.fields.date = { string: 'Date', type: 'date', sortable: true };
+ testConfig.serverData.models.partner.fields.date = {
+ string: "Date",
+ type: "date",
+ sortable: true,
+ };
- const actionManager = await createActionManager({
- data: this.data,
- archs: {
- 'partner,false,pivot': '',
- 'partner,false,search': '',
- },
- mockRPC: function (route, args) {
- if (route === '/board/add_to_dashboard') {
+ testConfig.serverData.views = {
+ "partner,false,pivot": '',
+ "partner,false,search": '',
+ };
+
+ const mockRPC = (route, args) => {
+ if (route === "/board/add_to_dashboard") {
assert.deepEqual(args.context_to_save.comparison, {
comparisonId: "previous_period",
fieldName: "date",
fieldDescription: "Date",
rangeDescription: "July 2020",
- range: ["&",["date", ">=", "2020-07-01"], ["date", "<=", "2020-07-31"]],
- comparisonRange: ["&", ["date", ">=", "2020-06-01"], ["date", "<=", "2020-06-30"]],
+ range: ["&", ["date", ">=", "2020-07-01"], ["date", "<=", "2020-07-31"]],
+ comparisonRange: [
+ "&",
+ ["date", ">=", "2020-06-01"],
+ ["date", "<=", "2020-06-30"],
+ ],
comparisonRangeDescription: "June 2020",
});
return Promise.resolve(true);
}
- return this._super.apply(this, arguments);
- },
- });
+ };
- await actionManager.doAction({
- id: 1,
- res_model: 'partner',
- type: 'ir.actions.act_window',
- views: [[false, 'pivot']],
- });
+ const webClient = await createWebClient({ testConfig, mockRPC });
- // filter on July 2020
- await cpHelpers.toggleFilterMenu(actionManager);
- await cpHelpers.toggleMenuItem(actionManager, 'Date');
- await cpHelpers.toggleMenuItemOption(actionManager, 'Date', 'July');
+ await doAction(webClient, {
+ id: 1,
+ res_model: "partner",
+ type: "ir.actions.act_window",
+ views: [[false, "pivot"]],
+ });
- // compare July 2020 to June 2020
- await cpHelpers.toggleComparisonMenu(actionManager);
- await cpHelpers.toggleMenuItem(actionManager, 0);
+ // filter on July 2020
+ await cpHelpers.toggleFilterMenu(webClient);
+ await cpHelpers.toggleMenuItem(webClient, "Date");
+ await cpHelpers.toggleMenuItemOption(webClient, "Date", "July");
- // add the view to the dashboard
- await cpHelpers.toggleFavoriteMenu(actionManager);
+ // compare July 2020 to June 2020
+ await cpHelpers.toggleComparisonMenu(webClient);
+ await cpHelpers.toggleMenuItem(webClient, 0);
- await testUtils.dom.click($('.o_add_to_board > button'));
- await testUtils.fields.editInput($('.o_add_to_board input'), 'a name');
- await testUtils.dom.click($('.o_add_to_board div button'));
+ // add the view to the dashboard
+ await cpHelpers.toggleFavoriteMenu(webClient);
- unpatchDate();
- actionManager.destroy();
-});
+ await testUtils.dom.click($(".o_add_to_board > button"));
+ await testUtils.fields.editInput($(".o_add_to_board input"), "a name");
+ await testUtils.dom.click($(".o_add_to_board div button"));
+
+ unpatchDate();
+ }
+);
QUnit.test('correctly display the time range descriptions of a reporting view in comparison mode', async function (assert) {
assert.expect(1);
diff --git a/addons/bus/static/tests/assets_watchdog_tests.js b/addons/bus/static/tests/assets_watchdog_tests.js
index e96ceaca835bc..175a069176e2c 100644
--- a/addons/bus/static/tests/assets_watchdog_tests.js
+++ b/addons/bus/static/tests/assets_watchdog_tests.js
@@ -82,6 +82,5 @@ QUnit.module("Bus Assets WatchDog", (hooks) => {
// reload by clicking on the reload button
await click(webClient.el, ".o_notification_buttons .btn-primary");
assert.verifySteps(["reloadPage"]);
- webClient.destroy();
});
});
diff --git a/addons/calendar/static/tests/calendar_notification_tests.js b/addons/calendar/static/tests/calendar_notification_tests.js
index 69a04d46a2408..9ac4238b81c28 100644
--- a/addons/calendar/static/tests/calendar_notification_tests.js
+++ b/addons/calendar/static/tests/calendar_notification_tests.js
@@ -98,8 +98,6 @@ QUnit.module("Calendar Notification", (hooks) => {
await click(webClient.el.querySelector(".o_notification_buttons .btn"));
assert.verifySteps(["notifyAck"]);
assert.containsNone(webClient.el, ".o_notification");
-
- webClient.destroy();
}
);
@@ -171,8 +169,6 @@ QUnit.module("Calendar Notification", (hooks) => {
await click(webClient.el.querySelectorAll(".o_notification_buttons .btn")[1]);
assert.verifySteps(["calendar.action_calendar_event_notify"]);
assert.containsNone(webClient.el, ".o_notification");
-
- webClient.destroy();
}
);
@@ -232,8 +228,6 @@ QUnit.module("Calendar Notification", (hooks) => {
await click(webClient.el.querySelectorAll(".o_notification_buttons .btn")[2]);
assert.verifySteps([], "should only close the notification withtout calling a rpc");
assert.containsNone(webClient.el, ".o_notification");
-
- webClient.destroy();
}
);
});
diff --git a/addons/mail/static/src/utils/test_utils.js b/addons/mail/static/src/utils/test_utils.js
index 3d94c28b9df7b..0919be6314632 100644
--- a/addons/mail/static/src/utils/test_utils.js
+++ b/addons/mail/static/src/utils/test_utils.js
@@ -18,12 +18,17 @@ import AbstractStorageService from 'web.AbstractStorageService';
import NotificationService from 'web.NotificationService';
import RamStorage from 'web.RamStorage';
import {
- createActionManager,
createView,
makeTestPromise,
mock,
} from 'web.test_utils';
import Widget from 'web.Widget';
+import {
+ createWebClient,
+ getActionManagerTestConfig,
+} from "@web/../tests/webclient/actions/helpers";
+import { ComponentAdapter } from "web.OwlCompatibility";
+import LegacyMockServer from "web.MockServer";
const {
addMockEnvironment,
@@ -546,8 +551,36 @@ async function start(param0 = {}) {
}
});
} else if (hasActionManager) {
- throw new Error("This is deprecated, should be adapted");
- widget = await createActionManager(kwargs);
+ let testConfig;
+ if (!kwargs.testConfig) {
+ testConfig = getActionManagerTestConfig();
+ } else {
+ testConfig = kwargs.testConfig;
+ delete kwargs.testConfig;
+ }
+
+ if (kwargs.actions) {
+ const actions = {};
+ kwargs.actions.forEach((act) => {
+ actions[act.xml_id || act.id] = act;
+ });
+ Object.assign(testConfig.serverData.actions, actions);
+ delete kwargs.actions;
+ }
+
+ Object.assign(testConfig.serverData.views, kwargs.archs);
+ delete kwargs.archs;
+
+ Object.assign(testConfig.serverData.models, kwargs.data);
+ delete kwargs.data;
+
+ const mockRPC = kwargs.mockRPC;
+ delete kwargs.mockRPC;
+
+ const legacyParams = kwargs;
+ legacyParams.withLegacyMockServer = true;
+ const widget = await createWebClient({ testConfig, mockRPC, legacyParams });
+
legacyPatch(widget, {
destroy() {
destroyCallbacks.forEach(callback => callback({ widget }));
diff --git a/addons/mail/static/tests/activity_tests.js b/addons/mail/static/tests/activity_tests.js
index bd01586654a0a..92af5da6c6bf5 100644
--- a/addons/mail/static/tests/activity_tests.js
+++ b/addons/mail/static/tests/activity_tests.js
@@ -2,8 +2,14 @@
import ActivityView from '@mail/js/views/activity/activity_view';
import testUtils from 'web.test_utils';
+import { createWebClient } from "@web/../tests/webclient/actions/helpers";
-var createActionManager = testUtils.createActionManager;
+import { legacyExtraNextTick } from "@web/../tests/helpers/utils";
+import { doAction, getActionManagerTestConfig } from "@web/../tests/webclient/actions/helpers";
+import { registry } from "@web/core/registry";
+import { makeFakeUserService } from "@web/../tests/helpers/mock_services";
+
+let testConfig;
var createView = testUtils.createView;
@@ -108,6 +114,8 @@ QUnit.module('activity view', {
],
},
};
+ testConfig = getActionManagerTestConfig();
+ Object.assign(testConfig.serverData.models, this.data);
}
});
@@ -350,49 +358,68 @@ QUnit.test('activity view: activity widget', async function (assert) {
activity.destroy();
});
-QUnit.skip('activity view: no group_by_menu and no comparison_menu', async function (assert) {
+
+QUnit.test("activity view: no group_by_menu and no comparison_menu", async function (assert) {
assert.expect(4);
- var actionManager = await createActionManager({
- actions: [{
- id: 1,
- name: 'Task Action',
- res_model: 'task',
- type: 'ir.actions.act_window',
- views: [[false, 'activity']],
- }],
- archs: {
- 'task,false,activity': '' +
- '' +
- '' +
- '' +
- '
' +
- '' +
- '',
- 'task,false,search': '',
- },
- data: this.data,
- session: {
- user_context: {lang: 'zz_ZZ'},
- },
- mockRPC: function(route, args) {
- if (args.method === 'get_activity_data') {
- assert.deepEqual(args.kwargs.context, {lang: 'zz_ZZ'},
- 'The context should have been passed');
- }
- return this._super.apply(this, arguments);
- },
- });
+ testConfig.serverData.actions[1] = {
+ id: 1,
+ name: "Task Action",
+ res_model: "task",
+ type: "ir.actions.act_window",
+ views: [[false, "activity"]],
+ };
- await actionManager.doAction(1);
+ testConfig.serverData.views = {
+ "task,false,activity":
+ '' +
+ "" +
+ '' +
+ '' +
+ "
" +
+ "" +
+ "",
+ "task,false,search": "",
+ };
+
+ const mockRPC = (route, args) => {
+ if (args.method === "get_activity_data") {
+ assert.strictEqual(
+ args.kwargs.context.lang,
+ "zz_ZZ",
+ "The context should have been passed"
+ );
+ }
+ };
- assert.containsN(actionManager, '.o_search_options .o_dropdown button:visible', 2,
- "only two elements should be available in view search");
- assert.isVisible(actionManager.$('.o_search_options .o_dropdown.o_filter_menu > button'),
- "filter should be available in view search");
- assert.isVisible(actionManager.$('.o_search_options .o_dropdown.o_favorite_menu > button'),
- "favorites should be available in view search");
- actionManager.destroy();
+ registry.category("services").add(
+ "user",
+ makeFakeUserService({
+ session_info: {
+ user_context: { lang: "zz_ZZ" },
+ },
+ }),
+ { force: true }
+ );
+
+ const webClient = await createWebClient({ testConfig, mockRPC , legacyParams: {withLegacyMockServer: true}});
+
+ await doAction(webClient, 1);
+
+ assert.containsN(
+ webClient,
+ ".o_search_options .o_dropdown button:visible",
+ 2,
+ "only two elements should be available in view search"
+ );
+ assert.isVisible(
+ $(webClient.el).find(".o_search_options .o_dropdown.o_filter_menu > button"),
+ "filter should be available in view search"
+ );
+ assert.isVisible(
+ $(webClient.el).find(".o_search_options .o_dropdown.o_favorite_menu > button"),
+ "favorites should be available in view search"
+ );
});
QUnit.test('activity view: search more to schedule an activity for a record of a respecting model', async function (assert) {
@@ -458,63 +485,54 @@ QUnit.test('activity view: search more to schedule an activity for a record of a
activity.destroy();
});
-QUnit.skip('Activity view: discard an activity creation dialog', async function (assert) {
+QUnit.test("Activity view: discard an activity creation dialog", async function (assert) {
assert.expect(2);
- var actionManager = await createActionManager({
- actions: [{
- id: 1,
- name: 'Task Action',
- res_model: 'task',
- type: 'ir.actions.act_window',
- views: [[false, 'activity']],
- }],
- archs: {
- 'task,false,activity': `
-
-
-
-
-
-
- `,
- 'task,false,search': '',
- 'mail.activity,false,form': `
-
`
- },
- data: this.data,
- intercepts: {
- do_action(ev) {
- actionManager.doAction(ev.data.action, ev.data.options);
- }
- },
- async mockRPC(route, args) {
- if (args.method === 'check_access_rights') {
- return true;
- }
- return this._super(...arguments);
- },
- });
- await actionManager.doAction(1);
+ testConfig.serverData.actions[1] = {
+ id: 1,
+ name: "Task Action",
+ res_model: "task",
+ type: "ir.actions.act_window",
+ views: [[false, "activity"]],
+ };
+
+ testConfig.serverData.views = {
+ "task,false,activity": `
+
+
+
+
+
+
+ `,
+ "task,false,search": "",
+ "mail.activity,false,form": `
+ `,
+ };
+
+ const mockRPC = (route, args) => {
+ if (args.method === "check_access_rights") {
+ return true;
+ }
+ };
- await testUtils.dom.click(actionManager.$('.o_activity_view .o_data_row .o_activity_empty_cell')[0]);
- assert.containsOnce(
- $,
- '.modal.o_technical_modal.show',
- "Activity Modal should be opened");
+ const webClient = await createWebClient({ testConfig, mockRPC, legacyParams: {withLegacyMockServer: true} });
+ await doAction(webClient, 1);
- await testUtils.dom.click($('.modal.o_technical_modal.show button[special="cancel"]'));
- assert.containsNone(
- $,
- '.modal.o_technical_modal.show',
- "Activity Modal should be closed");
+ await testUtils.dom.click(
+ $(webClient.el).find(".o_activity_view .o_data_row .o_activity_empty_cell")[0]
+ );
+ await legacyExtraNextTick();
+ assert.containsOnce($, ".modal.o_technical_modal", "Activity Modal should be opened");
- actionManager.destroy();
+ await testUtils.dom.click($('.modal.o_technical_modal button[special="cancel"]'));
+ await legacyExtraNextTick();
+ assert.containsNone($, ".modal.o_technical_modal", "Activity Modal should be closed");
});
});
diff --git a/addons/product/static/tests/product_pricelist_report_test.js b/addons/product/static/tests/product_pricelist_report_test.js
index d1bd158b1e773..a381884a4d0ee 100644
--- a/addons/product/static/tests/product_pricelist_report_test.js
+++ b/addons/product/static/tests/product_pricelist_report_test.js
@@ -1,11 +1,10 @@
odoo.define('product.pricelist.report.tests', function (require) {
"use strict";
-const core = require('web.core');
const GeneratePriceList = require('product.generate_pricelist').GeneratePriceList;
-const NotificationService = require('web.NotificationService');
const testUtils = require('web.test_utils');
-const createActionManager = testUtils.createActionManager;
-const testUtilsMock = require('web.test_utils_mock');
+
+const { createWebClient, getActionManagerTestConfig, doAction } = require('@web/../tests/webclient/actions/helpers');
+let testConfig;
QUnit.module('Product Pricelist', {
beforeEach: function () {
@@ -32,9 +31,11 @@ QUnit.module('Product Pricelist', {
}]
}
};
+ testConfig = getActionManagerTestConfig();
+ Object.assign(testConfig.serverData, {models: this.data});
},
}, function () {
- QUnit.skip('Pricelist Client Action', async function (assert) {
+ QUnit.test('Pricelist Client Action', async function (assert) {
assert.expect(21);
const self = this;
@@ -50,21 +51,14 @@ QUnit.module('Product Pricelist', {
return this._super.apply(this, arguments);
},
});
+ const mockRPC = (route, args) => {
+ if (route === '/web/dataset/call_kw/report.product.report_pricelist/get_html') {
+ return Promise.resolve("");
+ }
+ };
- const actionManager = await createActionManager({
- data: this.data,
- mockRPC: function(route, args) {
- if (route === '/web/dataset/call_kw/report.product.report_pricelist/get_html') {
- return Promise.resolve("");
- }
- return this._super(route, args);
- },
- services: {
- notification: NotificationService,
- },
- });
-
- await actionManager.doAction({
+ const webClient = await createWebClient({ testConfig, mockRPC });
+ await doAction(webClient, {
id: 1,
name: 'Generate Pricelist',
tag: 'generate_pricelist',
@@ -78,7 +72,7 @@ QUnit.module('Product Pricelist', {
});
// checking default pricelist
- assert.strictEqual(actionManager.$('.o_field_many2one input').val(), "Public Pricelist",
+ assert.strictEqual($(webClient.el).find('.o_field_many2one input').val(), "Public Pricelist",
"should have default pricelist");
// changing pricelist
@@ -86,28 +80,28 @@ QUnit.module('Product Pricelist', {
await testUtils.fields.many2one.clickItem("pricelist_id", "Test");
// check wherther pricelist value has been updated or not. along with that check default quantities should be there.
- assert.strictEqual(actionManager.$('.o_field_many2one input').val(), "Test",
+ assert.strictEqual($(webClient.el).find('.o_field_many2one input').val(), "Test",
"After pricelist change, the pricelist_id field should be updated");
- assert.strictEqual(actionManager.$('.o_badges > .badge').length, 3,
+ assert.strictEqual($(webClient.el).find('.o_badges > .badge').length, 3,
"There should be 3 default Quantities");
// existing quantity can not be added.
- await testUtils.dom.click(actionManager.$('.o_add_qty'));
+ await testUtils.dom.click($(webClient.el).find('.o_add_qty'));
let notificationElement = document.body.querySelector('.o_notification_manager .o_notification.bg-info');
assert.strictEqual(notificationElement.querySelector('.o_notification_content').textContent,
"Quantity already present (1).", "Existing Quantity can not be added");
// adding few more quantities to check.
- actionManager.$('.o_product_qty').val(2);
+ $(webClient.el).find('.o_product_qty').val(2);
Qty.push(2);
- await testUtils.dom.click(actionManager.$('.o_add_qty'));
- actionManager.$('.o_product_qty').val(3);
+ await testUtils.dom.click($(webClient.el).find('.o_add_qty'));
+ $(webClient.el).find('.o_product_qty').val(3);
Qty.push(3);
- await testUtils.dom.click(actionManager.$('.o_add_qty'));
+ await testUtils.dom.click($(webClient.el).find('.o_add_qty'));
// should not be added more then 5 quantities.
- actionManager.$('.o_product_qty').val(4);
- await testUtils.dom.click(actionManager.$('.o_add_qty'));
+ $(webClient.el).find('.o_product_qty').val(4);
+ await testUtils.dom.click($(webClient.el).find('.o_add_qty'));
notificationElement = document.body.querySelector('.o_notification_manager .o_notification.bg-warning');
assert.strictEqual(notificationElement.querySelector('.o_notification_content').textContent,
@@ -116,15 +110,15 @@ QUnit.module('Product Pricelist', {
// removing all the quantities should work
Qty.pop(10);
- await testUtils.dom.click(actionManager.$('.o_badges .badge:contains("10") .o_remove_qty'));
+ await testUtils.dom.click($(webClient.el).find('.o_badges .badge:contains("10") .o_remove_qty'));
Qty.pop(5);
- await testUtils.dom.click(actionManager.$('.o_badges .badge:contains("5") .o_remove_qty'));
+ await testUtils.dom.click($(webClient.el).find('.o_badges .badge:contains("5") .o_remove_qty'));
Qty.pop(3);
- await testUtils.dom.click(actionManager.$('.o_badges .badge:contains("3") .o_remove_qty'));
+ await testUtils.dom.click($(webClient.el).find('.o_badges .badge:contains("3") .o_remove_qty'));
Qty.pop(2);
- await testUtils.dom.click(actionManager.$('.o_badges .badge:contains("2") .o_remove_qty'));
+ await testUtils.dom.click($(webClient.el).find('.o_badges .badge:contains("2") .o_remove_qty'));
Qty.pop(1);
- await testUtils.dom.click(actionManager.$('.o_badges .badge:contains("1") .o_remove_qty'));
+ await testUtils.dom.click($(webClient.el).find('.o_badges .badge:contains("1") .o_remove_qty'));
assert.verifySteps([
'field_changed',
@@ -138,7 +132,6 @@ QUnit.module('Product Pricelist', {
]);
testUtils.mock.unpatch(GeneratePriceList);
- actionManager.destroy();
});
}
diff --git a/addons/stock/static/tests/stock_traceability_report_backend_tests.js b/addons/stock/static/tests/stock_traceability_report_backend_tests.js
index 2f2e531104ffe..e5b1f55273ca0 100644
--- a/addons/stock/static/tests/stock_traceability_report_backend_tests.js
+++ b/addons/stock/static/tests/stock_traceability_report_backend_tests.js
@@ -7,7 +7,9 @@ odoo.define('stock.stock_traceability_report_backend_tests', function (require)
const testUtils = require('web.test_utils');
const { patch, unpatch } = require('web.utils');
- const { createActionManager, dom: domUtils } = testUtils;
+ const { dom: domUtils } = testUtils;
+ const { legacyExtraNextTick } = require("@web/../tests/helpers/utils");
+ const { createWebClient, getActionManagerTestConfig, doAction } = require('@web/../tests/webclient/actions/helpers');
/**
* Helper function to instantiate a stock report action.
@@ -72,7 +74,7 @@ odoo.define('stock.stock_traceability_report_backend_tests', function (require)
report.destroy();
});
- QUnit.skip("mounted is called once when returning on 'Stock report' from breadcrumb", async assert => {
+ QUnit.test("mounted is called once when returning on 'Stock report' from breadcrumb", async assert => {
// This test can be removed as soon as we don't mix legacy and owl layers anymore.
assert.expect(7);
@@ -91,49 +93,48 @@ odoo.define('stock.stock_traceability_report_backend_tests', function (require)
this.__superMounted(...arguments);
},
});
-
- const actionManager = await createActionManager({
- actions: [
- {
- id: 42,
- name: "Stock report",
- tag: 'stock_report_generic',
- type: 'ir.actions.client',
- context: {},
- params: {},
- },
- ],
- archs: {
- 'partner,false,form': '',
- 'partner,false,search': '',
- },
- data: {
- partner: {
- fields: {
- display_name: { string: "Displayed name", type: "char" },
- },
- records: [
- {id: 1, display_name: "Genda Swami"},
- ],
+ const models = {
+ partner: {
+ fields: {
+ display_name: { string: "Displayed name", type: "char" },
},
+ records: [
+ {id: 1, display_name: "Genda Swami"},
+ ],
},
+ };
+ let testConfig = getActionManagerTestConfig();
+ Object.assign(testConfig.serverData, { models });
+
+ testConfig.serverData.views = {
+ 'partner,false,form': '',
+ 'partner,false,search': '',
+ };
+ testConfig.serverData.actions[42] = {
+ id: 42,
+ name: "Stock report",
+ tag: 'stock_report_generic',
+ type: 'ir.actions.client',
+ context: {},
+ params: {},
+ };
+ const webClient = await createWebClient({
+ testConfig,
mockRPC: function (route) {
if (route === '/web/dataset/call_kw/stock.traceability.report/get_html') {
return Promise.resolve({
html: 'Go to form view',
});
}
- return this._super.apply(this, arguments);
- },
- intercepts: {
- do_action: ev => actionManager.doAction(ev.data.action, ev.data.options),
},
});
- await actionManager.doAction(42);
- await domUtils.click(actionManager.$('.o_stock_reports_web_action'));
- await domUtils.click(actionManager.$('.breadcrumb-item:first'));
- actionManager.destroy();
+ await doAction(webClient, 42);
+ await domUtils.click($(webClient.el).find('.o_stock_reports_web_action'));
+ await legacyExtraNextTick();
+ await domUtils.click($(webClient.el).find('.breadcrumb-item:first'));
+ await legacyExtraNextTick();
+ webClient.destroy();
assert.verifySteps([
'mounted 1',
diff --git a/addons/web/static/tests/helpers/mock_server.js b/addons/web/static/tests/helpers/mock_server.js
index c8bc9e9eecea3..de34f8e72806a 100644
--- a/addons/web/static/tests/helpers/mock_server.js
+++ b/addons/web/static/tests/helpers/mock_server.js
@@ -398,6 +398,8 @@ export class MockServer {
return Promise.resolve(this.mockLoadViews(args.model, args.kwargs));
case "name_create":
return Promise.resolve(this.mockNameCreate(args.model, args.args[0]));
+ case "name_get":
+ return Promise.resolve(this.mockNameGet(args.model, args.args));
case "name_search":
return Promise.resolve(this.mockNameSearch(args.model, args.args, args.kwargs));
case "onchange":
@@ -406,8 +408,18 @@ export class MockServer {
return Promise.resolve(this.mockRead(args.model, args.args));
case "search":
return Promise.resolve(this.mockSearch(args.model, args.args, args.kwargs));
+ case "search_count":
+ return Promise.resolve(this.mockSearchCount(args.model, args.args, args.kwargs));
case "search_read":
return Promise.resolve(this.mockSearchRead(args.model, args.args, args.kwargs));
+ case "search_panel_select_range":
+ return Promise.resolve(
+ this.mockSearchPanelSelectRange(args.model, args.args, args.kwargs)
+ );
+ case "search_panel_select_multi_range":
+ return Promise.resolve(
+ this.mockSearchPanelSelectMultiRange(args.model, args.args, args.kwargs)
+ );
case "web_search_read":
return Promise.resolve(this.mockWebSearchRead(args.model, args.args, args.kwargs));
case "read_group":
@@ -533,6 +545,31 @@ export class MockServer {
return [id, name];
}
+ /**
+ * Simulate a 'name_get' operation
+ *
+ * @private
+ * @param {string} model
+ * @param {Array} args
+ * @returns {Array[]} a list of [id, display_name]
+ */
+ mockNameGet(model, args) {
+ var ids = args[0];
+ if (!args.length) {
+ throw new Error("name_get: expected one argument");
+ } else if (!ids) {
+ return [];
+ }
+ if (!Array.isArray(ids)) {
+ ids = [ids];
+ }
+ var records = this.models[model].records;
+ var names = ids.map((id) =>
+ id ? [id, records.find((r) => r.id === id).display_name] : [null, "False"]
+ );
+ return names;
+ }
+
/**
* Simulate a 'name_search' operation.
*
@@ -858,6 +895,18 @@ export class MockServer {
return result.records;
}
+ /**
+ * Simulate a 'search_count' operation
+ *
+ * @private
+ * @param {string} model
+ * @param {Array} args
+ * @returns {integer}
+ */
+ mockSearchCount(model, args) {
+ return this.getRecords(model, args[0]).length;
+ }
+
mockSearchRead(modelName, args, kwargs) {
const result = this.mockSearchReadController({
model: modelName,
@@ -917,6 +966,497 @@ export class MockServer {
};
}
+ /**
+ * Simulates a call to the server '_search_panel_domain_image' method.
+ *
+ * @private
+ * @param {string} model
+ * @param {Array[]} domain
+ * @param {string} fieldName
+ * @param {boolean} setCount
+ * @returns {Map}
+ */
+ mockSearchPanelDomainImage(model, fieldName, domain, setCount = false, limit = false) {
+ const field = this.models[model].fields[fieldName];
+ let groupIdName;
+ if (field.type === "many2one") {
+ groupIdName = (value) => value || [false, undefined];
+ // mockReadGroup does not take care of the condition [fieldName, '!=', false]
+ // in the domain defined below !!!
+ } else if (field.type === "selection") {
+ const selection = {};
+ for (const [value, label] of this.models[model].fields[fieldName].selection) {
+ selection[value] = label;
+ }
+ groupIdName = (value) => [value, selection[value]];
+ }
+ domain = Domain.combine([domain, [[fieldName, "!=", false]]]).toList();
+ const groups = this.mockReadGroup(model, {
+ domain,
+ fields: [fieldName],
+ groupby: [fieldName],
+ limit,
+ });
+ const domainImage = new Map();
+ for (const group of groups) {
+ const [id, display_name] = groupIdName(group[fieldName]);
+ const values = { id, display_name };
+ if (setCount) {
+ values.__count = group[fieldName + "_count"];
+ }
+ domainImage.set(id, values);
+ }
+ return domainImage;
+ }
+
+ /**
+ * Simulates a call to the server '_search_panel_field_image' method.
+ *
+ * @private
+ * @param {string} model
+ * @param {string} fieldName
+ * @param {Object} kwargs
+ * @see _mockSearchPanelDomainImage()
+ */
+ mockSearchPanelFieldImage(model, fieldName, kwargs) {
+ const enableCounters = kwargs.enable_counters;
+ const onlyCounters = kwargs.only_counters;
+ const extraDomain = kwargs.extra_domain || [];
+ const normalizedExtra = new Domain(extraDomain).toList();
+ const noExtra = JSON.stringify(normalizedExtra) === "[]";
+ const modelDomain = kwargs.model_domain || [];
+ const countDomain = Domain.combine([modelDomain, extraDomain]).toList();
+
+ const limit = kwargs.limit;
+ const setLimit = kwargs.set_limit;
+
+ if (onlyCounters) {
+ return this.mockSearchPanelDomainImage(model, fieldName, countDomain, true);
+ }
+
+ const modelDomainImage = this.mockSearchPanelDomainImage(
+ model,
+ fieldName,
+ modelDomain,
+ enableCounters && noExtra,
+ setLimit && limit
+ );
+ if (enableCounters && !noExtra) {
+ const countDomainImage = this.mockSearchPanelDomainImage(
+ model,
+ fieldName,
+ countDomain,
+ true
+ );
+ for (const [id, values] of modelDomainImage.entries()) {
+ const element = countDomainImage.get(id);
+ values.__count = element ? element.__count : 0;
+ }
+ }
+
+ return modelDomainImage;
+ }
+
+ /**
+ * Simulates a call to the server '_search_panel_global_counters' method.
+ *
+ * @private
+ * @param {Map} valuesRange
+ * @param {(string|boolean)} parentName 'parent_id' or false
+ */
+ mockSearchPanelGlobalCounters(valuesRange, parentName) {
+ const localCounters = [...valuesRange.keys()].map((id) => valuesRange.get(id).__count);
+ for (let [id, values] of valuesRange.entries()) {
+ const count = localCounters[id];
+ if (count) {
+ let parent_id = values[parentName];
+ while (parent_id) {
+ values = valuesRange.get(parent_id);
+ values.__count += count;
+ parent_id = values[parentName];
+ }
+ }
+ }
+ }
+
+ /**
+ * Simulates a call to the server '_search_panel_sanitized_parent_hierarchy' method.
+ *
+ * @private
+ * @param {Object[]} records
+ * @param {(string|boolean)} parentName 'parent_id' or false
+ * @param {number[]} ids
+ * @returns {Object[]}
+ */
+ mockSearchPanelSanitizedParentHierarchy(records, parentName, ids) {
+ const getParentId = (record) => record[parentName] && record[parentName][0];
+ const allowedRecords = {};
+ for (const record of records) {
+ allowedRecords[record.id] = record;
+ }
+ const recordsToKeep = {};
+ for (const id of ids) {
+ const ancestorChain = {};
+ let recordId = id;
+ let chainIsFullyIncluded = true;
+ while (chainIsFullyIncluded && recordId) {
+ const knownStatus = recordsToKeep[recordId];
+ if (knownStatus !== undefined) {
+ chainIsFullyIncluded = knownStatus;
+ break;
+ }
+ const record = allowedRecords[recordId];
+ if (record) {
+ ancestorChain[recordId] = record;
+ recordId = getParentId(record);
+ } else {
+ chainIsFullyIncluded = false;
+ }
+ }
+ for (const id in ancestorChain) {
+ recordsToKeep[id] = chainIsFullyIncluded;
+ }
+ }
+ return records.filter((rec) => recordsToKeep[rec.id]);
+ }
+
+ /**
+ * Simulates a call to the server 'search_panel_select_range' method.
+ *
+ * @private
+ * @param {string} model
+ * @param {string[]} args
+ * @param {string} args[fieldName]
+ * @param {Object} [kwargs={}]
+ * @param {Array[]} [kwargs.category_domain] domain generated by categories
+ * (this parameter is used in _search_panel_range)
+ * @param {Array[]} [kwargs.comodel_domain] domain of field values (if relational)
+ * (this parameter is used in _search_panel_range)
+ * @param {boolean} [kwargs.enable_counters] whether to count records by value
+ * @param {Array[]} [kwargs.filter_domain] domain generated by filters
+ * @param {integer} [kwargs.limit] maximal number of values to fetch
+ * @param {Array[]} [kwargs.search_domain] base domain of search (this parameter
+ * is used in _search_panel_range)
+ * @returns {Object}
+ */
+ mockSearchPanelSelectRange(model, [fieldName], kwargs) {
+ const field = this.models[model].fields[fieldName];
+ const supportedTypes = ["many2one", "selection"];
+ if (!supportedTypes.includes(field.type)) {
+ throw new Error(
+ `Only types ${supportedTypes} are supported for category (found type ${field.type})`
+ );
+ }
+
+ const modelDomain = kwargs.search_domain || [];
+ const extraDomain = Domain.combine([
+ kwargs.category_domain || [],
+ kwargs.filter_domain || [],
+ ]).toList();
+
+ if (field.type === "selection") {
+ const newKwargs = Object.assign({}, kwargs, {
+ model_domain: modelDomain,
+ extra_domain: extraDomain,
+ });
+ kwargs.model_domain = modelDomain;
+ return {
+ parent_field: false,
+ values: this.mockSearchPanelSelectionRange(model, fieldName, newKwargs),
+ };
+ }
+
+ const fieldNames = ["display_name"];
+ let hierarchize = "hierarchize" in kwargs ? kwargs.hierarchize : true;
+ let getParentId;
+ let parentName = false;
+ if (hierarchize && this.models[field.relation].fields.parent_id) {
+ parentName = "parent_id"; // in tests, parent field is always 'parent_id'
+ fieldNames.push(parentName);
+ getParentId = (record) => record.parent_id && record.parent_id[0];
+ } else {
+ hierarchize = false;
+ }
+ let comodelDomain = kwargs.comodel_domain || [];
+ const enableCounters = kwargs.enable_counters;
+ const expand = kwargs.expand;
+ const limit = kwargs.limit;
+ let domainImage;
+ if (enableCounters || !expand) {
+ const newKwargs = Object.assign({}, kwargs, {
+ model_domain: modelDomain,
+ extra_domain: extraDomain,
+ only_counters: expand,
+ set_limit: limit && !(expand || hierarchize || comodelDomain),
+ });
+ domainImage = this.mockSearchPanelFieldImage(model, fieldName, newKwargs);
+ }
+ if (!expand && !hierarchize && !comodelDomain.length) {
+ if (limit && domainImage.size === limit) {
+ return { error_msg: "Too many items to display." };
+ }
+ return {
+ parent_field: parentName,
+ values: [...domainImage.values()],
+ };
+ }
+ let imageElementIds;
+ if (!expand) {
+ imageElementIds = [...domainImage.keys()].map(Number);
+ let condition;
+ if (hierarchize) {
+ const records = this.models[field.relation].records;
+ const ancestorIds = new Set();
+ for (const id of imageElementIds) {
+ let recordId = id;
+ let record;
+ while (recordId) {
+ ancestorIds.add(recordId);
+ record = records.find((rec) => rec.id === recordId);
+ recordId = record[parentName];
+ }
+ }
+ condition = ["id", "in", [...new Set(ancestorIds)]];
+ } else {
+ condition = ["id", "in", imageElementIds];
+ }
+ comodelDomain = Domain.combine([comodelDomain, [condition]]).toList();
+ }
+ let comodelRecords = this.mockSearchRead(field.relation, [comodelDomain, fieldNames], {
+ limit,
+ });
+
+ if (hierarchize) {
+ const ids = expand ? comodelRecords.map((rec) => rec.id) : imageElementIds;
+ comodelRecords = this.mockSearchPanelSanitizedParentHierarchy(
+ comodelRecords,
+ parentName,
+ ids
+ );
+ }
+
+ if (limit && comodelRecords.length === limit) {
+ return { error_msg: "Too many items to display." };
+ }
+ // A map is used to keep the initial order.
+ const fieldRange = new Map();
+ for (const record of comodelRecords) {
+ const values = {
+ id: record.id,
+ display_name: record.display_name,
+ };
+ if (hierarchize) {
+ values[parentName] = getParentId(record);
+ }
+ if (enableCounters) {
+ values.__count = domainImage.get(record.id)
+ ? domainImage.get(record.id).__count
+ : 0;
+ }
+ fieldRange.set(record.id, values);
+ }
+
+ if (hierarchize && enableCounters) {
+ this.mockSearchPanelGlobalCounters(fieldRange, parentName);
+ }
+
+ return {
+ parent_field: parentName,
+ values: [...fieldRange.values()],
+ };
+ }
+
+ /**
+ * Simulates a call to the server 'search_panel_select_multi_range' method.
+ *
+ * @private
+ * @param {string} model
+ * @param {string[]} args
+ * @param {string} args[fieldName]
+ * @param {Object} [kwargs={}]
+ * @param {Array[]} [kwargs.category_domain] domain generated by categories
+ * @param {Array[]} [kwargs.comodel_domain] domain of field values (if relational)
+ * (this parameter is used in _search_panel_range)
+ * @param {boolean} [kwargs.enable_counters] whether to count records by value
+ * @param {Array[]} [kwargs.filter_domain] domain generated by filters
+ * @param {string} [kwargs.group_by] extra field to read on comodel, to group
+ * comodel records
+ * @param {Array[]} [kwargs.group_domain] dict, one domain for each activated
+ * group for the group_by (if any). Those domains are used to fech accurate
+ * counters for values in each group
+ * @param {integer} [kwargs.limit] maximal number of values to fetch
+ * @param {Array[]} [kwargs.search_domain] base domain of search
+ * @returns {Object}
+ */
+ mockSearchPanelSelectMultiRange(model, [fieldName], kwargs) {
+ const field = this.models[model].fields[fieldName];
+ const supportedTypes = ["many2one", "many2many", "selection"];
+ if (!supportedTypes.includes(field.type)) {
+ throw new Error(
+ `Only types ${supportedTypes} are supported for filter (found type ${field.type})`
+ );
+ }
+ let modelDomain = kwargs.search_domain || [];
+ let extraDomain = Domain.combine([
+ kwargs.category_domain || [],
+ kwargs.filter_domain || [],
+ ]).toList();
+ if (field.type === "selection") {
+ const newKwargs = Object.assign({}, kwargs, {
+ model_domain: modelDomain,
+ extra_domain: extraDomain,
+ });
+ return {
+ values: this.mockSearchPanelSelectionRange(model, fieldName, newKwargs),
+ };
+ }
+ const fieldNames = ["display_name"];
+ const groupBy = kwargs.group_by;
+ let groupIdName;
+ if (groupBy) {
+ const groupByField = this.models[field.relation].fields[groupBy];
+ fieldNames.push(groupBy);
+ if (groupByField.type === "many2one") {
+ groupIdName = (value) => value || [false, "Not set"];
+ } else if (groupByField.type === "selection") {
+ const groupBySelection = Object.assign(
+ {},
+ this.models[field.relation].fields[groupBy].selection
+ );
+ groupBySelection[false] = "Not Set";
+ groupIdName = (value) => [value, groupBySelection[value]];
+ } else {
+ groupIdName = (value) => (value ? [value, value] : [false, "Not set"]);
+ }
+ }
+ let comodelDomain = kwargs.comodel_domain || [];
+ const enableCounters = kwargs.enable_counters;
+ const expand = kwargs.expand;
+ const limit = kwargs.limit;
+ if (field.type === "many2many") {
+ const comodelRecords = this.mockSearchRead(
+ field.relation,
+ [comodelDomain, fieldNames],
+ { limit }
+ );
+ if (expand && limit && comodelRecords.length === limit) {
+ return { error_msg: "Too many items to display." };
+ }
+
+ const groupDomain = kwargs.group_domain;
+ const fieldRange = [];
+ for (const record of comodelRecords) {
+ const values = {
+ id: record.id,
+ display_name: record.display_name,
+ };
+ let groupId;
+ if (groupBy) {
+ const [gId, gName] = groupIdName(record[groupBy]);
+ values.group_id = groupId = gId;
+ values.group_name = gName;
+ }
+ let count;
+ let inImage;
+ if (enableCounters || !expand) {
+ const searchDomain = Domain.combine([
+ modelDomain,
+ [[fieldName, "in", record.id]],
+ ]).toList();
+ let localExtraDomain = extraDomain;
+ if (groupBy && groupDomain) {
+ localExtraDomain = Domain.combine([
+ localExtraDomain,
+ groupDomain[JSON.stringify(groupId)] || [],
+ ]).toList();
+ }
+ const searchCountDomain = Domain.combine([
+ searchDomain,
+ localExtraDomain,
+ ]).toList();
+ if (enableCounters) {
+ count = this.mockSearchCount(model, [searchCountDomain]);
+ }
+ if (!expand) {
+ if (enableCounters && JSON.stringify(localExtraDomain) === "[]") {
+ inImage = count;
+ } else {
+ inImage = this.mockSearch(model, [searchDomain], { limit: 1 }).length;
+ }
+ }
+ }
+ if (expand || inImage) {
+ if (enableCounters) {
+ values.__count = count;
+ }
+ fieldRange.push(values);
+ }
+ }
+
+ if (!expand && limit && fieldRange.length === limit) {
+ return { error_msg: "Too many items to display." };
+ }
+
+ return { values: fieldRange };
+ }
+
+ if (field.type === "many2one") {
+ let domainImage;
+ if (enableCounters || !expand) {
+ extraDomain = Domain.combine([extraDomain, kwargs.group_domain || []]).toList();
+ modelDomain = Domain.combine([modelDomain, kwargs.group_domain || []]).toList();
+ const newKwargs = Object.assign({}, kwargs, {
+ model_domain: modelDomain,
+ extra_domain: extraDomain,
+ only_counters: expand,
+ set_limit: limit && !(expand || groupBy || comodelDomain),
+ });
+ domainImage = this.mockSearchPanelFieldImage(model, fieldName, newKwargs);
+ }
+ if (!expand && !groupBy && !comodelDomain.length) {
+ if (limit && domainImage.size === limit) {
+ return { error_msg: "Too many items to display." };
+ }
+ return { values: [...domainImage.values()] };
+ }
+ if (!expand) {
+ const imageElementIds = [...domainImage.keys()].map(Number);
+ comodelDomain = Domain.combine([
+ comodelDomain,
+ [["id", "in", imageElementIds]],
+ ]).toList();
+ }
+ const comodelRecords = this.mockSearchRead(
+ field.relation,
+ [comodelDomain, fieldNames],
+ { limit }
+ );
+ if (limit && comodelRecords.length === limit) {
+ return { error_msg: "Too many items to display." };
+ }
+
+ const fieldRange = [];
+ for (const record of comodelRecords) {
+ const values = {
+ id: record.id,
+ display_name: record.display_name,
+ };
+ if (groupBy) {
+ const [groupId, groupName] = groupIdName(record[groupBy]);
+ values.group_id = groupId;
+ values.group_name = groupName;
+ }
+ if (enableCounters) {
+ values.__count = domainImage.get(record.id)
+ ? domainImage.get(record.id).__count
+ : 0;
+ }
+ fieldRange.push(values);
+ }
+ return { values: fieldRange };
+ }
+ }
+
mockWrite(modelName, args) {
args[0].forEach((id) => this.writeRecord(modelName, args[1], id));
return true;
diff --git a/addons/web/static/tests/helpers/mock_services.js b/addons/web/static/tests/helpers/mock_services.js
index ad14eb187c72a..4b6695604fc27 100644
--- a/addons/web/static/tests/helpers/mock_services.js
+++ b/addons/web/static/tests/helpers/mock_services.js
@@ -94,37 +94,6 @@ export function makeFakeUserService(values) {
};
}
-/*export function makeFakeMenusService(menuData?: MenuData): Service {
- const _menuData = menuData || {
- root: { id: "root", children: [1], name: "root" },
- 1: { id: 1, children: [], name: "App0" },
- };
- return {
- name: "menus",
- start() {
- const menusService = {
- getMenu(menuId: keyof MenuData) {
- return _menuData![menuId];
- },
- getApps() {
- return this.getMenu("root").children.map((mid) => this.getMenu(mid));
- },
- getAll() {
- return Object.values(_menuData);
- },
- getMenuAsTree(menuId: keyof MenuData) {
- const menu = this.getMenu(menuId) as MenuTree;
- if (!menu.childrenTree) {
- menu.childrenTree = menu.children.map((mid: Menu["id"]) => this.getMenuAsTree(mid));
- }
- return menu;
- },
- };
- return menusService;
- },
- };
-}*/
-
function buildMockRPC(mockRPC) {
return async function (...args) {
if (this instanceof Component && this.__owl__.status === 5) {
diff --git a/addons/web/static/tests/helpers/utils.js b/addons/web/static/tests/helpers/utils.js
index 06f34e7c263e1..c7cd3d7830465 100644
--- a/addons/web/static/tests/helpers/utils.js
+++ b/addons/web/static/tests/helpers/utils.js
@@ -3,6 +3,7 @@
import { isMacOS } from "@web/core/browser/feature_detection";
import { patch, unpatch } from "@web/core/utils/patch";
import { registerCleanup } from "./cleanup";
+import { download } from "@web/core/network/download";
const { Settings } = luxon;
@@ -128,3 +129,7 @@ export function triggerHotkey(hotkey, altIsOptional = false, eventAttrs = {}) {
export async function legacyExtraNextTick() {
return nextTick();
}
+
+export function mockDownload(cb) {
+ patchWithCleanup(download, { _download: cb });
+}
diff --git a/addons/web/static/tests/legacy/helpers/test_env.js b/addons/web/static/tests/legacy/helpers/test_env.js
index fd455240ab5a5..78debbbe1a868 100644
--- a/addons/web/static/tests/legacy/helpers/test_env.js
+++ b/addons/web/static/tests/legacy/helpers/test_env.js
@@ -22,19 +22,28 @@ odoo.define('web.test_env', async function (require) {
// time and they never change
qweb = new owl.QWeb({ templates: session.owlTemplates });
}
- const database = {
- parameters: {
- code: "en_US",
- date_format: '%m/%d/%Y',
- decimal_point: ".",
- direction: 'ltr',
- grouping: [],
- thousands_sep: ",",
- time_format: '%H:%M:%S',
- },
+
+ const defaultTranslationParamters = {
+ code: "en_US",
+ date_format: '%m/%d/%Y',
+ decimal_point: ".",
+ direction: 'ltr',
+ grouping: [],
+ thousands_sep: ",",
+ time_format: '%H:%M:%S',
};
+
+ let _t;
+ if ('_t' in env) {
+ _t = Object.assign(env._t, {database: env._t.database || {}})
+ } else {
+ _t = Object.assign(((s) => s), { database: {} });
+ }
+
+ _t.database.parameters = Object.assign(defaultTranslationParamters, _t.database.parameters);
+
const defaultEnv = {
- _t: env._t || Object.assign((s => s), { database }),
+ _t,
browser: Object.assign({
setTimeout: window.setTimeout.bind(window),
clearTimeout: window.clearTimeout.bind(window),
@@ -76,6 +85,7 @@ odoo.define('web.test_env', async function (require) {
throw new Error(`No method to perform RPC`);
},
url: session.url,
+ getTZOffset: (() => 0),
}, env.session),
};
return Object.assign(env, defaultEnv);
diff --git a/addons/web/static/tests/legacy/helpers/test_utils_mock.js b/addons/web/static/tests/legacy/helpers/test_utils_mock.js
index 8cf2c79e52816..17eb9121ac805 100644
--- a/addons/web/static/tests/legacy/helpers/test_utils_mock.js
+++ b/addons/web/static/tests/legacy/helpers/test_utils_mock.js
@@ -51,11 +51,14 @@ const DebouncedField = basic_fields.DebouncedField;
async function _getMockedOwlEnv(params, mockServer) {
params.env = params.env || {};
+ const database = {parameters: params.translateParameters || {}};
+
// build the env
const favoriteFilters = params.favoriteFilters;
const debug = params.debug;
const services = {};
const env = Object.assign({}, params.env, {
+ _t: params.env && params.env._t || Object.assign((s => s), { database }),
browser: Object.assign({
fetch: (resource, init) => mockServer.performFetch(resource, init),
}, params.env.browser),
diff --git a/addons/web/static/tests/legacy/report/client_action_tests.js b/addons/web/static/tests/legacy/report/client_action_tests.js
deleted file mode 100644
index 4607b882e905c..0000000000000
--- a/addons/web/static/tests/legacy/report/client_action_tests.js
+++ /dev/null
@@ -1,110 +0,0 @@
-odoo.define('web/static/tests/report/client_action_tests', function (require) {
- "use strict";
-
- const ControlPanel = require('web.ControlPanel');
- const ReportClientAction = require('report.client_action');
- const testUtils = require("web.test_utils");
- const { patch, unpatch } = require('web.utils');
-
- const { createActionManager, dom, mock } = testUtils;
-
- QUnit.module('Client Action Report', {}, () => {
- QUnit.skip("mounted is called once when returning on 'Client Action Report' from breadcrumb", async assert => {
- // This test can be removed as soon as we don't mix legacy and owl layers anymore.
- assert.expect(7);
-
- let mountCount = 0;
-
- // patch the report client action to override its iframe's url so that
- // it doesn't trigger an RPC when it is appended to the DOM (for this
- // usecase, using removeSRCAttribute doesn't work as the RPC is
- // triggered as soon as the iframe is in the DOM, even if its src
- // attribute is removed right after)
- mock.patch(ReportClientAction, {
- start: function () {
- var self = this;
- return this._super.apply(this, arguments).then(function () {
- self._rpc({route: self.iframe.getAttribute('src')});
- self.iframe.setAttribute('src', 'about:blank');
- });
- }
- });
-
- patch(ControlPanel.prototype, 'test.ControlPanel', {
- mounted() {
- mountCount = mountCount + 1;
- this.__uniqueId = mountCount;
- assert.step(`mounted ${this.__uniqueId}`);
- this.__superMounted = this._super.bind(this);
- this.__superMounted(...arguments);
- },
- willUnmount() {
- assert.step(`willUnmount ${this.__uniqueId}`);
- this.__superMounted(...arguments);
- },
- });
- const actionManager = await createActionManager({
- actions: [
- {
- id: 42,
- name: "Client Action Report",
- tag: 'report.client_action',
- type: 'ir.actions.report',
- report_type: 'qweb-html',
- },
- {
- id: 43,
- type: "ir.actions.act_window",
- res_id: 1,
- res_model: "partner",
- views: [
- [false, "form"],
- ],
- }
- ],
- archs: {
- 'partner,false,form': '',
- 'partner,false,search': '',
- },
- data: {
- partner: {
- fields: {
- display_name: { string: "Displayed name", type: "char" },
- },
- records: [
- {id: 1, display_name: "Genda Swami"},
- ],
- },
- },
- mockRPC: function (route) {
- if (route === '/report/html/undefined?context=%7B%7D') {
- return Promise.resolve('Go to detail view');
- }
- return this._super.apply(this, arguments);
- },
- intercepts: {
- do_action: ev => actionManager.doAction(ev.data.action, ev.data.options),
- },
- });
-
- await actionManager.doAction(42);
- // simulate an action as we are not able to reproduce a real doAction using 'Client Action Report'
- await actionManager.doAction(43);
- await dom.click(actionManager.$('.breadcrumb-item:first'));
- actionManager.destroy();
-
- assert.verifySteps([
- 'mounted 1',
- 'willUnmount 1',
- 'mounted 2',
- 'willUnmount 2',
- 'mounted 3',
- 'willUnmount 3',
- ]);
-
- unpatch(ControlPanel.prototype, 'test.ControlPanel');
- mock.unpatch(ReportClientAction);
- });
- });
-
-});
diff --git a/addons/web/static/tests/legacy/services/crash_manager_tests.js b/addons/web/static/tests/legacy/services/crash_manager_tests.js
deleted file mode 100644
index ebff3bd15655b..0000000000000
--- a/addons/web/static/tests/legacy/services/crash_manager_tests.js
+++ /dev/null
@@ -1,64 +0,0 @@
-odoo.define('web.crash_manager_tests', function (require) {
- "use strict";
- const CrashManager = require('web.CrashManager').CrashManager;
- const Bus = require('web.Bus');
- const testUtils = require('web.test_utils');
- const core = require('web.core');
- const ajax = require('web.ajax');
- const createActionManager = testUtils.createActionManager;
-
-QUnit.module('Services', {}, function() {
-
- QUnit.module('CrashManager');
-
- QUnit.skip("Execute an action and close the RedirectWarning when clicking on the primary button", async function (assert) {
- assert.expect(4);
-
- var dummy_action_name = "crash_manager_tests_dummy_action";
- var dummy_action = function() {
- assert.step('do_action');
- };
- core.action_registry.add(dummy_action_name, dummy_action);
-
- // What we want to test is a do-action triggered by the crashManagerService
- // the intercept feature of testUtilsMock is not fit for this, because it is too low in the hierarchy
- const bus = new Bus();
- bus.on('do-action', null, payload => {
- const { action, options } = payload;
- actionManager.doAction(action, options);
- });
-
- var actionManager = await createActionManager({
- actions: [dummy_action],
- services: {
- crash_manager: CrashManager,
- },
- bus
- });
- actionManager.call('crash_manager', 'rpc_error', {
- code: 200,
- data: {
- name: "odoo.exceptions.RedirectWarning",
- arguments: [
- "crash_manager_tests_warning_modal_text",
- dummy_action_name,
- "crash_manager_tests_button_text",
- null,
- ]
- }
- });
- await ajax.loadJS('/web/static/lib/stacktracejs/stacktrace.js');
- await testUtils.nextTick();
-
- var modal_selector = 'div.modal:contains("crash_manager_tests_warning_modal_text")';
- assert.containsOnce($, modal_selector, "Warning Modal should be opened");
-
- await testUtils.dom.click($(modal_selector).find('button.btn-primary'));
-
- assert.containsNone($, modal_selector, "Warning Modal should be closed");
- assert.verifySteps(['do_action'], "Warning Modal Primary Button Action should be executed");
-
- actionManager.destroy();
- });
-});
-});
diff --git a/addons/web/static/tests/legacy/views/abstract_view_tests.js b/addons/web/static/tests/legacy/views/abstract_view_tests.js
index 6eadb56c0f654..d3c42f0934d3c 100644
--- a/addons/web/static/tests/legacy/views/abstract_view_tests.js
+++ b/addons/web/static/tests/legacy/views/abstract_view_tests.js
@@ -5,7 +5,7 @@ var AbstractView = require('web.AbstractView');
var ajax = require('web.ajax');
var testUtils = require('web.test_utils');
-var createActionManager = testUtils.createActionManager;
+const { createWebClient, doAction, getActionManagerTestConfig } = require('@web/../tests/webclient/actions/helpers');
var createView = testUtils.createView;
QUnit.module('Views', {
@@ -110,36 +110,37 @@ QUnit.module('Views', {
await proms.c.resolve();
});
- QUnit.skip('group_by from context can be a string, instead of a list of strings', async function (assert) {
+ QUnit.test('group_by from context can be a string, instead of a list of strings', async function (assert) {
assert.expect(1);
- var actionManager = await createActionManager({
- actions: [{
- id: 1,
- name: 'Foo',
- res_model: 'foo',
- type: 'ir.actions.act_window',
- views: [[false, 'list']],
- context: {
- group_by: 'bar',
- },
- }],
- archs: {
+ const testConfig = getActionManagerTestConfig();
+ Object.assign(testConfig.serverData, {
+ actions: {
+ 1:{
+ id: 1,
+ name: 'Foo',
+ res_model: 'foo',
+ type: 'ir.actions.act_window',
+ views: [[false, 'list']],
+ context: {
+ group_by: 'bar',
+ },
+ }
+ },
+ views: {
'foo,false,list': '',
'foo,false,search': '',
},
- data: this.data,
- mockRPC: function (route, args) {
- if (args.method === 'web_read_group') {
- assert.deepEqual(args.kwargs.groupby, ['bar']);
- }
- return this._super.apply(this, arguments);
- },
+ models: this.data
});
- await actionManager.doAction(1);
-
- actionManager.destroy();
+ const mockRPC = (route, args) => {
+ if (args.method === 'web_read_group') {
+ assert.deepEqual(args.kwargs.groupby, ['bar']);
+ }
+ };
+ const webClient = await createWebClient({testConfig, mockRPC});
+ await doAction(webClient, 1);
});
});
diff --git a/addons/web/static/tests/legacy/views/calendar_tests.js b/addons/web/static/tests/legacy/views/calendar_tests.js
index 0c34982c26588..35672d97b941a 100644
--- a/addons/web/static/tests/legacy/views/calendar_tests.js
+++ b/addons/web/static/tests/legacy/views/calendar_tests.js
@@ -15,7 +15,10 @@ var testUtils = require('web.test_utils');
var session = require('web.session');
const Widget = require('web.Widget');
-var createActionManager = testUtils.createActionManager;
+const { patchWithCleanup } = require("@web/../tests/helpers/utils");
+
+const { createWebClient, getActionManagerTestConfig, doAction } = require('@web/../tests/webclient/actions/helpers');
+let testConfig;
CalendarRenderer.include({
getAvatars: function () {
@@ -41,7 +44,9 @@ function _preventScroll(ev) {
QUnit.module('Views', {
beforeEach: function () {
window.addEventListener('scroll', _preventScroll, true);
- session.uid = -1; // TO CHECK
+ patchWithCleanup(session, {
+ uid: -1
+ });
this.data = {
event: {
fields: {
@@ -125,6 +130,11 @@ QUnit.module('Views', {
]
},
};
+ testConfig = getActionManagerTestConfig();
+ this.data.event.methods = {
+ check_access_rights: this.data.event.check_access_rights,
+ }
+ Object.assign(testConfig.serverData, {models: this.data});
},
afterEach: function () {
window.removeEventListener('scroll', _preventScroll, true);
@@ -293,15 +303,15 @@ QUnit.module('Views', {
calendar.destroy();
});
- QUnit.skip('breadcrumbs are updated with the displayed period', async function (assert) {
+ QUnit.test('breadcrumbs are updated with the displayed period', async function (assert) {
assert.expect(4);
- var archs = {
+ testConfig.serverData.views = {
'event,1,calendar': '',
'event,false,search': '',
};
- var actions = [{
+ testConfig.serverData.actions[1] = {
id: 1,
flags: {
initialDate: initialDate,
@@ -310,16 +320,10 @@ QUnit.module('Views', {
res_model: 'event',
type: 'ir.actions.act_window',
views: [[1, 'calendar']],
- }];
-
- var actionManager = await createActionManager({
- actions: actions,
- archs: archs,
- data: this.data,
- });
+ };
- await actionManager.doAction(1);
- await testUtils.nextTick();
+ const webClient = await createWebClient({ testConfig });
+ await doAction(webClient, 1);
// displays month mode by default
assert.strictEqual($('.o_control_panel .breadcrumb-item').text(),
@@ -339,8 +343,6 @@ QUnit.module('Views', {
await testUtils.dom.click($('.o_control_panel .o_calendar_button_year'));
assert.strictEqual($('.o_control_panel .breadcrumb-item').text(),
'Meetings Test (2016)', "should display the current year");
-
- actionManager.destroy();
});
QUnit.test('create and change events', async function (assert) {
@@ -2863,10 +2865,10 @@ QUnit.module('Views', {
testUtils.mock.unpatch(Dialog);
});
- QUnit.skip('calendar is configured to have no groupBy menu', async function (assert) {
+ QUnit.test('calendar is configured to have no groupBy menu', async function (assert) {
assert.expect(1);
- var archs = {
+ testConfig.serverData.views = {
'event,1,calendar': '',
};
- var actions = [{
+ testConfig.serverData.actions[1] = {
id: 1,
name: 'some action',
res_model: 'event',
type: 'ir.actions.act_window',
views: [[1, 'calendar']]
- }];
+ };
- var actionManager = await createActionManager({
- actions: actions,
- archs: archs,
- data: this.data,
- });
+ const webClient = await createWebClient({ testConfig });
- await actionManager.doAction(1);
- assert.containsNone(actionManager.$('.o_control_panel .o_search_options span.fa.fa-bars'),
+ await doAction(webClient, 1);
+ assert.containsNone($(webClient.el).find('.o_control_panel .o_search_options span.fa.fa-bars'),
"the control panel has no groupBy menu");
- actionManager.destroy();
});
QUnit.test('timezone does not affect current day', async function (assert) {
@@ -3368,34 +3365,28 @@ QUnit.module('Views', {
calendar.destroy();
});
- QUnit.skip('initial_date given in the context', async function (assert) {
+ QUnit.test('initial_date given in the context', async function (assert) {
assert.expect(1);
- var archs = {
+ testConfig.serverData.views = {
'event,1,calendar': '',
'event,false,search': '',
};
- var actions = [{
+ testConfig.serverData.actions[1] = {
id: 1,
name: 'context initial date',
res_model: 'event',
type: 'ir.actions.act_window',
views: [[1, 'calendar']],
context: {initial_date: initialDate}
- }];
-
- var actionManager = await createActionManager({
- actions: actions,
- archs: archs,
- data: this.data,
- });
+ };
- await actionManager.doAction(1);
+ const webClient = await createWebClient({ testConfig });
+ await doAction(webClient, 1);
await testUtils.nextTick();
assert.strictEqual($('.o_control_panel .breadcrumb-item').text(),
'context initial date (December 12, 2016)', "should display day passed in the context");
- actionManager.destroy();
});
QUnit.test('default week start (US) month mode', async function (assert) {
diff --git a/addons/web/static/tests/legacy/views/form_tests.js b/addons/web/static/tests/legacy/views/form_tests.js
index 0c9e8be3c6a52..686991255e19e 100644
--- a/addons/web/static/tests/legacy/views/form_tests.js
+++ b/addons/web/static/tests/legacy/views/form_tests.js
@@ -8,7 +8,6 @@ var concurrency = require('web.concurrency');
var core = require('web.core');
var fieldRegistry = require('web.field_registry');
const fieldRegistryOwl = require('web.field_registry_owl');
-const FormController = require('web.FormController');
const FormRenderer = require('web.FormRenderer');
var FormView = require('web.FormView');
var mixins = require('web.mixins');
@@ -23,8 +22,11 @@ var Widget = require('web.Widget');
var _t = core._t;
const cpHelpers = testUtils.controlPanel;
var createView = testUtils.createView;
-var createActionManager = testUtils.createActionManager;
+const { legacyExtraNextTick } = require("@web/../tests/helpers/utils");
+const { createWebClient, doAction, getActionManagerTestConfig } = require('@web/../tests/webclient/actions/helpers');
+
+let testConfig;
QUnit.module('Views', {
beforeEach: function () {
this.data = {
@@ -152,6 +154,15 @@ QUnit.module('Views', {
type: 'ir.actions.act_window',
views: [[false, 'kanban'], [false, 'form']],
}];
+
+ testConfig = getActionManagerTestConfig();
+
+ // map legacy test data
+ const actions = {};
+ this.actions.forEach((act) => {
+ actions[act.xmlId || act.id] = act;
+ });
+ Object.assign(testConfig.serverData, {actions, models: this.data});
},
}, function () {
@@ -489,78 +500,68 @@ QUnit.module('Views', {
form.destroy();
});
- QUnit.skip('Form and subview with _view_ref contexts', async function (assert) {
- assert.expect(2);
+ QUnit.test('Form and subview with _view_ref contexts', async function (assert) {
+ assert.expect(3);
- this.data.product.fields.partner_type_ids = {string: "one2many field", type: "one2many", relation: "partner_type"},
- this.data.product.records = [{id: 1, name: 'Tromblon', partner_type_ids: [12,14]}];
- this.data.partner.records[0].product_id = 1;
+ testConfig.serverData.models.product.fields.partner_type_ids = {string: "one2many field", type: "one2many", relation: "partner_type"},
+ testConfig.serverData.models.product.records = [{id: 1, name: 'Tromblon', partner_type_ids: [12,14]}];
+ testConfig.serverData.models.partner.records[0].product_id = 1;
- var actionManager = await createActionManager({
- data: this.data,
- archs: {
- 'product,false,form': '',
-
- 'partner_type,false,list': ''+
- ''+
- '',
- 'product,false,search': '',
- },
- mockRPC: function (route, args) {
- if (args.method === 'load_views') {
- var context = args.kwargs.context;
- if (args.model === 'product') {
- assert.deepEqual(context, {tree_view_ref: 'some_tree_view'},
- 'The correct _view_ref should have been sent to the server, first time');
- }
- if (args.model === 'partner_type') {
- assert.deepEqual(context, {
- base_model_name: 'product',
- tree_view_ref: 'some_other_tree_view',
- }, 'The correct _view_ref should have been sent to the server for the subview');
- }
- }
- return this._super.apply(this, arguments);
- },
- });
+ testConfig.serverData.views = {
+ 'product,false,form': '',
- var form = await createView({
- View: FormView,
- model: 'partner',
- data: this.data,
- arch: '',
- res_id: 1,
+ 'partner,false,search': '',
+ };
- mockRPC: function(route, args) {
- if (args.method === 'get_formview_action') {
- return Promise.resolve({
- res_id: 1,
- type: 'ir.actions.act_window',
- target: 'current',
- res_model: args.model,
- context: args.kwargs.context,
- 'view_mode': 'form',
- 'views': [[false, 'form']],
- });
+ const mockRPC = (route, args) => {
+ if (args.method === 'load_views') {
+ var context = args.kwargs.context;
+ if (args.model === 'product') {
+ assert.strictEqual(context.tree_view_ref, 'some_tree_view',
+ 'The correct _view_ref should have been sent to the server, first time');
}
- return this._super(route, args);
- },
+ if (args.model === 'partner_type') {
+ assert.strictEqual(context.base_model_name, 'product',
+ 'The correct base_model_name should have been sent to the server for the subview');
+ assert.strictEqual(context.tree_view_ref, 'some_other_tree_view',
+ 'The correct _view_ref should have been sent to the server for the subview');
+ }
+ }
+ if (args.method === 'get_formview_action') {
+ return Promise.resolve({
+ res_id: 1,
+ type: 'ir.actions.act_window',
+ target: 'current',
+ res_model: args.model,
+ context: args.kwargs.context,
+ 'view_mode': 'form',
+ 'views': [[false, 'form']],
+ });
+ }
+ };
- interceptsPropagate: {
- do_action: function (ev) {
- actionManager.doAction(ev.data.action);
- },
- },
+ const webClient = await createWebClient({testConfig, mockRPC});
+ await doAction(webClient, {
+ res_id: 1,
+ type: 'ir.actions.act_window',
+ target: 'current',
+ res_model: 'partner',
+ 'view_mode': 'form',
+ 'views': [[false, 'form']],
});
- await testUtils.dom.click(form.$('.o_field_widget[name="product_id"]'));
- form.destroy();
- actionManager.destroy();
+
+ await testUtils.dom.click(webClient.el.querySelector('.o_field_widget[name="product_id"]'));
});
QUnit.test('invisible fields are properly hidden', async function (assert) {
@@ -6812,10 +6813,16 @@ QUnit.module('Views', {
_t.database.multi_lang = multi_lang;
});
+ // LPE: map translationService to session
+ // with loading translations only once
QUnit.skip('translation alerts preseved on reverse breadcrumb', async function (assert) {
assert.expect(2);
- this.data['ir.translation'] = {
+ testConfig.localizationParameters = {
+ multiLang: true,
+ };
+
+ testConfig.serverData.models['ir.translation'] = {
fields: {
name: { string: "name", type: "char" },
source: {string: "Source", type: "char"},
@@ -6824,12 +6831,9 @@ QUnit.module('Views', {
records: [],
};
- this.data.partner.fields.foo.translate = true;
-
- var multi_lang = _t.database.multi_lang;
- _t.database.multi_lang = true;
+ testConfig.serverData.models.partner.fields.foo.translate = true;
- var archs = {
+ testConfig.serverData.views = {
'partner,false,form': '
+ `,
+ 'partner,false,search': '',
+ };
+
+ const mockRPC = (route, args) => {
+ if (args.method === 'write') {
+ assert.deepEqual(args.args, [
+ [1],
+ { name: "aaa" },
+ ]);
+ }
+ };
+
+ const webClient = await createWebClient({ testConfig , mockRPC });
- await testUtils.dom.click(actionManager.$('.o_data_row:first'));
- assert.strictEqual(actionManager.$('.breadcrumb').text(), 'Partnerfirst record');
+ await doAction(webClient, 1);
- await testUtils.dom.click(actionManager.$('.o_form_button_edit'));
- await testUtils.fields.editInput(actionManager.$('.o_field_widget[name="name"]'), 'aaa');
+ await testUtils.dom.click($(webClient.el).find('.o_data_row:first'));
+ await legacyExtraNextTick();
+ assert.strictEqual($(webClient.el).find('.breadcrumb').text(), 'Partnerfirst record');
- await testUtils.controlPanel.pagerNext(actionManager);
- assert.containsOnce(actionManager, '.o_form_editable');
- assert.strictEqual(actionManager.$('.breadcrumb').text(), 'Partnersecond record');
- assert.strictEqual(actionManager.$('.o_field_widget[name="name"]').val(), 'name');
+ await testUtils.dom.click($(webClient.el).find('.o_form_button_edit'));
+ await testUtils.fields.editInput($(webClient.el).find('.o_field_widget[name="name"]'), 'aaa');
- await testUtils.dom.click(actionManager.$('.o_form_button_cancel'));
- assert.strictEqual(actionManager.$('.breadcrumb').text(), 'Partnersecond record');
- assert.strictEqual(actionManager.$('.o_field_widget[name="name"]').text(), 'name');
+ await testUtils.controlPanel.pagerNext(webClient);
+ await legacyExtraNextTick();
+ assert.containsOnce(webClient, '.o_form_editable');
+ assert.strictEqual($(webClient.el).find('.breadcrumb').text(), 'Partnersecond record');
+ assert.strictEqual($(webClient.el).find('.o_field_widget[name="name"]').val(), 'name');
- await testUtils.controlPanel.pagerPrevious(actionManager);
- assert.containsOnce(actionManager, '.o_form_readonly');
- assert.strictEqual(actionManager.$('.breadcrumb').text(), 'Partnerfirst record');
- assert.strictEqual(actionManager.$('.o_field_widget[name="name"]').text(), 'aaa');
+ await testUtils.dom.click($(webClient.el).find('.o_form_button_cancel'));
+ assert.strictEqual($(webClient.el).find('.breadcrumb').text(), 'Partnersecond record');
+ assert.strictEqual($(webClient.el).find('.o_field_widget[name="name"]').text(), 'name');
- actionManager.destroy();
+ await testUtils.controlPanel.pagerPrevious(webClient);
+ await legacyExtraNextTick();
+ assert.containsOnce(webClient, '.o_form_readonly');
+ assert.strictEqual($(webClient.el).find('.breadcrumb').text(), 'Partnerfirst record');
+ assert.strictEqual($(webClient.el).find('.o_field_widget[name="name"]').text(), 'aaa');
});
- QUnit.skip('Auto save: save when breadcrumb clicked', async function (assert) {
+ QUnit.test('Auto save: save when breadcrumb clicked', async function (assert) {
assert.expect(7);
- const actions = [{
+ testConfig.serverData.actions[1] = {
id: 1,
name: 'Partner',
res_model: 'partner',
type: 'ir.actions.act_window',
views: [[false, 'list'], [false, 'form']],
- }];
+ };
- const actionManager = await createActionManager({
- actions,
- data: this.data,
- archs: {
- 'partner,false,list': `
-
+ testConfig.serverData.views = {
+ 'partner,false,list': `
+
+
+
+ `,
+ 'partner,false,form': `
+
- `,
- 'partner,false,form': `
-
- `,
- 'partner,false,search': '',
- },
- mockRPC(route, { args, method }) {
- if (method === 'write') {
- assert.deepEqual(args, [
- [1],
- { name: "aaa" },
- ]);
- }
- return this._super(...arguments);
- },
- });
- await actionManager.doAction(1);
+
+
+ `,
+ 'partner,false,search': '',
+ };
+
+ const mockRPC = (route, args) => {
+ if (args.method === 'write') {
+ assert.deepEqual(args.args, [
+ [1],
+ { name: "aaa" },
+ ]);
+ }
+ };
+
+ const webClient = await createWebClient({ testConfig , mockRPC });
- await testUtils.dom.click(actionManager.$('.o_data_row:first'));
- assert.strictEqual(actionManager.$('.breadcrumb').text(), 'Partnerfirst record');
+ await doAction(webClient, 1);
- await testUtils.dom.click(actionManager.$('.o_form_button_edit'));
- await testUtils.fields.editInput(actionManager.$('.o_field_widget[name="name"]'), 'aaa');
+ await testUtils.dom.click($(webClient.el).find('.o_data_row:first'));
+ await legacyExtraNextTick();
+ assert.strictEqual($(webClient.el).find('.breadcrumb').text(), 'Partnerfirst record');
- await testUtils.dom.click(actionManager.$('.breadcrumb-item.o_back_button'));
+ await testUtils.dom.click($(webClient.el).find('.o_form_button_edit'));
+ await testUtils.fields.editInput($(webClient.el).find('.o_field_widget[name="name"]'), 'aaa');
- assert.strictEqual(actionManager.$('.breadcrumb').text(), 'Partner');
- assert.strictEqual(actionManager.$('.o_field_cell[name="name"]:first').text(), 'aaa');
+ await testUtils.dom.click($(webClient.el).find('.breadcrumb-item.o_back_button'));
+ await legacyExtraNextTick();
- await testUtils.dom.click(actionManager.$('.o_data_row:first'));
- assert.containsOnce(actionManager, '.o_form_readonly');
- assert.strictEqual(actionManager.$('.breadcrumb').text(), 'Partnerfirst record');
- assert.strictEqual(actionManager.$('.o_field_widget[name="name"]').text(), 'aaa');
+ assert.strictEqual($(webClient.el).find('.breadcrumb').text(), 'Partner');
+ assert.strictEqual($(webClient.el).find('.o_field_cell[name="name"]:first').text(), 'aaa');
- actionManager.destroy();
+ await testUtils.dom.click($(webClient.el).find('.o_data_row:first'));
+ await legacyExtraNextTick();
+ assert.containsOnce(webClient, '.o_form_readonly');
+ assert.strictEqual($(webClient.el).find('.breadcrumb').text(), 'Partnerfirst record');
+ assert.strictEqual($(webClient.el).find('.o_field_widget[name="name"]').text(), 'aaa');
});
- QUnit.skip('Auto save: save when action changed', async function (assert) {
+ QUnit.test('Auto save: save when action changed', async function (assert) {
assert.expect(6);
- const actions = [{
+ testConfig.serverData.actions[1] = {
id: 1,
name: 'Partner',
res_model: 'partner',
type: 'ir.actions.act_window',
views: [[false, 'list'], [false, 'form']],
- }, {
+ };
+
+ testConfig.serverData.actions[2] = {
id: 2,
name: 'Other action',
res_model: 'partner',
type: 'ir.actions.act_window',
views: [[false, 'kanban']],
- }];
+ };
- const actionManager = await createActionManager({
- actions,
- data: this.data,
- archs: {
- 'partner,false,list': `
-
-
-
- `,
- 'partner,false,form': `
-
- `,
- 'partner,false,search': '',
- 'partner,false,kanban': `
-
+ testConfig.serverData.views = {
+ 'partner,false,list': `
+
+
+
+ `,
+ 'partner,false,form': `
+
- `,
- },
- mockRPC(route, { args, method }) {
- if (method === 'write') {
- assert.deepEqual(args, [
- [1],
- { name: "aaa" },
- ]);
- }
- return this._super(...arguments);
- },
- });
- await actionManager.doAction(1);
+
+
+ `,
+ 'partner,false,search': '',
+ 'partner,false,kanban': `
+
+
+
+
+
+
+
+
+ `,
+ };
+
+ const mockRPC = (route, args) => {
+ if (args.method === 'write') {
+ assert.deepEqual(args.args, [
+ [1],
+ { name: "aaa" },
+ ]);
+ }
+ };
+
+ const webClient = await createWebClient({ testConfig , mockRPC });
- await testUtils.dom.click(actionManager.$('.o_data_row:first'));
- assert.strictEqual(actionManager.$('.breadcrumb').text(), 'Partnerfirst record');
+ await doAction(webClient, 1);
- await testUtils.dom.click(actionManager.$('.o_form_button_edit'));
- await testUtils.fields.editInput(actionManager.$('.o_field_widget[name="name"]'), 'aaa');
+ await testUtils.dom.click($(webClient.el).find('.o_data_row:first'));
+ await legacyExtraNextTick();
+ assert.strictEqual($(webClient.el).find('.breadcrumb').text(), 'Partnerfirst record');
- await actionManager.doAction(2, { clear_breadcrumbs: true });
+ await testUtils.dom.click($(webClient.el).find('.o_form_button_edit'));
+ await testUtils.fields.editInput($(webClient.el).find('.o_field_widget[name="name"]'), 'aaa');
- assert.strictEqual(actionManager.$('.breadcrumb').text(), 'Other action');
+ await doAction(webClient, 2, { clearBreadcrumbs: true });
- await actionManager.doAction(1, { clear_breadcrumbs: true });
+ assert.strictEqual($(webClient.el).find('.breadcrumb').text(), 'Other action');
- await testUtils.dom.click(actionManager.$('.o_data_row:first'));
- assert.containsOnce(actionManager, '.o_form_readonly');
- assert.strictEqual(actionManager.$('.breadcrumb').text(), 'Partnerfirst record');
- assert.strictEqual(actionManager.$('.o_field_widget[name="name"]').text(), 'aaa');
+ await doAction(webClient, 1, { clearBreadcrumbs: true });
- actionManager.destroy();
+ await testUtils.dom.click($(webClient.el).find('.o_data_row:first'));
+ await legacyExtraNextTick();
+ assert.containsOnce(webClient, '.o_form_readonly');
+ assert.strictEqual($(webClient.el).find('.breadcrumb').text(), 'Partnerfirst record');
+ assert.strictEqual($(webClient.el).find('.o_field_widget[name="name"]').text(), 'aaa');
});
QUnit.test('Auto save: save on closing tab/browser', async function (assert) {
@@ -10025,51 +10017,52 @@ QUnit.module('Views', {
form.destroy();
});
- QUnit.skip('Auto save: save on closing tab/browser (detached form)', async function (assert) {
+ QUnit.test('Auto save: save on closing tab/browser (detached form)', async function (assert) {
assert.expect(3);
- const actions = [{
+ testConfig.serverData.actions[1] = {
id: 1,
name: 'Partner',
res_model: 'partner',
type: 'ir.actions.act_window',
views: [[false, 'list'], [false, 'form']],
- }];
+ };
- const actionManager = await createActionManager({
- actions,
- data: this.data,
- archs: {
- 'partner,false,list': `
-
+ testConfig.serverData.views = {
+ 'partner,false,list': `
+
+
+
+ `,
+ 'partner,false,form': `
+
- `,
- 'partner,false,form': `
-
- `,
- 'partner,false,search': '',
- },
- mockRPC(route, { args, method }) {
- if (method === 'write') {
- assert.step('save');
- }
- return this._super(...arguments);
- },
- });
- await actionManager.doAction(1);
+
+
+ `,
+ 'partner,false,search': '',
+ };
+
+ const mockRPC = (route, args) => {
+ if (args.method === 'write') {
+ assert.step('save');
+ }
+ };
+
+ const webClient = await createWebClient({ testConfig , mockRPC });
+
+ await doAction(webClient, 1);
// Click on a row to open a record
- await testUtils.dom.click(actionManager.$('.o_data_row:first'));
- assert.strictEqual(actionManager.$('.breadcrumb').text(), 'Partnerfirst record');
+ await testUtils.dom.click($(webClient.el).find('.o_data_row:first'));
+ await legacyExtraNextTick();
+ assert.strictEqual($(webClient.el).find('.breadcrumb').text(), 'Partnerfirst record');
// Return in the list view to detach the form view
- await testUtils.dom.click(actionManager.$('.o_back_button'));
- assert.strictEqual(actionManager.$('.breadcrumb').text(), 'Partner');
+ await testUtils.dom.click($(webClient.el).find('.o_back_button'));
+ await legacyExtraNextTick();
+ assert.strictEqual($(webClient.el).find('.breadcrumb').text(), 'Partner');
// Simulate tab/browser close in the list
window.dispatchEvent(new Event("beforeunload"));
@@ -10078,8 +10071,6 @@ QUnit.module('Views', {
// write rpc should not trigger because form view has been detached
// and list has nothing to save
assert.verifySteps([]);
-
- actionManager.destroy();
});
QUnit.test('Auto save: save on closing tab/browser (onchanges)', async function (assert) {
diff --git a/addons/web/static/tests/legacy/views/graph_tests.js b/addons/web/static/tests/legacy/views/graph_tests.js
index e9872c31f4426..ed6ede924e998 100644
--- a/addons/web/static/tests/legacy/views/graph_tests.js
+++ b/addons/web/static/tests/legacy/views/graph_tests.js
@@ -6,6 +6,9 @@ const GraphView = require('web.GraphView');
const testUtils = require('web.test_utils');
const { sortBy } = require('web.utils');
+const { legacyExtraNextTick } = require("@web/../tests/helpers/utils");
+const { createWebClient, doAction, getActionManagerTestConfig } = require('@web/../tests/webclient/actions/helpers');
+
const { createView } = testUtils;
const cpHelpers = testUtils.controlPanel;
const patchDate = testUtils.mock.patchDate;
@@ -72,6 +75,7 @@ function checkLegend(assert, graph, expectedLegendLabels) {
assert.deepEqual(actualLegendLabels, expectedLegendLabels);
}
+let testConfig;
QUnit.module('Views', {
beforeEach: function () {
this.data = {
@@ -120,6 +124,9 @@ QUnit.module('Views', {
}]
},
};
+
+ testConfig = getActionManagerTestConfig();
+ Object.assign(testConfig.serverData, {models: this.data});
}
}, function () {
@@ -783,28 +790,28 @@ QUnit.module('Views', {
graph.destroy();
});
- QUnit.skip('measure dropdown consistency', async function (assert) {
+ QUnit.test('measure dropdown consistency', async function (assert) {
assert.expect(2);
- const actionManager = await testUtils.createActionManager({
- archs: {
- 'foo,false,graph': `
-
-
- `,
- 'foo,false,search': ``,
- 'foo,false,kanban': `
-
-
-
-
-
-
- `,
- },
- data: this.data,
- });
- await actionManager.doAction({
+ testConfig.serverData.views = {
+ 'foo,false,graph': `
+
+
+ `,
+ 'foo,false,search': ``,
+ 'foo,false,kanban': `
+
+
+
+
+
+
+ `,
+ };
+
+ const webClient = await createWebClient({ testConfig });
+
+ await doAction(webClient, {
res_model: 'foo',
type: 'ir.actions.act_window',
views: [[false, 'graph'], [false, 'kanban']],
@@ -815,18 +822,18 @@ QUnit.module('Views', {
},
});
- assert.containsOnce(actionManager, '.o_control_panel .o_graph_measures_list',
+ assert.containsOnce(webClient, '.o_control_panel .o_graph_measures_list',
"Measures dropdown is present at init"
);
- await cpHelpers.switchView(actionManager, 'kanban');
- await cpHelpers.switchView(actionManager, 'graph');
+ await cpHelpers.switchView(webClient, 'kanban');
+ await legacyExtraNextTick();
+ await cpHelpers.switchView(webClient, 'graph');
+ await legacyExtraNextTick();
- assert.containsOnce(actionManager, '.o_control_panel .o_graph_measures_list',
+ assert.containsOnce(webClient, '.o_control_panel .o_graph_measures_list',
"Measures dropdown is present after reload"
);
-
- actionManager.destroy();
});
QUnit.test('graph view crash when moving from search view using Down key', async function (assert) {
diff --git a/addons/web/static/tests/legacy/views/list_tests.js b/addons/web/static/tests/legacy/views/list_tests.js
index fdc90033a6d51..9413e467d35f7 100644
--- a/addons/web/static/tests/legacy/views/list_tests.js
+++ b/addons/web/static/tests/legacy/views/list_tests.js
@@ -24,9 +24,13 @@ var Widget = require('web.Widget');
var _t = core._t;
const cpHelpers = testUtils.controlPanel;
-var createActionManager = testUtils.createActionManager;
var createView = testUtils.createView;
+const { legacyExtraNextTick } = require("@web/../tests/helpers/utils");
+const { createWebClient, doAction, getActionManagerTestConfig, loadState } = require('@web/../tests/webclient/actions/helpers');
+
+let testConfig;
+
QUnit.module('Views', {
beforeEach: function () {
this.data = {
@@ -128,6 +132,9 @@ QUnit.module('Views', {
}]
},
};
+
+ testConfig = getActionManagerTestConfig();
+ Object.assign(testConfig.serverData, {models: this.data});
}
}, function () {
@@ -1762,45 +1769,42 @@ QUnit.module('Views', {
list.destroy();
});
- QUnit.skip('editable list view: check that controlpanel buttons are updating when groupby applied', async function (assert) {
+ QUnit.test('editable list view: check that controlpanel buttons are updating when groupby applied', async function (assert) {
assert.expect(4);
- this.data.foo.fields.foo = {string: "Foo", type: "char", required:true};
+ testConfig.serverData.models.foo.fields.foo = {string: "Foo", type: "char", required:true};
- var actionManager = await createActionManager({
- actions: [{
- id: 11,
- name: 'Partners Action 11',
- res_model: 'foo',
- type: 'ir.actions.act_window',
- views: [[3, 'list']],
- search_view_id: [9, 'search'],
- }],
- archs: {
- 'foo,3,list': '',
+ testConfig.serverData.actions[11] = {
+ id: 11,
+ name: 'Partners Action 11',
+ res_model: 'foo',
+ type: 'ir.actions.act_window',
+ views: [[3, 'list']],
+ search_view_id: [9, 'search'],
+ };
+ testConfig.serverData.views = {
+ 'foo,3,list': '',
- 'foo,9,search': ''+
- '' +
- '',
- },
- data: this.data,
- });
+ 'foo,9,search': ''+
+ '' +
+ '',
+ };
- await actionManager.doAction(11);
- await testUtils.dom.click(actionManager.$('.o_list_button_add'));
+ const webClient = await createWebClient({ testConfig });
- assert.isNotVisible(actionManager.$('.o_list_button_add'),
+ await doAction(webClient, 11);
+ await testUtils.dom.click($(webClient.el).find('.o_list_button_add'));
+
+ assert.isNotVisible($(webClient.el).find('.o_list_button_add'),
"create button should be invisible");
- assert.isVisible(actionManager.$('.o_list_button_save'), "save button should be visible");
+ assert.isVisible($(webClient.el).find('.o_list_button_save'), "save button should be visible");
- await testUtils.dom.click(actionManager.$('.o_dropdown_toggler_btn:contains("Group By")'));
- await testUtils.dom.click(actionManager.$('.o_group_by_menu .o_menu_item a:contains("candle")'));
+ await testUtils.dom.click($(webClient.el).find('.o_dropdown_toggler_btn:contains("Group By")'));
+ await testUtils.dom.click($(webClient.el).find('.o_group_by_menu .o_menu_item a:contains("candle")'));
- assert.isNotVisible(actionManager.$('.o_list_button_add'), "create button should be invisible");
- assert.isNotVisible(actionManager.$('.o_list_button_save'),
+ assert.isNotVisible($(webClient.el).find('.o_list_button_add'), "create button should be invisible");
+ assert.isNotVisible($(webClient.el).find('.o_list_button_save'),
"save button should be invisible after applying groupby");
-
- actionManager.destroy();
});
QUnit.test('list view not groupable', async function (assert) {
@@ -9305,62 +9309,60 @@ QUnit.module('Views', {
list.destroy();
});
- QUnit.skip('add filter in a grouped list with a pager', async function (assert) {
+ QUnit.test('add filter in a grouped list with a pager', async function (assert) {
assert.expect(11);
- const actionManager = await createActionManager({
- data: this.data,
- actions: [{
- id: 11,
- name: 'Action 11',
- res_model: 'foo',
- type: 'ir.actions.act_window',
- views: [[3, 'list']],
- search_view_id: [9, 'search'],
- flags: {
- context: { group_by: ['int_field'] },
- },
- }],
- archs: {
- 'foo,3,list': '',
- 'foo,9,search': `
-
-
- `,
- },
- mockRPC: function (route, args) {
- if (args.method === 'web_read_group') {
- assert.step(JSON.stringify(args.kwargs.domain) + ', ' + args.kwargs.offset);
- }
- return this._super.apply(this, arguments);
+ testConfig.serverData.actions[11] = {
+ id: 11,
+ name: 'Action 11',
+ res_model: 'foo',
+ type: 'ir.actions.act_window',
+ views: [[3, 'list']],
+ search_view_id: [9, 'search'],
+ flags: {
+ context: { group_by: ['int_field'] },
},
- });
+ };
- await actionManager.doAction(11);
+ testConfig.serverData.views = {
+ 'foo,3,list': '',
+ 'foo,9,search': `
+
+
+ `,
+ };
- assert.containsOnce(actionManager, '.o_list_view');
- assert.strictEqual(actionManager.$('.o_pager_counter').text().trim(), '1-3 / 4');
- assert.containsN(actionManager, '.o_group_header', 3); // page 1
+ const mockRPC = (route, args) => {
+ if (args.method === 'web_read_group') {
+ assert.step(JSON.stringify(args.kwargs.domain) + ', ' + args.kwargs.offset);
+ }
+ };
+
+ const webClient = await createWebClient({testConfig, mockRPC});
+ await doAction(webClient, 11);
+
+ assert.containsOnce(webClient, '.o_list_view');
+ assert.strictEqual($(webClient.el).find('.o_pager_counter').text().trim(), '1-3 / 4');
+ assert.containsN(webClient, '.o_group_header', 3); // page 1
- await testUtils.dom.click(actionManager.$('.o_pager_next')); // switch to page 2
+ await testUtils.dom.click($(webClient.el).find('.o_pager_next')); // switch to page 2
+ await legacyExtraNextTick();
- assert.strictEqual(actionManager.$('.o_pager_counter').text().trim(), '4-4 / 4');
- assert.containsN(actionManager, '.o_group_header', 1); // page 2
+ assert.strictEqual($(webClient.el).find('.o_pager_counter').text().trim(), '4-4 / 4');
+ assert.containsN(webClient, '.o_group_header', 1); // page 2
// toggle a filter -> there should be only one group left (on page 1)
- await cpHelpers.toggleFilterMenu(actionManager);
- await cpHelpers.toggleMenuItem(actionManager, 0);
+ await cpHelpers.toggleFilterMenu(webClient);
+ await cpHelpers.toggleMenuItem(webClient, 0);
- assert.strictEqual(actionManager.$('.o_pager_counter').text().trim(), '1-1 / 1');
- assert.containsN(actionManager, '.o_group_header', 1); // page 1
+ assert.strictEqual($(webClient.el).find('.o_pager_counter').text().trim(), '1-1 / 1');
+ assert.containsN(webClient, '.o_group_header', 1); // page 1
assert.verifySteps([
'[], undefined',
'[], 3',
'[["bar","=",false]], undefined',
]);
-
- actionManager.destroy();
});
QUnit.test('editable grouped lists', async function (assert) {
@@ -10878,24 +10880,25 @@ QUnit.module('Views', {
delete fieldRegistry.map.asyncwidget;
});
- QUnit.skip('change the viewType of the current action', async function (assert) {
+ QUnit.test('change the viewType of the current action', async function (assert) {
assert.expect(25);
- this.actions = [{
+ testConfig.serverData.actions[1] = {
id: 1,
name: 'Partners Action 1',
res_model: 'foo',
type: 'ir.actions.act_window',
views: [[1, 'kanban']],
- }, {
+ };
+ testConfig.serverData.actions[2] = {
id: 2,
name: 'Partners',
res_model: 'foo',
type: 'ir.actions.act_window',
views: [[false, 'list'], [1, 'kanban']],
- }];
+ };
- this.archs = {
+ testConfig.serverData.views = {
'foo,1,kanban': '' +
'
' +
'',
@@ -10908,94 +10911,82 @@ QUnit.module('Views', {
'foo,false,search': '',
};
- var RamStorageService = AbstractStorageService.extend({
- storage: new RamStorage(),
- });
+ const webClient = await createWebClient({ testConfig });
- var actionManager = await testUtils.createActionManager({
- actions: this.actions,
- archs: this.archs,
- data: this.data,
- services: {
- local_storage: RamStorageService,
- },
- });
- await actionManager.doAction(2);
+ await doAction(webClient, 2);
- assert.containsOnce(actionManager, '.o_list_view',
+ assert.containsOnce(webClient, '.o_list_view',
"should have rendered a list view");
- assert.containsN(actionManager, 'th', 3, "should display 3 th (selector + 2 fields)");
+ assert.containsN(webClient, 'th', 3, "should display 3 th (selector + 2 fields)");
// enable optional field
- await testUtils.dom.click(actionManager.$('table .o_optional_columns_dropdown_toggle'));
- assert.notOk(actionManager.$('div.o_optional_columns div.dropdown-item [name="m2o"]').is(":checked"));
- assert.ok(actionManager.$('div.o_optional_columns div.dropdown-item [name="o2m"]').is(":checked"));
- await testUtils.dom.click(actionManager.$('div.o_optional_columns div.dropdown-item:first'));
- assert.containsN(actionManager, 'th', 4, "should display 4 th (selector + 3 fields)");
- assert.ok(actionManager.$('th:contains(M2O field)').is(':visible'),
+ await testUtils.dom.click($(webClient.el).find('table .o_optional_columns_dropdown_toggle'));
+ assert.notOk($(webClient.el).find('div.o_optional_columns div.dropdown-item [name="m2o"]').is(":checked"));
+ assert.ok($(webClient.el).find('div.o_optional_columns div.dropdown-item [name="o2m"]').is(":checked"));
+ await testUtils.dom.click($(webClient.el).find('div.o_optional_columns div.dropdown-item:first'));
+ assert.containsN(webClient, 'th', 4, "should display 4 th (selector + 3 fields)");
+ assert.ok($(webClient.el).find('th:contains(M2O field)').is(':visible'),
"should have a visible m2o field"); //m2o field
// switch to kanban view
- await actionManager.loadState({
+ await loadState(webClient, {
action: 2,
view_type: 'kanban',
});
- assert.containsNone(actionManager, '.o_list_view',
+ assert.containsNone(webClient, '.o_list_view',
"should not display the list view anymore");
- assert.containsOnce(actionManager, '.o_kanban_view',
+ assert.containsOnce(webClient, '.o_kanban_view',
"should have switched to the kanban view");
// switch back to list view
- await actionManager.loadState({
+ await loadState(webClient, {
action: 2,
view_type: 'list',
});
- assert.containsNone(actionManager, '.o_kanban_view',
+ assert.containsNone(webClient, '.o_kanban_view',
"should not display the kanban view anymoe");
- assert.containsOnce(actionManager, '.o_list_view',
+ assert.containsOnce(webClient, '.o_list_view',
"should display the list view");
- assert.containsN(actionManager, 'th', 4, "should display 4 th");
- assert.ok(actionManager.$('th:contains(M2O field)').is(':visible'),
+ assert.containsN(webClient, 'th', 4, "should display 4 th");
+ assert.ok($(webClient.el).find('th:contains(M2O field)').is(':visible'),
"should have a visible m2o field"); //m2o field
- assert.ok(actionManager.$('th:contains(O2M field)').is(':visible'),
+ assert.ok($(webClient.el).find('th:contains(O2M field)').is(':visible'),
"should have a visible o2m field"); //m2o field
// disable optional field
- await testUtils.dom.click(actionManager.$('table .o_optional_columns_dropdown_toggle'));
- assert.ok(actionManager.$('div.o_optional_columns div.dropdown-item [name="m2o"]').is(":checked"));
- assert.ok(actionManager.$('div.o_optional_columns div.dropdown-item [name="o2m"]').is(":checked"));
- await testUtils.dom.click(actionManager.$('div.o_optional_columns div.dropdown-item:last input'));
- assert.ok(actionManager.$('th:contains(M2O field)').is(':visible'),
+ await testUtils.dom.click($(webClient.el).find('table .o_optional_columns_dropdown_toggle'));
+ assert.ok($(webClient.el).find('div.o_optional_columns div.dropdown-item [name="m2o"]').is(":checked"));
+ assert.ok($(webClient.el).find('div.o_optional_columns div.dropdown-item [name="o2m"]').is(":checked"));
+ await testUtils.dom.click($(webClient.el).find('div.o_optional_columns div.dropdown-item:last input'));
+ assert.ok($(webClient.el).find('th:contains(M2O field)').is(':visible'),
"should have a visible m2o field"); //m2o field
- assert.notOk(actionManager.$('th:contains(O2M field)').is(':visible'),
+ assert.notOk($(webClient.el).find('th:contains(O2M field)').is(':visible'),
"should have a visible o2m field"); //m2o field
- assert.containsN(actionManager, 'th', 3, "should display 3 th");
+ assert.containsN(webClient, 'th', 3, "should display 3 th");
- await actionManager.doAction(1);
+ await doAction(webClient, 1);
- assert.containsNone(actionManager, '.o_list_view',
+ assert.containsNone(webClient, '.o_list_view',
"should not display the list view anymore");
- assert.containsOnce(actionManager, '.o_kanban_view',
+ assert.containsOnce(webClient, '.o_kanban_view',
"should have switched to the kanban view");
- await actionManager.doAction(2);
+ await doAction(webClient, 2);
- assert.containsNone(actionManager, '.o_kanban_view',
+ assert.containsNone(webClient, '.o_kanban_view',
"should not havethe kanban view anymoe");
- assert.containsOnce(actionManager, '.o_list_view',
+ assert.containsOnce(webClient, '.o_list_view',
"should display the list view");
- assert.containsN(actionManager, 'th', 3, "should display 3 th");
- assert.ok(actionManager.$('th:contains(M2O field)').is(':visible'),
+ assert.containsN(webClient, 'th', 3, "should display 3 th");
+ assert.ok($(webClient.el).find('th:contains(M2O field)').is(':visible'),
"should have a visible m2o field"); //m2o field
- assert.notOk(actionManager.$('th:contains(O2M field)').is(':visible'),
+ assert.notOk($(webClient.el).find('th:contains(O2M field)').is(':visible'),
"should have a visible o2m field"); //m2o field
-
- actionManager.destroy();
});
QUnit.test('list view with optional fields rendering and local storage mock', async function (assert) {
@@ -11464,135 +11455,126 @@ QUnit.module('Views', {
list.destroy();
});
- QUnit.skip("Auto save: add a record and leave action", async function (assert) {
+ QUnit.test("Auto save: add a record and leave action", async function (assert) {
assert.expect(4);
- const actionManager = await createActionManager({
- actions: [{
- id: 1,
- name: 'Action 1',
- res_model: 'foo',
- type: 'ir.actions.act_window',
- views: [[2, 'list']],
- search_view_id: [1, 'search'],
- }, {
- id: 2,
- name: 'Action 2',
- res_model: 'foo',
- type: 'ir.actions.act_window',
- views: [[3, 'list']],
- search_view_id: [1, 'search'],
- }],
- archs: {
- 'foo,1,search': '',
- 'foo,2,list': '',
- 'foo,3,list': '',
- },
- data: this.data,
- });
+ testConfig.serverData.actions[1] = {
+ id: 1,
+ name: 'Action 1',
+ res_model: 'foo',
+ type: 'ir.actions.act_window',
+ views: [[2, 'list']],
+ search_view_id: [1, 'search'],
+ };
+ testConfig.serverData.actions[2] = {
+ id: 2,
+ name: 'Action 2',
+ res_model: 'foo',
+ type: 'ir.actions.act_window',
+ views: [[3, 'list']],
+ search_view_id: [1, 'search'],
+ };
+ testConfig.serverData.views = {
+ 'foo,1,search': '',
+ 'foo,2,list': '',
+ 'foo,3,list': '',
+ };
+ const webClient = await createWebClient({ testConfig });
- await actionManager.doAction(1);
+ await doAction(webClient, 1);
- assert.strictEqual(actionManager.$('.o_field_cell[name="foo"]').text(), "yopblipgnapblip");
- assert.containsN(actionManager, '.o_data_row', 4);
+ assert.strictEqual($(webClient.el).find('.o_field_cell[name="foo"]').text(), "yopblipgnapblip");
+ assert.containsN(webClient, '.o_data_row', 4);
- await testUtils.dom.click(actionManager.$('.o_list_button_add'));
- await testUtils.fields.editInput(actionManager.$('.o_field_widget[name="foo"]'), "test");
+ await testUtils.dom.click($(webClient.el).find('.o_list_button_add'));
+ await testUtils.fields.editInput($(webClient.el).find('.o_field_widget[name="foo"]'), "test");
// change action and come back
- await actionManager.doAction(2);
- await actionManager.doAction(1, { clear_breadcrumbs: true });
-
- assert.strictEqual(actionManager.$('.o_field_cell[name="foo"]').text(), "yopblipgnapbliptest");
- assert.containsN(actionManager, '.o_data_row', 5);
+ await doAction(webClient, 2);
+ await doAction(webClient, 1, { clearBreadcrumbs: true });
- actionManager.destroy();
+ assert.strictEqual($(webClient.el).find('.o_field_cell[name="foo"]').text(), "yopblipgnapbliptest");
+ assert.containsN(webClient, '.o_data_row', 5);
});
- QUnit.skip("Auto save: modify a record and leave action", async function (assert) {
+ QUnit.test("Auto save: modify a record and leave action", async function (assert) {
assert.expect(2);
- const actionManager = await createActionManager({
- actions: [{
- id: 1,
- name: 'Action 1',
- res_model: 'foo',
- type: 'ir.actions.act_window',
- views: [[2, 'list']],
- search_view_id: [1, 'search'],
- }, {
- id: 2,
- name: 'Action 2',
- res_model: 'foo',
- type: 'ir.actions.act_window',
- views: [[3, 'list']],
- search_view_id: [1, 'search'],
- }],
- archs: {
- 'foo,1,search': '',
- 'foo,2,list': '',
- 'foo,3,list': '',
- },
- data: this.data,
- });
+ testConfig.serverData.actions[1] = {
+ id: 1,
+ name: 'Action 1',
+ res_model: 'foo',
+ type: 'ir.actions.act_window',
+ views: [[2, 'list']],
+ search_view_id: [1, 'search'],
+ };
+ testConfig.serverData.actions[2] = {
+ id: 2,
+ name: 'Action 2',
+ res_model: 'foo',
+ type: 'ir.actions.act_window',
+ views: [[3, 'list']],
+ search_view_id: [1, 'search'],
+ };
+ testConfig.serverData.views = {
+ 'foo,1,search': '',
+ 'foo,2,list': '',
+ 'foo,3,list': '',
+ };
+ const webClient = await createWebClient({ testConfig });
- await actionManager.doAction(1);
+ await doAction(webClient, 1);
- assert.strictEqual(actionManager.$('.o_field_cell[name="foo"]').text(), "yopblipgnapblip");
+ assert.strictEqual($(webClient.el).find('.o_field_cell[name="foo"]').text(), "yopblipgnapblip");
- await testUtils.dom.click(actionManager.$('.o_field_cell[name="foo"]:first'));
- await testUtils.fields.editInput(actionManager.$('.o_field_widget[name="foo"]'), "test");
+ await testUtils.dom.click($(webClient.el).find('.o_field_cell[name="foo"]:first'));
+ await testUtils.fields.editInput($(webClient.el).find('.o_field_widget[name="foo"]'), "test");
// change action and come back
- await actionManager.doAction(2);
- await actionManager.doAction(1, { clear_breadcrumbs: true });
+ await doAction(webClient, 2);
+ await doAction(webClient, 1, { clearBreadcrumbs: true });
- assert.strictEqual(actionManager.$('.o_field_cell[name="foo"]').text(), "testblipgnapblip");
-
- actionManager.destroy();
+ assert.strictEqual($(webClient.el).find('.o_field_cell[name="foo"]').text(), "testblipgnapblip");
});
- QUnit.skip("Auto save: modify a record and leave action (reject)", async function (assert) {
+ QUnit.test("Auto save: modify a record and leave action (reject)", async function (assert) {
assert.expect(5);
- const actionManager = await createActionManager({
- actions: [{
- id: 1,
- name: 'Action 1',
- res_model: 'foo',
- type: 'ir.actions.act_window',
- views: [[2, 'list']],
- search_view_id: [1, 'search'],
- }, {
- id: 2,
- name: 'Action 2',
- res_model: 'foo',
- type: 'ir.actions.act_window',
- views: [[3, 'list']],
- search_view_id: [1, 'search'],
- }],
- archs: {
- 'foo,1,search': '',
- 'foo,2,list': '',
- 'foo,3,list': '',
- },
- data: this.data,
- });
-
- await actionManager.doAction(1);
+ testConfig.serverData.actions[1] = {
+ id: 1,
+ name: 'Action 1',
+ res_model: 'foo',
+ type: 'ir.actions.act_window',
+ views: [[2, 'list']],
+ search_view_id: [1, 'search'],
+ };
+ testConfig.serverData.actions[2] = {
+ id: 2,
+ name: 'Action 2',
+ res_model: 'foo',
+ type: 'ir.actions.act_window',
+ views: [[3, 'list']],
+ search_view_id: [1, 'search'],
+ };
+ testConfig.serverData.views = {
+ 'foo,1,search': '',
+ 'foo,2,list': '',
+ 'foo,3,list': '',
+ };
+ const webClient = await createWebClient({ testConfig });
- assert.strictEqual(actionManager.$('.o_field_cell[name="foo"]').text(), "yopblipgnapblip");
+ await doAction(webClient,1);
- await testUtils.dom.click(actionManager.$('.o_field_cell[name="foo"]:first'));
- await testUtils.fields.editInput(actionManager.$('.o_field_widget[name="foo"]'), "");
+ assert.strictEqual($(webClient.el).find('.o_field_cell[name="foo"]').text(), "yopblipgnapblip");
- await assert.rejects(actionManager.doAction(2));
+ await testUtils.dom.click($(webClient.el).find('.o_field_cell[name="foo"]:first'));
+ await testUtils.fields.editInput($(webClient.el).find('.o_field_widget[name="foo"]'), "");
- assert.strictEqual(actionManager.$('.o_field_cell[name="foo"]').text(), "blipgnapblip");
- assert.hasClass(actionManager.$('.o_field_widget[name="foo"]:first'), 'o_field_invalid');
- assert.containsN(actionManager, '.o_data_row', 4);
+ await assert.rejects(doAction(webClient,2));
- actionManager.destroy();
+ assert.strictEqual($(webClient.el).find('.o_field_cell[name="foo"]').text(), "blipgnapblip");
+ assert.hasClass($(webClient.el).find('.o_field_widget[name="foo"]:first'), 'o_field_invalid');
+ assert.containsN(webClient, '.o_data_row', 4);
});
QUnit.test("Auto save: add a record and change page", async function (assert) {
diff --git a/addons/web/static/tests/legacy/views/pivot_tests.js b/addons/web/static/tests/legacy/views/pivot_tests.js
index e0fed1f4e15f6..22f65309dfafa 100644
--- a/addons/web/static/tests/legacy/views/pivot_tests.js
+++ b/addons/web/static/tests/legacy/views/pivot_tests.js
@@ -7,9 +7,10 @@ const PivotController = require("web.PivotController");
var testUtils = require('web.test_utils');
var testUtilsDom = require('web.test_utils_dom');
+const { createWebClient, doAction, getActionManagerTestConfig } = require('@web/../tests/webclient/actions/helpers');
+
var _t = core._t;
const cpHelpers = testUtils.controlPanel;
-var createActionManager = testUtils.createActionManager;
var createView = testUtils.createView;
var patchDate = testUtils.mock.patchDate;
@@ -26,6 +27,8 @@ var getCurrentValues = function (pivot) {
};
+let testConfig;
+
QUnit.module('Views', {
beforeEach: function () {
this.data = {
@@ -110,6 +113,9 @@ QUnit.module('Views', {
}]
},
};
+
+ testConfig = getActionManagerTestConfig();
+ Object.assign(testConfig.serverData, {models: this.data});
},
}, function () {
QUnit.module('PivotView');
@@ -2709,73 +2715,65 @@ QUnit.module('Views', {
pivot.destroy();
});
- QUnit.skip('Navigation list view for a group and back with breadcrumbs', async function (assert) {
+ QUnit.test('Navigation list view for a group and back with breadcrumbs', async function (assert) {
assert.expect(16);
- // create an action manager to test the interactions with the search view
- var readGroupCount = 0;
+ // create a webClient to test the interactions with the search view
+
+ testConfig.serverData.views = {
+ 'partner,false,pivot': '' +
+ '' +
+ '',
+ 'partner,false,search': '',
+ 'partner,false,list': '',
+ 'partner,false,form': '',
+ };
- var actionManager = await createActionManager({
- data: this.data,
- archs: {
- 'partner,false,pivot': '' +
- '' +
- '',
- 'partner,false,search': '',
- 'partner,false,list': '',
- 'partner,false,form': '',
- },
- intercepts: {
- do_action: function (event) {
- var action = event.data.action;
- actionManager.doAction(action);
- }
- },
- mockRPC: function (route, args) {
- if (args.method === 'read_group') {
- assert.step('read_group');
- const domain = args.kwargs.domain;
- if ([0,1].indexOf(readGroupCount) !== -1) {
- assert.deepEqual(domain, [], 'domain empty');
- } else if ([2,3,4,5].indexOf(readGroupCount) !== -1) {
- assert.deepEqual(domain, [['foo', '=', 12]],
- 'domain conserved when back with breadcrumbs');
- }
- readGroupCount++;
- }
- if (route === '/web/dataset/search_read') {
- assert.step('search_read');
- const domain = args.domain;
- assert.deepEqual(domain, ['&', ['customer', '=', 1], ['foo', '=', 12]],
- 'list domain is correct');
+ let readGroupCount = 0;
+ const mockRPC = (route, args) => {
+ if (args.method === 'read_group') {
+ assert.step('read_group');
+ const domain = args.kwargs.domain;
+ if ([0,1].indexOf(readGroupCount) !== -1) {
+ assert.deepEqual(domain, [], 'domain empty');
+ } else if ([2,3,4,5].indexOf(readGroupCount) !== -1) {
+ assert.deepEqual(domain, [['foo', '=', 12]],
+ 'domain conserved when back with breadcrumbs');
}
- return this._super.apply(this, arguments);
- },
- });
+ readGroupCount++;
+ }
+ if (route === '/web/dataset/search_read') {
+ assert.step('search_read');
+ const domain = args.domain;
+ assert.deepEqual(domain, ['&', ['customer', '=', 1], ['foo', '=', 12]],
+ 'list domain is correct');
+ }
+ };
+
+ const webClient = await createWebClient({testConfig, mockRPC});
- await actionManager.doAction({
+ await doAction(webClient, {
res_model: 'partner',
type: 'ir.actions.act_window',
views: [[false, 'pivot']],
});
- await cpHelpers.toggleFilterMenu(actionManager);
- await cpHelpers.toggleMenuItem(actionManager, 0);
+ await cpHelpers.toggleFilterMenu(webClient);
+ await cpHelpers.toggleMenuItem(webClient, 0);
await testUtils.nextTick();
- await testUtilsDom.click(actionManager.$('.o_pivot_cell_value:nth(1)'));
+ await testUtilsDom.click($(webClient.el).find('.o_pivot_cell_value:nth(1)'));
await testUtils.nextTick();
- assert.containsOnce(actionManager, '.o_list_view');
+ assert.containsOnce(webClient, '.o_list_view');
- await testUtilsDom.click(actionManager.$('.o_control_panel ol.breadcrumb li.breadcrumb-item').eq(0));
+ await testUtilsDom.click($(webClient.el).find('.o_control_panel ol.breadcrumb li.breadcrumb-item').eq(0));
assert.verifySteps([
'read_group', 'read_group',
'read_group', 'read_group',
'search_read',
'read_group', 'read_group']);
- actionManager.destroy();
});
QUnit.test('Cell values are kept when flippin a pivot view in comparison mode', async function (assert) {
diff --git a/addons/web/static/tests/legacy/views/qweb_tests.js b/addons/web/static/tests/legacy/views/qweb_tests.js
index 255126a05ad79..53db230fa2582 100644
--- a/addons/web/static/tests/legacy/views/qweb_tests.js
+++ b/addons/web/static/tests/legacy/views/qweb_tests.js
@@ -1,36 +1,40 @@
odoo.define('web.qweb_view_tests', function (require) {
"use strict";
-var utils = require('web.test_utils');
+const utils = require('web.test_utils');
+const { legacyExtraNextTick } = require("@web/../tests/helpers/utils");
+const { createWebClient, doAction, getActionManagerTestConfig } = require('@web/../tests/webclient/actions/helpers');
QUnit.module("Views", {
}, function () {
QUnit.module("QWeb");
- QUnit.skip("basic", async function (assert) {
+ QUnit.test("basic", async function (assert) {
assert.expect(14);
- var am = await utils.createActionManager({
- data: {
- test: {
- fields: {},
- records: [],
- }
- },
- archs: {
- 'test,5,qweb': '
',
- 'test,false,search': ''
- },
- mockRPC: function (route, args) {
- if (/^\/web\/dataset\/call_kw/.test(route)) {
- switch (_.str.sprintf('%(model)s.%(method)s', args)) {
+ const testConfig = getActionManagerTestConfig();
+
+ testConfig.serverData.models = {
+ test: {
+ fields: {},
+ records: [],
+ }
+ };
+ testConfig.serverData.views = {
+ 'test,5,qweb': '
',
+ 'test,false,search': ''
+ };
+
+ const mockRPC = (route, args) => {
+ if (/^\/web\/dataset\/call_kw/.test(route)) {
+ switch (_.str.sprintf('%(model)s.%(method)s', args)) {
case 'test.qweb_render_view':
assert.step('fetch');
assert.equal(args.kwargs.view_id, 5);
return Promise.resolve(
''
);
case 'test.wheee':
@@ -38,35 +42,32 @@ QUnit.module("Views", {
assert.deepEqual(args.args, [42]);
assert.deepEqual(args.kwargs, {other: 5});
return Promise.resolve('ok
');
- }
}
- return this._super.apply(this, arguments);
}
- });
- try {
- var resolved = false;
- am.doAction({
- type: 'ir.actions.act_window',
- views: [[false, 'qweb']],
- res_model: 'test',
- }).then(function () { resolved = true; });
- assert.ok(!resolved, "Action cannot be resolved synchronously");
+ };
+
+ const webClient = await createWebClient({testConfig, mockRPC});
+
+ let resolved = false;
+ const doActionProm = doAction(webClient, {
+ type: 'ir.actions.act_window',
+ views: [[false, 'qweb']],
+ res_model: 'test',
+ }).then(function () { resolved = true; });
+ assert.ok(!resolved, "Action cannot be resolved synchronously");
- await utils.nextTick();
- assert.ok(resolved, "Action is resolved asynchronously");
+ await doActionProm;
+ assert.ok(resolved, "Action is resolved asynchronously");
- var $content = am.$('.o_content');
- assert.ok(/^\s*foo/.test($content.text()));
- await utils.dom.click($content.find('[type=toggle]'));
- assert.equal($content.find('div#sub').text(), 'ok', 'should have unfolded the sub-item');
- await utils.dom.click($content.find('[type=toggle]'));
- assert.equal($content.find('div#sub').length, 0, "should have removed the sub-item");
- await utils.dom.click($content.find('[type=toggle]'));
+ const content = webClient.el.querySelector('.o_content');
+ assert.ok(/^\s*foo/.test(content.textContent));
+ await utils.dom.click(content.querySelector('[type=toggle]'));
+ assert.equal(content.querySelector('div#sub').textContent, 'ok', 'should have unfolded the sub-item');
+ await utils.dom.click(content.querySelector('[type=toggle]'));
+ assert.containsNone(content, "div#sub")
+ await utils.dom.click(content.querySelector('[type=toggle]'));
- assert.verifySteps(['fetch', 'unfold', 'unfold']);
- } finally {
- am.destroy();
- }
+ assert.verifySteps(['fetch', 'unfold', 'unfold']);
});
});
});
diff --git a/addons/web/static/tests/legacy/views/search_panel_tests.js b/addons/web/static/tests/legacy/views/search_panel_tests.js
index 8a90def96c0ad..c7a28be2d1f58 100644
--- a/addons/web/static/tests/legacy/views/search_panel_tests.js
+++ b/addons/web/static/tests/legacy/views/search_panel_tests.js
@@ -8,9 +8,11 @@ const testUtils = require('web.test_utils');
const SearchPanel = require("web.searchPanel");
const cpHelpers = testUtils.controlPanel;
-const createActionManager = testUtils.createActionManager;
const createView = testUtils.createView;
+const { createWebClient, doAction, getActionManagerTestConfig, loadState } = require('@web/../tests/webclient/actions/helpers');
+const { legacyExtraNextTick } = require("@web/../tests/helpers/utils");
+
/**
* Return the list of counters displayed in the search panel (if any).
* @param {Widget} view, view controller
@@ -36,6 +38,8 @@ function toggleFold(widget, text) {
return testUtils.dom.click(target);
}
+let testConfig;
+
QUnit.module('Views', {
beforeEach: function () {
this.data = {
@@ -116,6 +120,15 @@ QUnit.module('Views', {
`,
};
+
+ testConfig = getActionManagerTestConfig();
+
+ // map legacy test data
+ const actions = {};
+ this.actions.forEach((act) => {
+ actions[act.xmlId || act.id] = act;
+ });
+ Object.assign(testConfig.serverData, {actions, models: this.data, views: this.archs});
},
}, function () {
@@ -2317,39 +2330,36 @@ QUnit.module('Views', {
kanban.destroy();
});
- QUnit.skip('search panel is available on list and kanban by default', async function (assert) {
+ QUnit.test('search panel is available on list and kanban by default', async function (assert) {
assert.expect(8);
- var actionManager = await createActionManager({
- actions: this.actions,
- archs: this.archs,
- data: this.data,
- });
- await actionManager.doAction(1);
+ const webClient = await createWebClient({ testConfig });
- assert.containsOnce(actionManager, '.o_content.o_controller_with_searchpanel .o_kanban_view');
- assert.containsOnce(actionManager, '.o_content.o_controller_with_searchpanel .o_search_panel');
-
- await cpHelpers.switchView(actionManager, 'pivot');
- await testUtils.nextTick();
- assert.containsOnce(actionManager, '.o_content .o_pivot');
- assert.containsNone(actionManager, '.o_content .o_search_panel');
+ await doAction(webClient, 1);
- await cpHelpers.switchView(actionManager, 'list');
- assert.containsOnce(actionManager, '.o_content.o_controller_with_searchpanel .o_list_view');
- assert.containsOnce(actionManager, '.o_content.o_controller_with_searchpanel .o_search_panel');
+ assert.containsOnce(webClient, '.o_content.o_controller_with_searchpanel .o_kanban_view');
+ assert.containsOnce(webClient, '.o_content.o_controller_with_searchpanel .o_search_panel');
- await testUtils.dom.click(actionManager.$('.o_data_row .o_data_cell:first'));
- assert.containsOnce(actionManager, '.o_content .o_form_view');
- assert.containsNone(actionManager, '.o_content .o_search_panel');
-
- actionManager.destroy();
+ await cpHelpers.switchView(webClient, 'pivot');
+ await testUtils.nextTick();
+ assert.containsOnce(webClient, '.o_content .o_pivot');
+ assert.containsNone(webClient, '.o_content .o_search_panel');
+
+ await cpHelpers.switchView(webClient, 'list');
+ await legacyExtraNextTick();
+ assert.containsOnce(webClient, '.o_content.o_controller_with_searchpanel .o_list_view');
+ assert.containsOnce(webClient, '.o_content.o_controller_with_searchpanel .o_search_panel');
+
+ await testUtils.dom.click($(webClient.el).find('.o_data_row .o_data_cell:first'));
+ await legacyExtraNextTick();
+ assert.containsOnce(webClient, '.o_content .o_form_view');
+ assert.containsNone(webClient, '.o_content .o_search_panel');
});
- QUnit.skip('search panel with view_types attribute', async function (assert) {
+ QUnit.test('search panel with view_types attribute', async function (assert) {
assert.expect(6);
- this.archs['partner,false,search'] =
+ testConfig.serverData.views['partner,false,search'] =
`
@@ -2358,63 +2368,60 @@ QUnit.module('Views', {
`;
- var actionManager = await createActionManager({
- actions: this.actions,
- archs: this.archs,
- data: this.data,
- });
- await actionManager.doAction(1);
-
- assert.containsOnce(actionManager, '.o_content.o_controller_with_searchpanel .o_kanban_view');
- assert.containsOnce(actionManager, '.o_content.o_controller_with_searchpanel .o_search_panel');
+ const webClient = await createWebClient({ testConfig });
+ await doAction(webClient, 1);
- await cpHelpers.switchView(actionManager, 'list');
- assert.containsOnce(actionManager, '.o_content .o_list_view');
- assert.containsNone(actionManager, '.o_content .o_search_panel');
+ assert.containsOnce(webClient, '.o_content.o_controller_with_searchpanel .o_kanban_view');
+ assert.containsOnce(webClient, '.o_content.o_controller_with_searchpanel .o_search_panel');
- await cpHelpers.switchView(actionManager, 'pivot');
- assert.containsOnce(actionManager, '.o_content.o_controller_with_searchpanel .o_pivot');
- assert.containsOnce(actionManager, '.o_content.o_controller_with_searchpanel .o_search_panel');
+ await cpHelpers.switchView(webClient, 'list');
+ await legacyExtraNextTick();
+ assert.containsOnce(webClient, '.o_content .o_list_view');
+ assert.containsNone(webClient, '.o_content .o_search_panel');
- actionManager.destroy();
+ await cpHelpers.switchView(webClient, 'pivot');
+ await legacyExtraNextTick();
+ assert.containsOnce(webClient, '.o_content.o_controller_with_searchpanel .o_pivot');
+ assert.containsOnce(webClient, '.o_content.o_controller_with_searchpanel .o_search_panel');
});
- QUnit.skip('search panel state is shared between views', async function (assert) {
+ QUnit.test('search panel state is shared between views', async function (assert) {
assert.expect(16);
- var actionManager = await createActionManager({
- actions: this.actions,
- archs: this.archs,
- data: this.data,
- mockRPC: function (route, args) {
- if (route === '/web/dataset/search_read') {
- assert.step(JSON.stringify(args.domain));
- }
- return this._super.apply(this, arguments);
- },
- });
- await actionManager.doAction(1);
+ const mockRPC = (route, args) => {
+ if (route === '/web/dataset/search_read') {
+ assert.step(JSON.stringify(args.domain));
+ }
+ };
+
+ const webClient = await createWebClient({ testConfig , mockRPC });
- assert.hasClass(actionManager.$('.o_search_panel_category_value:first header'), 'active');
- assert.containsN(actionManager, '.o_kanban_record:not(.o_kanban_ghost)', 4);
+ await doAction(webClient, 1);
+
+ assert.hasClass($(webClient.el).find('.o_search_panel_category_value:first header'), 'active');
+ assert.containsN(webClient, '.o_kanban_record:not(.o_kanban_ghost)', 4);
// select 'asustek' company
- await testUtils.dom.click(actionManager.$('.o_search_panel_category_value:nth(1) header'));
- assert.hasClass(actionManager.$('.o_search_panel_category_value:nth(1) header'), 'active');
- assert.containsN(actionManager, '.o_kanban_record:not(.o_kanban_ghost)', 2);
+ await testUtils.dom.click($(webClient.el).find('.o_search_panel_category_value:nth(1) header'));
+ await legacyExtraNextTick();
+ assert.hasClass($(webClient.el).find('.o_search_panel_category_value:nth(1) header'), 'active');
+ assert.containsN(webClient, '.o_kanban_record:not(.o_kanban_ghost)', 2);
- await cpHelpers.switchView(actionManager, 'list');
- assert.hasClass(actionManager.$('.o_search_panel_category_value:nth(1) header'), 'active');
- assert.containsN(actionManager, '.o_data_row', 2);
+ await cpHelpers.switchView(webClient, 'list');
+ await legacyExtraNextTick();
+ assert.hasClass($(webClient.el).find('.o_search_panel_category_value:nth(1) header'), 'active');
+ assert.containsN(webClient, '.o_data_row', 2);
// select 'agrolait' company
- await testUtils.dom.click(actionManager.$('.o_search_panel_category_value:nth(2) header'));
- assert.hasClass(actionManager.$('.o_search_panel_category_value:nth(2) header'), 'active');
- assert.containsN(actionManager, '.o_data_row', 2);
+ await testUtils.dom.click($(webClient.el).find('.o_search_panel_category_value:nth(2) header'));
+ await legacyExtraNextTick();
+ assert.hasClass($(webClient.el).find('.o_search_panel_category_value:nth(2) header'), 'active');
+ assert.containsN(webClient, '.o_data_row', 2);
- await cpHelpers.switchView(actionManager, 'kanban');
- assert.hasClass(actionManager.$('.o_search_panel_category_value:nth(2) header'), 'active');
- assert.containsN(actionManager, '.o_kanban_record:not(.o_kanban_ghost)', 2);
+ await cpHelpers.switchView(webClient, 'kanban');
+ await legacyExtraNextTick();
+ assert.hasClass($(webClient.el).find('.o_search_panel_category_value:nth(2) header'), 'active');
+ assert.containsN(webClient, '.o_kanban_record:not(.o_kanban_ghost)', 2);
assert.verifySteps([
'[]', // initial search_read
@@ -2423,49 +2430,49 @@ QUnit.module('Views', {
'[["company_id","child_of",5]]', // list, after selecting the other company
'[["company_id","child_of",5]]', // kanban
]);
-
- actionManager.destroy();
});
- QUnit.skip('search panel filters are kept between switch views', async function (assert) {
+ QUnit.test('search panel filters are kept between switch views', async function (assert) {
assert.expect(17);
- const actionManager = await createActionManager({
- actions: this.actions,
- archs: this.archs,
- data: this.data,
- mockRPC: function (route, args) {
- if (route === '/web/dataset/search_read') {
- assert.step(JSON.stringify(args.domain));
- }
- return this._super.apply(this, arguments);
- },
- });
- await actionManager.doAction(1);
+ const mockRPC = (route, args) => {
+ if (route === '/web/dataset/search_read') {
+ assert.step(JSON.stringify(args.domain));
+ }
+ };
- assert.containsNone(actionManager, '.o_search_panel_filter_value input:checked');
- assert.containsN(actionManager, '.o_kanban_record:not(.o_kanban_ghost)', 4);
+ const webClient = await createWebClient({ testConfig , mockRPC });
+ await doAction(webClient, 1);
+
+ assert.containsNone(webClient, '.o_search_panel_filter_value input:checked');
+ assert.containsN(webClient, '.o_kanban_record:not(.o_kanban_ghost)', 4);
// select gold filter
- await testUtils.dom.click(actionManager.$('.o_search_panel_filter input[type="checkbox"]:nth(0)'));
- assert.containsOnce(actionManager, '.o_search_panel_filter_value input:checked');
- assert.containsN(actionManager, '.o_kanban_record:not(.o_kanban_ghost)', 1);
+ await testUtils.dom.click($(webClient.el).find('.o_search_panel_filter input[type="checkbox"]:nth(0)'));
+ await legacyExtraNextTick();
+ assert.containsOnce(webClient, '.o_search_panel_filter_value input:checked');
+ assert.containsN(webClient, '.o_kanban_record:not(.o_kanban_ghost)', 1);
- await cpHelpers.switchView(actionManager, 'list');
- assert.containsOnce(actionManager, '.o_search_panel_filter_value input:checked');
- assert.containsN(actionManager, '.o_data_row', 1);
+ await cpHelpers.switchView(webClient, 'list');
+ await legacyExtraNextTick();
+ assert.containsOnce(webClient, '.o_search_panel_filter_value input:checked');
+ assert.containsN(webClient, '.o_data_row', 1);
// select silver filter
- await testUtils.dom.click(actionManager.$('.o_search_panel_filter input[type="checkbox"]:nth(1)'));
- assert.containsN(actionManager, '.o_search_panel_filter_value input:checked', 2);
- assert.containsN(actionManager, '.o_data_row', 4);
+ await testUtils.dom.click($(webClient.el).find('.o_search_panel_filter input[type="checkbox"]:nth(1)'));
+ await legacyExtraNextTick();
+ assert.containsN(webClient, '.o_search_panel_filter_value input:checked', 2);
+ assert.containsN(webClient, '.o_data_row', 4);
- await cpHelpers.switchView(actionManager, 'kanban');
- assert.containsN(actionManager, '.o_search_panel_filter_value input:checked', 2);
- assert.containsN(actionManager, '.o_kanban_record:not(.o_kanban_ghost)', 4);
+ await cpHelpers.switchView(webClient, 'kanban');
+ await legacyExtraNextTick();
+ assert.containsN(webClient, '.o_search_panel_filter_value input:checked', 2);
+ assert.containsN(webClient, '.o_kanban_record:not(.o_kanban_ghost)', 4);
- await testUtils.dom.click(actionManager.$(".o_kanban_record:nth(0)"));
- await testUtils.dom.click(actionManager.$(".breadcrumb-item:nth(0)"));
+ await testUtils.dom.click($(webClient.el).find(".o_kanban_record:nth(0)"));
+ await legacyExtraNextTick();
+ await testUtils.dom.click($(webClient.el).find(".breadcrumb-item:nth(0)"));
+ await legacyExtraNextTick();
assert.verifySteps([
'[]', // initial search_read
@@ -2475,153 +2482,130 @@ QUnit.module('Views', {
'[["category_id","in",[6,7]]]', // kanban
'[["category_id","in",[6,7]]]', // kanban, after switching back from form view
]);
-
- actionManager.destroy();
});
- QUnit.skip('search panel filters are kept when switching to a view with no search panel', async function (assert) {
+ QUnit.test('search panel filters are kept when switching to a view with no search panel', async function (assert) {
assert.expect(13);
- var actionManager = await createActionManager({
- actions: this.actions,
- archs: this.archs,
- data: this.data,
- });
- await actionManager.doAction(1);
+ const webClient = await createWebClient({ testConfig });
+ await doAction(webClient, 1);
- assert.containsOnce(actionManager, '.o_content.o_controller_with_searchpanel .o_kanban_view');
- assert.containsOnce(actionManager, '.o_content.o_controller_with_searchpanel .o_search_panel');
- assert.containsNone(actionManager, '.o_search_panel_filter_value input:checked');
- assert.containsN(actionManager, '.o_kanban_record:not(.o_kanban_ghost)', 4);
+ assert.containsOnce(webClient, '.o_content.o_controller_with_searchpanel .o_kanban_view');
+ assert.containsOnce(webClient, '.o_content.o_controller_with_searchpanel .o_search_panel');
+ assert.containsNone(webClient, '.o_search_panel_filter_value input:checked');
+ assert.containsN(webClient, '.o_kanban_record:not(.o_kanban_ghost)', 4);
// select gold filter
- await testUtils.dom.click(actionManager.$('.o_search_panel_filter input[type="checkbox"]:nth(0)'));
- assert.containsOnce(actionManager, '.o_search_panel_filter_value input:checked');
- assert.containsN(actionManager, '.o_kanban_record:not(.o_kanban_ghost)', 1);
+ await testUtils.dom.click($(webClient.el).find('.o_search_panel_filter input[type="checkbox"]:nth(0)'));
+ await legacyExtraNextTick();
+ assert.containsOnce(webClient, '.o_search_panel_filter_value input:checked');
+ assert.containsN(webClient, '.o_kanban_record:not(.o_kanban_ghost)', 1);
// switch to pivot
- await cpHelpers.switchView(actionManager, 'pivot');
- assert.containsOnce(actionManager, '.o_content .o_pivot');
- assert.containsNone(actionManager, '.o_content .o_search_panel');
- assert.strictEqual(actionManager.$('.o_pivot_cell_value').text(), '15');
+ await cpHelpers.switchView(webClient, 'pivot');
+ await legacyExtraNextTick();
+ assert.containsOnce(webClient, '.o_content .o_pivot');
+ assert.containsNone(webClient, '.o_content .o_search_panel');
+ assert.strictEqual($(webClient.el).find('.o_pivot_cell_value').text(), '15');
// switch to list
- await cpHelpers.switchView(actionManager, 'list');
- assert.containsOnce(actionManager, '.o_content.o_controller_with_searchpanel .o_list_view');
- assert.containsOnce(actionManager, '.o_content.o_controller_with_searchpanel .o_search_panel');
- assert.containsOnce(actionManager, '.o_search_panel_filter_value input:checked');
- assert.containsN(actionManager, '.o_data_row', 1);
-
- actionManager.destroy();
+ await cpHelpers.switchView(webClient, 'list');
+ await legacyExtraNextTick();
+ assert.containsOnce(webClient, '.o_content.o_controller_with_searchpanel .o_list_view');
+ assert.containsOnce(webClient, '.o_content.o_controller_with_searchpanel .o_search_panel');
+ assert.containsOnce(webClient, '.o_search_panel_filter_value input:checked');
+ assert.containsN(webClient, '.o_data_row', 1);
});
- QUnit.skip('after onExecuteAction, selects "All" as default category value', async function (assert) {
+ QUnit.test('after onExecuteAction, selects "All" as default category value', async function (assert) {
assert.expect(4);
- var actionManager = await createActionManager({
- actions: this.actions,
- archs: this.archs,
- data: this.data,
- });
+ const webClient = await createWebClient({ testConfig });
+ await doAction(webClient, 2);
- await actionManager.doAction(2);
- await testUtils.dom.click(actionManager.$('.o_form_view button:contains("multi view")'));
+ await testUtils.dom.click($(webClient.el).find('.o_form_view button:contains("multi view")'));
+ await legacyExtraNextTick();
- assert.containsOnce(actionManager, '.o_kanban_view');
- assert.containsOnce(actionManager, '.o_search_panel');
- assert.containsOnce(actionManager, '.o_search_panel_category_value:first .active');
+ assert.containsOnce(webClient, '.o_kanban_view');
+ assert.containsOnce(webClient, '.o_search_panel');
+ assert.containsOnce(webClient, '.o_search_panel_category_value:first .active');
assert.verifySteps([]); // should not communicate with localStorage
-
- actionManager.destroy();
});
- QUnit.skip('search panel is not instantiated if stated in context', async function (assert) {
+ QUnit.test('search panel is not instantiated if stated in context', async function (assert) {
assert.expect(2);
- this.actions[0].context = {search_panel: false};
- var actionManager = await createActionManager({
- actions: this.actions,
- archs: this.archs,
- data: this.data,
- });
+ testConfig.serverData.actions[2].context = {search_panel: false};
+ const webClient = await createWebClient({ testConfig });
+ await doAction(webClient, 2);
- await actionManager.doAction(2);
- await testUtils.dom.click(actionManager.$('.o_form_view button:contains("multi view")'));
+ await testUtils.dom.click($(webClient.el).find('.o_form_view button:contains("multi view")'));
+ await legacyExtraNextTick();
- assert.containsOnce(actionManager, '.o_kanban_view');
- assert.containsNone(actionManager, '.o_search_panel');
-
- actionManager.destroy();
+ assert.containsOnce(webClient, '.o_kanban_view');
+ assert.containsNone(webClient, '.o_search_panel');
});
- QUnit.skip('categories and filters are not reloaded when switching between views', async function (assert) {
+ QUnit.test('categories and filters are not reloaded when switching between views', async function (assert) {
assert.expect(3);
- var actionManager = await createActionManager({
- actions: this.actions,
- archs: this.archs,
- data: this.data,
- mockRPC: function (route, args) {
- if (args.method && args.method.includes('search_panel_')) {
- assert.step(args.method);
- }
- return this._super.apply(this, arguments);
- },
- });
- await actionManager.doAction(1);
+ const mockRPC = (route, args) => {
+ if (args.method && args.method.includes('search_panel_')) {
+ assert.step(args.method);
+ }
+ };
+
+ const webClient = await createWebClient({ testConfig, mockRPC });
+ await doAction(webClient, 1);
- await cpHelpers.switchView(actionManager, 'list');
- await cpHelpers.switchView(actionManager, 'kanban');
+ await cpHelpers.switchView(webClient, 'list');
+ await legacyExtraNextTick();
+ await cpHelpers.switchView(webClient, 'kanban');
+ await legacyExtraNextTick();
assert.verifySteps([
'search_panel_select_range', // kanban: categories
'search_panel_select_multi_range', // kanban: filters
]);
-
- actionManager.destroy();
});
- QUnit.skip('scroll position is kept when switching between controllers', async function (assert) {
+ QUnit.test('scroll position is kept when switching between controllers', async function (assert) {
assert.expect(6);
const originalDebounce = SearchPanel.scrollDebounce;
SearchPanel.scrollDebounce = 0;
for (var i = 10; i < 20; i++) {
- this.data.category.records.push({id: i, name: "Cat " + i});
+ testConfig.serverData.models.category.records.push({id: i, name: "Cat " + i});
}
- var actionManager = await createActionManager({
- actions: this.actions,
- archs: this.archs,
- data: this.data,
- });
- actionManager.$el.css('max-height', 300);
+ const webClient = await createWebClient({ testConfig });
+ webClient.el.querySelector('.o_action_manager').style.maxHeight = "300px";
+
+ await doAction(webClient, 1);
async function scroll(top) {
- actionManager.el.querySelector(".o_search_panel").scrollTop = top;
+ webClient.el.querySelector(".o_search_panel").scrollTop = top;
await testUtils.nextTick();
}
- await actionManager.doAction(1);
-
- assert.containsOnce(actionManager, '.o_content .o_kanban_view');
- assert.strictEqual(actionManager.$('.o_search_panel').scrollTop(), 0);
+ assert.containsOnce(webClient, '.o_content .o_kanban_view');
+ assert.strictEqual($(webClient.el).find('.o_search_panel').scrollTop(), 0);
// simulate a scroll in the search panel and switch into list
await scroll(50);
- await cpHelpers.switchView(actionManager, 'list');
- assert.containsOnce(actionManager, '.o_content .o_list_view');
- assert.strictEqual(actionManager.$('.o_search_panel').scrollTop(), 50);
+ await cpHelpers.switchView(webClient, 'list');
+ await legacyExtraNextTick();
+ assert.containsOnce(webClient, '.o_content .o_list_view');
+ assert.strictEqual($(webClient.el).find('.o_search_panel').scrollTop(), 50);
// simulate another scroll and switch back to kanban
await scroll(30);
- await cpHelpers.switchView(actionManager, 'kanban');
- assert.containsOnce(actionManager, '.o_content .o_kanban_view');
- assert.strictEqual(actionManager.$('.o_search_panel').scrollTop(), 30);
-
- actionManager.destroy();
+ await cpHelpers.switchView(webClient, 'kanban');
+ await legacyExtraNextTick();
+ assert.containsOnce(webClient, '.o_content .o_kanban_view');
+ assert.strictEqual($(webClient.el).find('.o_search_panel').scrollTop(), 30);
SearchPanel.scrollDebounce = originalDebounce;
});
diff --git a/addons/web/static/tests/legacy/widgets/domain_selector_tests.js b/addons/web/static/tests/legacy/widgets/domain_selector_tests.js
index 9f4fc24245864..9e49c8d644c26 100644
--- a/addons/web/static/tests/legacy/widgets/domain_selector_tests.js
+++ b/addons/web/static/tests/legacy/widgets/domain_selector_tests.js
@@ -3,6 +3,7 @@ odoo.define('web.domain_selector_tests', function (require) {
var DomainSelector = require("web.DomainSelector");
var testUtils = require("web.test_utils");
+const { createWebClient, doAction, getActionManagerTestConfig } = require('@web/../tests/webclient/actions/helpers');
QUnit.module('widgets', {}, function () {
@@ -245,33 +246,31 @@ QUnit.module('DomainSelector', {
domainSelector.destroy();
});
- QUnit.skip("inline domain editor in modal", async function (assert) {
+ QUnit.test("inline domain editor in modal", async function (assert) {
assert.expect(1);
- const actions = [
- {
- id: 5,
- name: "Partner Form",
- res_model: "partner",
- target: "new",
- type: "ir.actions.act_window",
- views: [["view_ref", "form"]],
- },
- ];
- const actionManager = await testUtils.createActionManager({
- actions,
- archs: {
- "partner,view_ref,form": `
-
- `,
- },
- data: this.data,
- });
- await actionManager.doAction(5);
+ const testConfig = getActionManagerTestConfig();
+
+ testConfig.serverData.actions[5] = {
+ id: 5,
+ name: "Partner Form",
+ res_model: "partner",
+ target: "new",
+ type: "ir.actions.act_window",
+ views: [["view_ref", "form"]],
+ };
+
+ testConfig.serverData.views = {
+ "partner,view_ref,form": `
+
+ `,
+ };
+
+ const webClient = await createWebClient({testConfig});
+ await doAction(webClient, 5);
assert.strictEqual(document.querySelector('div[name="foo"]').closest('.modal-body').style.overflow,
'visible', "modal should have visible overflow if there is inline domain field widget");
- actionManager.destroy();
});
});
});
diff --git a/addons/web/static/tests/legacy/widgets/week_days_tests.js b/addons/web/static/tests/legacy/widgets/week_days_tests.js
index fdda354a94900..80430c4e05108 100644
--- a/addons/web/static/tests/legacy/widgets/week_days_tests.js
+++ b/addons/web/static/tests/legacy/widgets/week_days_tests.js
@@ -136,14 +136,8 @@ odoo.define('web.week_days_tests', function (require) {
`,
- env: {
- _t: {
- database: {
- parameters: Object.assign(_t.database.parameters,{
- week_start: 5,
- }),
- }
- }
+ translateParameters: {
+ week_start: 5,
},
});
diff --git a/addons/web/static/tests/setup.js b/addons/web/static/tests/setup.js
index 3a6863c12df99..c8eb1f3485efc 100644
--- a/addons/web/static/tests/setup.js
+++ b/addons/web/static/tests/setup.js
@@ -1,6 +1,7 @@
/** @odoo-module **/
import core from "web.core";
+import session from "web.session";
import { browser } from "@web/core/browser/browser";
import { patchWithCleanup } from "@web/../tests/helpers/utils";
import { legacyProm } from "web.test_legacy";
@@ -53,6 +54,13 @@ function patchLegacyCoreBus() {
});
}
+function patchLegacySession() {
+ const userContext = Object.getOwnPropertyDescriptor(session, "user_context");
+ registerCleanup(() => {
+ Object.defineProperty(session, "user_context", userContext);
+ });
+}
+
export async function setupTests() {
QUnit.testStart(() => {
setTestOdooWithCleanup();
@@ -60,6 +68,7 @@ export async function setupTests() {
forceLocaleAndTimezoneWithCleanup();
patchBrowserWithCleanup();
patchLegacyCoreBus();
+ patchLegacySession();
});
const templatesUrl = `/web/webclient/qweb/${new Date().getTime()}?bundle=web.assets_qweb`;
diff --git a/addons/web/static/tests/webclient/actions/helpers.js b/addons/web/static/tests/webclient/actions/helpers.js
index 6d8b1e3ffc8f9..6ea6f6cccdb50 100644
--- a/addons/web/static/tests/webclient/actions/helpers.js
+++ b/addons/web/static/tests/webclient/actions/helpers.js
@@ -11,6 +11,7 @@ import {
makeLegacyActionManagerService,
makeLegacyNotificationService,
mapLegacyEnvToWowlEnv,
+ makeLegacySessionService,
} from "@web/legacy/utils";
import { viewService } from "@web/views/view_service";
import { actionService } from "@web/webclient/actions/action_service";
@@ -41,6 +42,9 @@ import {
} from "../../helpers/mock_services";
import { getFixture, legacyExtraNextTick, nextTick, patchWithCleanup } from "../../helpers/utils";
import session from "web.session";
+import { ComponentAdapter } from "web.OwlCompatibility";
+import LegacyMockServer from "web.MockServer";
+import Widget from "web.Widget";
const { Component, mount, tags } = owl;
@@ -78,9 +82,17 @@ export async function createWebClient(params) {
controllers.push(this);
},
});
- if (params.legacyParams && params.legacyParams.getTZOffset) {
- patchWithCleanup(session, {
- getTZOffset: params.legacyParams.getTZOffset,
+
+ const legacyParams = params.legacyParams;
+ const models = params.testConfig.serverData.models;
+ if (legacyParams && legacyParams.withLegacyMockServer && models) {
+ legacyParams.models = Object.assign({}, models);
+ // In lagacy, data may not be sole models, but can contain some other variables
+ // So we filter them out for our WOWL mockServer
+ Object.entries(legacyParams.models).forEach(([k, v]) => {
+ if (!(v instanceof Object) || !("fields" in v)) {
+ delete models[k];
+ }
});
}
@@ -89,7 +101,7 @@ export async function createWebClient(params) {
...params.testConfig,
mockRPC,
});
- addLegacyMockEnvironment(env, params.testConfig, params.legacyParams);
+ addLegacyMockEnvironment(env, params.testConfig, legacyParams);
const WebClientClass = params.WebClientClass || WebClient;
const target = params && params.target ? params.target : getFixture();
@@ -157,7 +169,15 @@ function addLegacyMockEnvironment(env, testConfig, legacyParams = {}) {
ActionMenus.registry = new Registry();
registerCleanup(() => (ActionMenus.registry = actionMenusRegistry));
- const legacyEnv = makeTestEnvironment({ dataManager, bus: core.bus });
+ let localSession;
+ if (legacyParams && legacyParams.getTZOffset) {
+ patchWithCleanup(session, {
+ getTZOffset: legacyParams.getTZOffset,
+ });
+ localSession = { getTZOffset: legacyParams.getTZOffset };
+ }
+
+ const legacyEnv = makeTestEnvironment({ dataManager, bus: core.bus, session: localSession });
if (legacyParams.serviceRegistry) {
const legacyServiceMap = core.serviceRegistry.map;
@@ -173,6 +193,7 @@ function addLegacyMockEnvironment(env, testConfig, legacyParams = {}) {
Component.env = legacyEnv;
mapLegacyEnvToWowlEnv(legacyEnv, env);
+ serviceRegistry.add("legacy_session", makeLegacySessionService(legacyEnv, session));
// deploy the legacyActionManagerService (in Wowl env)
const legacyActionManagerService = makeLegacyActionManagerService(legacyEnv);
serviceRegistry.add("legacy_action_manager", legacyActionManagerService);
@@ -183,6 +204,26 @@ function addLegacyMockEnvironment(env, testConfig, legacyParams = {}) {
const initialDebouncedVal = debouncedField.prototype.DEBOUNCE;
debouncedField.prototype.DEBOUNCE = 0;
registerCleanup(() => (debouncedField.prototype.DEBOUNCE = initialDebouncedVal));
+
+ if (legacyParams.withLegacyMockServer) {
+ const adapter = new ComponentAdapter(null, { Component: owl.Component });
+ adapter.env = legacyEnv;
+ const W = Widget.extend({ do_push_state() {} });
+ const widget = new W(adapter);
+ const legacyMockServer = new LegacyMockServer(legacyParams.models, { widget });
+ const originalRPC = env.services.rpc;
+ env.services.rpc = async (...args) => {
+ try {
+ return await originalRPC(...args);
+ } catch (e) {
+ if (e.message.includes("Unimplemented")) {
+ return legacyMockServer._performRpc(...args);
+ } else {
+ throw e;
+ }
+ }
+ };
+ }
}
export async function doAction(env, ...args) {
diff --git a/addons/web/static/tests/webclient/actions/legacy_tests.js b/addons/web/static/tests/webclient/actions/legacy_tests.js
index dcaeb184dfd94..9095994922db0 100644
--- a/addons/web/static/tests/webclient/actions/legacy_tests.js
+++ b/addons/web/static/tests/webclient/actions/legacy_tests.js
@@ -13,6 +13,7 @@ import { ClientActionAdapter } from "@web/legacy/action_adapters";
import { useDebugManager } from "@web/core/debug/debug_menu";
import { debugService } from "@web/core/debug/debug_service";
+import ControlPanel from "web.ControlPanel";
import core from "web.core";
import AbstractAction from "web.AbstractAction";
@@ -136,4 +137,53 @@ QUnit.module("ActionManager", (hooks) => {
assert.verifySteps(["debugItems executed"]);
delete core.action_registry.map.customLegacy;
});
+
+ QUnit.test("willUnmount is called down the legacy layers", async (assert) => {
+ assert.expect(7);
+
+ let mountCount = 0;
+ patchWithCleanup(ControlPanel.prototype, {
+ mounted() {
+ mountCount = mountCount + 1;
+ this.__uniqueId = mountCount;
+ assert.step(`mounted ${this.__uniqueId}`);
+ this._super(...arguments);
+ },
+ willUnmount() {
+ assert.step(`willUnmount ${this.__uniqueId}`);
+ this._super(...arguments);
+ },
+ });
+
+ const LegacyAction = AbstractAction.extend({
+ hasControlPanel: true,
+ start() {
+ const ret = this._super(...arguments);
+ const el = document.createElement("div");
+ el.classList.add("custom-action");
+ this.el.append(el);
+ return ret;
+ },
+ });
+ core.action_registry.add("customLegacy", LegacyAction);
+
+ const webClient = await createWebClient({ testConfig });
+ await doAction(webClient, 1);
+ await doAction(webClient, "customLegacy");
+ await click(webClient.el.querySelectorAll(".breadcrumb-item")[0]);
+ await legacyExtraNextTick();
+
+ webClient.destroy();
+
+ assert.verifySteps([
+ "mounted 1",
+ "willUnmount 1",
+ "mounted 2",
+ "willUnmount 2",
+ "mounted 3",
+ "willUnmount 3",
+ ]);
+
+ delete core.action_registry.map.customLegacy;
+ });
});
diff --git a/addons/web/static/tests/webclient/actions/report_action_tests.js b/addons/web/static/tests/webclient/actions/report_action_tests.js
index d4b7400cd0a47..9e624e9931bdc 100644
--- a/addons/web/static/tests/webclient/actions/report_action_tests.js
+++ b/addons/web/static/tests/webclient/actions/report_action_tests.js
@@ -1,24 +1,19 @@
/** @odoo-module **/
import { registry } from "@web/core/registry";
-import { download } from "@web/core/network/download";
import { uiService } from "@web/core/ui_service";
import testUtils from "web.test_utils";
import ReportClientAction from "report.client_action";
import { clearRegistryWithCleanup } from "../../helpers/mock_env";
import { makeFakeNotificationService, makeFakeUserService } from "../../helpers/mock_services";
-import { patchWithCleanup } from "../../helpers/utils";
import { createWebClient, doAction, getActionManagerTestConfig } from "./helpers";
+import { mockDownload } from "@web/../tests/helpers/utils";
let testConfig;
const mainComponentRegistry = registry.category("main_components");
const serviceRegistry = registry.category("services");
-function mockDownload(cb) {
- patchWithCleanup(download, { _download: cb });
-}
-
QUnit.module("ActionManager", (hooks) => {
hooks.beforeEach(() => {
testConfig = getActionManagerTestConfig();
diff --git a/addons/web/static/tests/webclient/actions/target_tests.js b/addons/web/static/tests/webclient/actions/target_tests.js
index 0f54d7d480d42..c94456eae496d 100644
--- a/addons/web/static/tests/webclient/actions/target_tests.js
+++ b/addons/web/static/tests/webclient/actions/target_tests.js
@@ -294,8 +294,6 @@ QUnit.module("ActionManager", (hooks) => {
await testUtils.dom.click($(".modal:last .modal-footer .btn-primary"));
assert.containsOnce(document.body, ".modal");
assert.strictEqual($(".modal:last .modal-body").text().trim(), "Another action");
-
- webClient.destroy();
}
);
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 63a506f83f16c..dbdf3aa2bad99 100644
--- a/addons/web/static/tests/webclient/actions/window_action_tests.js
+++ b/addons/web/static/tests/webclient/actions/window_action_tests.js
@@ -2168,8 +2168,6 @@ QUnit.module("ActionManager", (hooks) => {
".modal.o_technical_modal",
"Warning modal should be closed"
);
-
- webClient.destroy();
}
);
@@ -2190,7 +2188,6 @@ QUnit.module("ActionManager", (hooks) => {
await legacyExtraNextTick();
assert.containsOnce(webClient, ".o_dialog");
assert.containsOnce(webClient, ".o_dialog .o_act_window .o_view_controller");
- webClient.destroy();
}
);
@@ -2224,7 +2221,6 @@ QUnit.module("ActionManager", (hooks) => {
await click(webClient.el.querySelector(".o_form_buttons_edit .o_form_button_save"));
await legacyExtraNextTick();
assert.isVisible(webClient.el.querySelector(".o_form_buttons_view .o_form_button_edit"));
- webClient.destroy();
});
QUnit.test("debugManager is active for (legacy) views", async function (assert) {
@@ -2248,7 +2244,6 @@ QUnit.module("ActionManager", (hooks) => {
webClient.el,
".o_debug_manager .o_dropdown_item:contains('Edit View: Kanban')"
);
- webClient.destroy();
});
QUnit.test("reload a view via the view switcher keep state", async function (assert) {
diff --git a/odoo/addons/base/static/tests/base_settings_tests.js b/odoo/addons/base/static/tests/base_settings_tests.js
index 61b5f821fb3fc..a08c27d977570 100644
--- a/odoo/addons/base/static/tests/base_settings_tests.js
+++ b/odoo/addons/base/static/tests/base_settings_tests.js
@@ -6,9 +6,15 @@ var view_registry = require('web.view_registry');
var createView = testUtils.createView;
var BaseSettingsView = view_registry.get('base_settings');
-var createActionManager = testUtils.createActionManager;
+const { legacyExtraNextTick } = require("@web/../tests/helpers/utils");
+const {
+ createWebClient,
+ doAction,
+ getActionManagerTestConfig,
+} = require("@web/../tests/webclient/actions/helpers");
+let testConfig;
QUnit.module('base_settings_tests', {
beforeEach: function () {
this.data = {
@@ -23,6 +29,9 @@ QUnit.module('base_settings_tests', {
fields: {}
}
};
+ testConfig = getActionManagerTestConfig();
+ const models = Object.assign(testConfig.serverData.models, this.data);
+ Object.assign(testConfig.serverData, { models });
}
}, function () {
@@ -91,160 +100,189 @@ QUnit.module('base_settings_tests', {
form.destroy();
});
- QUnit.skip('settings views does not read existing id when coming back in breadcrumbs', async function (assert) {
- assert.expect(8);
-
- var actions = [{
- id: 1,
- name: 'Settings view',
- res_model: 'res.config.settings',
- type: 'ir.actions.act_window',
- views: [[1, 'form']],
- }, {
- id: 4,
- name: 'Other action',
- res_model: 'task',
- type: 'ir.actions.act_window',
- views: [[2, 'list']],
- }];
- var archs = {
- 'res.config.settings,1,form': '',
- 'task,2,list': '',
- 'res.config.settings,false,search': '',
- 'task,false,search': '',
- };
+ QUnit.test(
+ "settings views does not read existing id when coming back in breadcrumbs",
+ async function (assert) {
+ assert.expect(8);
+
+ testConfig.serverData.actions = {
+ 1: {
+ id: 1,
+ name: "Settings view",
+ res_model: "res.config.settings",
+ type: "ir.actions.act_window",
+ views: [[1, "form"]],
+ },
+ 4: {
+ id: 4,
+ name: "Other action",
+ res_model: "task",
+ type: "ir.actions.act_window",
+ views: [[2, "list"]],
+ },
+ };
- var actionManager = await createActionManager({
- actions: actions,
- archs: archs,
- data: this.data,
- mockRPC: function (route, args) {
+ testConfig.serverData.views = {
+ "res.config.settings,1,form":
+ ``,
+ "task,2,list": '',
+ "res.config.settings,false,search": "",
+ "task,false,search": "",
+ };
+
+ const mockRPC = (route, args) => {
if (args.method) {
assert.step(args.method);
}
- return this._super.apply(this, arguments);
- },
- });
-
- await actionManager.doAction(1);
- await testUtils.nextTick();
- await testUtils.dom.click(actionManager.$('button[name="4"]'));
- await testUtils.dom.click($('.o_control_panel .breadcrumb-item a'));
- assert.hasClass(actionManager.$('.o_form_view'), 'o_form_editable');
- assert.verifySteps([
- 'load_views', // initial setting action
- 'onchange', // this is a setting view => create new record
- 'create', // when we click on action button => save
- 'read', // with save, we have a reload... (not necessary actually)
- 'load_views', // for other action in breadcrumb,
- // with a searchread (not shown here since it is a route)
- 'onchange', // when we come back, we want to restart from scratch
- ]);
-
- actionManager.destroy();
- });
-
- QUnit.skip('clicking on any button in setting should show discard warning if setting form is dirty', async function (assert) {
- assert.expect(11);
-
- var actions = [{
- id: 1,
- name: 'Settings view',
- res_model: 'res.config.settings',
- type: 'ir.actions.act_window',
- views: [[1, 'form']],
- }, {
- id: 4,
- name: 'Other action',
- res_model: 'task',
- type: 'ir.actions.act_window',
- views: [[2, 'list']],
- }];
- var archs = {
- 'res.config.settings,1,form': '',
- 'task,2,list': '',
- 'res.config.settings,false,search': '',
- 'task,false,search': '',
- };
-
- var actionManager = await createActionManager({
- actions: actions,
- archs: archs,
- data: this.data,
- mockRPC: function (route, args) {
- if (route === '/web/dataset/call_button') {
+ };
+
+ const webClient = await createWebClient({ testConfig, mockRPC });
+
+ await doAction(webClient, 1);
+ await testUtils.dom.click($(webClient.el).find('button[name="4"]'));
+ await legacyExtraNextTick();
+ await testUtils.dom.click($(".o_control_panel .breadcrumb-item a"));
+ await legacyExtraNextTick();
+ assert.hasClass($(webClient.el).find(".o_form_view"), "o_form_editable");
+ assert.verifySteps([
+ "load_views", // initial setting action
+ "onchange", // this is a setting view => create new record
+ "create", // when we click on action button => save
+ "read", // with save, we have a reload... (not necessary actually)
+ "load_views", // for other action in breadcrumb,
+ // with a searchread (not shown here since it is a route)
+ "onchange", // when we come back, we want to restart from scratch
+ ]);
+ }
+ );
+
+ QUnit.test(
+ "clicking on any button in setting should show discard warning if setting form is dirty",
+ async function (assert) {
+ assert.expect(11);
+
+ testConfig.serverData.actions = {
+ 1: {
+ id: 1,
+ name: "Settings view",
+ res_model: "res.config.settings",
+ type: "ir.actions.act_window",
+ views: [[1, "form"]],
+ },
+ 4: {
+ id: 4,
+ name: "Other action",
+ res_model: "task",
+ type: "ir.actions.act_window",
+ views: [[2, "list"]],
+ },
+ };
+
+ testConfig.serverData.views = {
+ "res.config.settings,1,form":
+ ``,
+ "task,2,list": '',
+ "res.config.settings,false,search": "",
+ "task,false,search": "",
+ };
+
+ const mockRPC = (route, args) => {
+ if (route === "/web/dataset/call_button") {
if (args.method === "execute") {
assert.ok("execute method called");
- return Promise.resolve(true);
+ return true;
}
if (args.method === "cancel") {
assert.ok("cancel method called");
- return Promise.resolve(true);
+ return true;
}
}
- return this._super.apply(this, arguments);
- },
- });
-
- await actionManager.doAction(1);
- assert.containsNone(actionManager, '.o_field_boolean input:checked',
- "checkbox should not be checked");
-
- await testUtils.dom.click(actionManager.$("input[type='checkbox']"));
- assert.containsOnce(actionManager, '.o_field_boolean input:checked',
- "checkbox should be checked");
-
- await testUtils.dom.click(actionManager.$('button[name="4"]'));
- assert.containsOnce(document.body, '.modal', "should open a warning dialog");
-
- await testUtils.dom.click($('.modal button:contains(Discard)'));
- assert.containsOnce(actionManager, '.o_list_view', "should be open list view");
-
- await testUtils.dom.click($('.o_control_panel .breadcrumb-item a'));
- assert.containsNone(actionManager, '.o_field_boolean input:checked',
- "checkbox should not be checked");
-
- await testUtils.dom.click(actionManager.$("input[type='checkbox']"));
- await testUtils.dom.click(actionManager.$('button[name="4"]'));
- assert.containsOnce(document.body, '.modal', "should open a warning dialog");
-
- await testUtils.dom.click($('.modal button:contains(Stay Here)'));
- assert.containsOnce(actionManager, '.o_form_view' ,"should be remain on form view");
-
- await testUtils.dom.click(actionManager.$("button[name='execute']"));
- assert.containsNone(document.body, '.modal', "should not open a warning dialog");
-
- await testUtils.dom.click(actionManager.$("input[type='checkbox']"));
- await testUtils.dom.click(actionManager.$("button[name='cancel']"));
- assert.containsNone(document.body, '.modal', "should not open a warning dialog");
-
- actionManager.destroy();
- });
+ };
+
+ const webClient = await createWebClient({ testConfig, mockRPC });
+
+ await doAction(webClient, 1);
+ assert.containsNone(
+ webClient,
+ ".o_field_boolean input:checked",
+ "checkbox should not be checked"
+ );
+
+ await testUtils.dom.click($(webClient.el).find("input[type='checkbox']"));
+ assert.containsOnce(
+ webClient,
+ ".o_field_boolean input:checked",
+ "checkbox should be checked"
+ );
+
+ await testUtils.dom.click($(webClient.el).find('button[name="4"]'));
+ await legacyExtraNextTick();
+ assert.containsOnce(document.body, ".modal", "should open a warning dialog");
+
+ await testUtils.dom.click($(".modal button:contains(Discard)"));
+ await legacyExtraNextTick();
+ assert.containsOnce(webClient, ".o_list_view", "should be open list view");
+
+ await testUtils.dom.click($(".o_control_panel .breadcrumb-item a"));
+ await legacyExtraNextTick();
+ assert.containsNone(
+ webClient,
+ ".o_field_boolean input:checked",
+ "checkbox should not be checked"
+ );
+
+ await testUtils.dom.click($(webClient.el).find("input[type='checkbox']"));
+ await testUtils.dom.click($(webClient.el).find('button[name="4"]'));
+ await legacyExtraNextTick();
+ assert.containsOnce(document.body, ".modal", "should open a warning dialog");
+
+ await testUtils.dom.click($(".modal button:contains(Stay Here)"));
+ await legacyExtraNextTick();
+ assert.containsOnce(webClient, ".o_form_view", "should be remain on form view");
+
+ await testUtils.dom.click($(webClient.el).find("button[name='execute']"));
+ await legacyExtraNextTick();
+ assert.containsNone(
+ document.body,
+ ".modal",
+ "should not open a warning dialog"
+ );
+
+ await testUtils.dom.click($(webClient.el).find("input[type='checkbox']"));
+ await testUtils.dom.click($(webClient.el).find("button[name='cancel']"));
+ await legacyExtraNextTick();
+ assert.containsNone(
+ document.body,
+ ".modal",
+ "should not open a warning dialog"
+ );
+ }
+ );
QUnit.test('settings view does not display other settings after reload', async function (assert) {
assert.expect(2);
@@ -365,72 +403,83 @@ QUnit.module('base_settings_tests', {
form.destroy();
});
- QUnit.skip('execute action from settings view with several actions in the breadcrumb', async function (assert) {
- // This commit fixes a race condition, that's why we artificially slow down a read rpc
- assert.expect(4);
-
- const actions = [{
- id: 1,
- name: 'First action',
- res_model: 'task',
- type: 'ir.actions.act_window',
- views: [[1, 'list']],
- }, {
- id: 2,
- name: 'Settings view',
- res_model: 'res.config.settings',
- type: 'ir.actions.act_window',
- views: [[2, 'form']],
- }, {
- id: 3,
- name: 'Other action',
- res_model: 'task',
- type: 'ir.actions.act_window',
- views: [[3, 'list']],
- }];
- const archs = {
- 'task,1,list': '',
- 'res.config.settings,2,form': `
- `,
- 'task,3,list': '',
- 'res.config.settings,false,search': '',
- 'task,false,search': '',
- };
-
- let loadViewsDef;
- const actionManager = await createActionManager({
- actions: actions,
- archs: archs,
- data: this.data,
- async mockRPC(route, args) {
- const _super = this._super.bind(this);
- if (args.method === 'read') {
- await Promise.resolve(loadViewsDef); // slow down reload of settings view
+ QUnit.test(
+ "execute action from settings view with several actions in the breadcrumb",
+ async function (assert) {
+ // This commit fixes a race condition, that's why we artificially slow down a read rpc
+ assert.expect(4);
+
+ testConfig.serverData.actions = {
+ 1: {
+ id: 1,
+ name: "First action",
+ res_model: "task",
+ type: "ir.actions.act_window",
+ views: [[1, "list"]],
+ },
+ 2: {
+ id: 2,
+ name: "Settings view",
+ res_model: "res.config.settings",
+ type: "ir.actions.act_window",
+ views: [[2, "form"]],
+ },
+ 3: {
+ id: 3,
+ name: "Other action",
+ res_model: "task",
+ type: "ir.actions.act_window",
+ views: [[3, "list"]],
+ },
+ };
+
+ testConfig.serverData.views = {
+ "task,1,list": '',
+ "res.config.settings,2,form": `
+ `,
+ "task,3,list": '',
+ "res.config.settings,false,search": "",
+ "task,false,search": "",
+ };
+
+ let loadViewsDef;
+ const mockRPC = async (route, args) => {
+ if (args.method === "read") {
+ await loadViewsDef; // slow down reload of settings view
}
- return _super(route, args);
- },
- });
-
- await actionManager.doAction(1);
- assert.strictEqual(actionManager.$('.breadcrumb').text(), 'First action');
-
- await actionManager.doAction(2);
- assert.strictEqual(actionManager.$('.breadcrumb').text(), 'First actionNew');
-
- loadViewsDef = testUtils.makeTestPromise();
- await testUtils.dom.click(actionManager.$('button[name="3"]'));
- assert.strictEqual(actionManager.$('.breadcrumb').text(), 'First actionNew');
-
- loadViewsDef.resolve();
- await testUtils.nextTick();
- assert.strictEqual(actionManager.$('.breadcrumb').text(), 'First actionNewOther action');
-
- actionManager.destroy();
- });
+ };
+
+ const webClient = await createWebClient({ testConfig, mockRPC });
+ await doAction(webClient, 1);
+ assert.strictEqual($(webClient.el).find(".breadcrumb").text(), "First action");
+
+ await doAction(webClient, 2);
+ assert.strictEqual(
+ $(webClient.el).find(".breadcrumb").text(),
+ "First actionNew"
+ );
+
+ loadViewsDef = testUtils.makeTestPromise();
+ await testUtils.dom.click($(webClient.el).find('button[name="3"]'));
+ await legacyExtraNextTick();
+ assert.strictEqual(
+ $(webClient.el).find(".breadcrumb").text(),
+ "First actionNew"
+ );
+
+ loadViewsDef.resolve();
+ await testUtils.nextTick();
+ await legacyExtraNextTick();
+ assert.strictEqual(
+ $(webClient.el).find(".breadcrumb").text(),
+ "First actionNewOther action"
+ );
+ }
+ );
QUnit.test('settings can contain one2many fields', async function (assert) {
assert.expect(2);
@@ -477,75 +526,79 @@ QUnit.module('base_settings_tests', {
form.destroy();
});
- QUnit.skip('call "call_button/execute" when clicking on a button in dirty settings', async function (assert) {
- assert.expect(7);
-
- const actions = [{
- id: 1,
- name: 'Settings view',
- res_model: 'res.config.settings',
- type: 'ir.actions.act_window',
- views: [[1, 'form']],
- }];
- const archs = {
- 'res.config.settings,1,form': `
-