*crm, project With owl2, the `el` of components is no longer available. It still works in Odoo on LegacyComponent, which has been introduced to ease the switch from owl1 to owl2, and we're now incrementally removing it. With this commit, the action scrolling helpers no longer rely on component.el, meaning that views using them (through the hook `useSetupAction`) no longer need to extend LegacyComponent. More specifically, we move the action scrolling helpers from core/ to webclient/actions, as those helpers make no sense outside the context of actions (and thus are unnecessary in the frontend). Tests have been adapted as well. closes odoo/odoo#85631 Related: odoo/enterprise#24902 Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
307 lines
11 KiB
JavaScript
307 lines
11 KiB
JavaScript
/** @odoo-module **/
|
|
|
|
import { getFixture, legacyExtraNextTick, patchWithCleanup } from "@web/../tests/helpers/utils";
|
|
import {
|
|
setupControlPanelServiceRegistry,
|
|
switchView,
|
|
toggleFilterMenu,
|
|
toggleGroupByMenu,
|
|
toggleMenuItem,
|
|
toggleMenuItemOption,
|
|
} from "@web/../tests/search/helpers";
|
|
import { makeView } from "@web/../tests/views/helpers";
|
|
import { createWebClient, doAction } from "@web/../tests/webclient/helpers";
|
|
import { dialogService } from "@web/core/dialog/dialog_service";
|
|
import { _lt } from "@web/core/l10n/translation";
|
|
import { registry } from "@web/core/registry";
|
|
import AbstractModel from "web.AbstractModel";
|
|
import AbstractView from "web.AbstractView";
|
|
import { controlPanel as cpHelpers, mock } from "web.test_utils";
|
|
import legacyViewRegistry from "web.view_registry";
|
|
import { browser } from "@web/core/browser/browser";
|
|
|
|
const patchDate = mock.patchDate;
|
|
|
|
const serviceRegistry = registry.category("services");
|
|
|
|
const forecastDomain = (forecastStart) => {
|
|
return ["|", ["date_field", "=", false], ["date_field", ">=", forecastStart]];
|
|
};
|
|
|
|
let serverData;
|
|
let target;
|
|
QUnit.module("Views", (hooks) => {
|
|
hooks.beforeEach(async () => {
|
|
serverData = {
|
|
models: {
|
|
foo: {
|
|
fields: {
|
|
date_field: {
|
|
string: "Date Field",
|
|
type: "date",
|
|
store: true,
|
|
sortable: true,
|
|
},
|
|
bar: {
|
|
string: "Bar",
|
|
type: "many2one",
|
|
relation: "partner",
|
|
store: true,
|
|
sortable: true,
|
|
},
|
|
},
|
|
records: [],
|
|
},
|
|
partner: {},
|
|
},
|
|
views: {
|
|
"foo,false,legacy_toy": `<legacy_toy/>`,
|
|
"foo,false,graph": `<graph js_class="forecast_graph"/>`,
|
|
"foo,false,search": `
|
|
<search>
|
|
<filter name="forecast_filter" string="Forecast Filter" context="{ 'forecast_filter': 1 }"/>
|
|
<filter name="group_by_bar" string="Bar" context="{ 'group_by': 'bar' }"/>
|
|
<filter name="group_by_date_field" string="Date Field" context="{ 'group_by': 'date_field' }"/>
|
|
</search>
|
|
`,
|
|
},
|
|
};
|
|
setupControlPanelServiceRegistry();
|
|
serviceRegistry.add("dialog", dialogService);
|
|
|
|
target = getFixture();
|
|
});
|
|
|
|
QUnit.module("Forecast views");
|
|
|
|
QUnit.test("Forecast graph view", async function (assert) {
|
|
assert.expect(5);
|
|
|
|
patchWithCleanup(browser, { setTimeout: (fn) => fn() });
|
|
const unpatchDate = patchDate(2021, 8, 16, 16, 54, 0);
|
|
|
|
const expectedDomains = [
|
|
forecastDomain("2021-09-01"), // month granularity due to no groupby
|
|
forecastDomain("2021-09-16"), // day granularity due to simple bar groupby
|
|
// quarter granularity due to date field groupby activated with quarter interval option
|
|
forecastDomain("2021-07-01"),
|
|
// quarter granularity due to date field groupby activated with quarter and year interval option
|
|
forecastDomain("2021-01-01"),
|
|
// forecast filter no more active
|
|
[],
|
|
];
|
|
|
|
await makeView({
|
|
resModel: "foo",
|
|
type: "graph",
|
|
serverData,
|
|
searchViewId: false,
|
|
context: {
|
|
search_default_forecast_filter: 1,
|
|
forecast_field: "date_field",
|
|
},
|
|
mockRPC(_, args) {
|
|
if (args.method === "web_read_group") {
|
|
const { domain } = args.kwargs;
|
|
assert.deepEqual(domain, expectedDomains.shift());
|
|
}
|
|
},
|
|
});
|
|
|
|
await toggleGroupByMenu(target);
|
|
await toggleMenuItem(target, "Bar");
|
|
|
|
await toggleMenuItem(target, "Date Field");
|
|
await toggleMenuItemOption(target, "Date Field", "Quarter");
|
|
|
|
await toggleMenuItemOption(target, "Date Field", "Year");
|
|
|
|
await toggleFilterMenu(target);
|
|
await toggleMenuItem(target, "Forecast Filter");
|
|
|
|
unpatchDate();
|
|
});
|
|
|
|
QUnit.test(
|
|
"forecast filter domain is combined with other domains with an AND",
|
|
async function (assert) {
|
|
assert.expect(1);
|
|
|
|
const unpatchDate = patchDate(2021, 8, 16, 16, 54, 0);
|
|
|
|
serverData.views["foo,false,search"] = `
|
|
<search>
|
|
<filter name="other_filter" string="Other Filter" domain="[('bar', '=', 2)]"/>
|
|
<filter name="forecast_filter" string="Forecast Filter" context="{ 'forecast_filter': 1 }"/>
|
|
</search>
|
|
`;
|
|
|
|
await makeView({
|
|
resModel: "foo",
|
|
type: "graph",
|
|
serverData,
|
|
searchViewId: false,
|
|
context: {
|
|
search_default_other_filter: 1,
|
|
search_default_forecast_filter: 1,
|
|
forecast_field: "date_field",
|
|
},
|
|
mockRPC(_, args) {
|
|
if (args.method === "web_read_group") {
|
|
const { domain } = args.kwargs;
|
|
assert.deepEqual(domain, [
|
|
"&",
|
|
["bar", "=", 2],
|
|
"|",
|
|
["date_field", "=", false],
|
|
["date_field", ">=", "2021-09-01"],
|
|
]);
|
|
}
|
|
},
|
|
});
|
|
|
|
// note that the facets of the two filters are combined with an OR.
|
|
// --> current behavior in legacy
|
|
|
|
unpatchDate();
|
|
}
|
|
);
|
|
|
|
/** @todo remove this legacy test when conversion of all forecast views is done */
|
|
QUnit.test(
|
|
"legacy and new forecast views can share search model state",
|
|
async function (assert) {
|
|
assert.expect(16);
|
|
|
|
patchWithCleanup(browser, { setTimeout: (fn) => fn() });
|
|
const unpatchDate = patchDate(2021, 8, 16, 16, 54, 0);
|
|
|
|
const expectedDomains = [
|
|
// first doAction
|
|
forecastDomain("2021-09-01"), // initial load of forecast_graph
|
|
forecastDomain("2021-07-01"), // toggle date field groupby with quarter option
|
|
forecastDomain("2021-07-01"), // initial load of legacy_toy
|
|
forecastDomain("2021-01-01"), // toggle date field groupby with year option
|
|
forecastDomain("2021-01-01"), // switch back to forecast_graph
|
|
|
|
// second doAction
|
|
|
|
forecastDomain("2021-09-01"), // initial load of legacy_toy
|
|
forecastDomain("2021-07-01"), // toggle date field groupby with quarter option
|
|
forecastDomain("2021-07-01"), // switch to forecast_graph
|
|
forecastDomain("2021-01-01"), // toggle date field groupby with year option
|
|
forecastDomain("2021-01-01"), // switch back to legacy_toy
|
|
];
|
|
|
|
patchWithCleanup(AbstractModel.prototype, {
|
|
async load(params) {
|
|
assert.deepEqual(params.domain, expectedDomains.shift());
|
|
return this._super(...arguments);
|
|
},
|
|
async reload(_, params) {
|
|
assert.deepEqual(params.domain, expectedDomains.shift());
|
|
return this._super(...arguments);
|
|
},
|
|
});
|
|
|
|
const LegacyForecastView = AbstractView.extend({
|
|
display_name: _lt("Legacy toy view"),
|
|
icon: "fa fa-bars",
|
|
multiRecord: true,
|
|
viewType: "legacy_toy",
|
|
searchMenuTypes: ["filter", "groupBy"],
|
|
|
|
_createSearchModel(params, extraExtensions = {}) {
|
|
Object.assign(extraExtensions, { forecast: {} });
|
|
return this._super(params, extraExtensions);
|
|
},
|
|
});
|
|
|
|
legacyViewRegistry.add("legacy_toy", LegacyForecastView);
|
|
|
|
const webClient = await createWebClient({
|
|
serverData,
|
|
mockRPC(_, args) {
|
|
if (args.method === "web_read_group") {
|
|
const { domain } = args.kwargs;
|
|
assert.deepEqual(domain, expectedDomains.shift());
|
|
}
|
|
},
|
|
});
|
|
|
|
// first doAction forecast_graph -> legacy_toy -> forecast_graph
|
|
|
|
await doAction(webClient, {
|
|
name: "Action name",
|
|
res_model: "foo",
|
|
type: "ir.actions.act_window",
|
|
views: [
|
|
[false, "graph"],
|
|
[false, "legacy_toy"],
|
|
],
|
|
context: {
|
|
search_default_forecast_filter: 1,
|
|
forecast_field: "date_field",
|
|
},
|
|
});
|
|
|
|
assert.containsOnce(target, ".o_switch_view.o_graph.active");
|
|
|
|
await toggleGroupByMenu(target);
|
|
await toggleMenuItem(target, "Date Field");
|
|
await toggleMenuItemOption(target, "Date Field", "Quarter");
|
|
|
|
await switchView(target, "legacy_toy");
|
|
await legacyExtraNextTick();
|
|
|
|
assert.containsOnce(target, ".o_switch_view.o_legacy_toy.active");
|
|
|
|
await cpHelpers.toggleGroupByMenu(target);
|
|
await toggleMenuItem(target, "Date Field");
|
|
await toggleMenuItemOption(target, "Date Field", "Year");
|
|
|
|
await switchView(target, "graph");
|
|
|
|
assert.containsOnce(target, ".o_switch_view.o_graph.active");
|
|
|
|
// second doAction legacy_toy -> forecast_graph -> legacy_toy
|
|
|
|
await doAction(webClient, {
|
|
name: "Action name",
|
|
res_model: "foo",
|
|
type: "ir.actions.act_window",
|
|
views: [
|
|
[false, "legacy_toy"],
|
|
[false, "graph"],
|
|
],
|
|
context: {
|
|
search_default_forecast_filter: 1,
|
|
forecast_field: "date_field",
|
|
},
|
|
});
|
|
await legacyExtraNextTick();
|
|
|
|
assert.containsOnce(target, ".o_switch_view.o_legacy_toy.active");
|
|
|
|
await cpHelpers.toggleGroupByMenu(target);
|
|
await toggleMenuItem(target, "Date Field");
|
|
await toggleMenuItemOption(target, "Date Field", "Quarter");
|
|
|
|
await switchView(target, "graph");
|
|
|
|
assert.containsOnce(target, ".o_switch_view.o_graph.active");
|
|
|
|
await toggleGroupByMenu(target);
|
|
await toggleMenuItem(target, "Date Field");
|
|
await toggleMenuItemOption(target, "Date Field", "Year");
|
|
|
|
await switchView(target, "legacy_toy");
|
|
await legacyExtraNextTick();
|
|
|
|
assert.containsOnce(target, ".o_switch_view.o_legacy_toy.active");
|
|
|
|
unpatchDate();
|
|
}
|
|
);
|
|
});
|