233 lines
12 KiB
JavaScript
233 lines
12 KiB
JavaScript
|
/** @odoo-module */
|
||
|
|
||
|
import { browser } from "@web/core/browser/browser";
|
||
|
import { click, getFixture, patchWithCleanup } from "@web/../tests/helpers/utils";
|
||
|
import { setupControlPanelServiceRegistry, toggleSearchBarMenu, toggleMenuItem, toggleMenuItemOption } from "@web/../tests/search/helpers";
|
||
|
import { makeView } from "@web/../tests/views/helpers";
|
||
|
import { registry } from "@web/core/registry";
|
||
|
import { makeFakeNotificationService } from "@web/../tests/helpers/mock_services";
|
||
|
import { getFirstElementForXpath } from './project_test_utils';
|
||
|
|
||
|
QUnit.module("Project", {}, () => {
|
||
|
QUnit.module("Views", (hooks) => {
|
||
|
let makeViewParams;
|
||
|
let target;
|
||
|
hooks.beforeEach(async (assert) => {
|
||
|
target = getFixture();
|
||
|
const serverData = {
|
||
|
models: {
|
||
|
burndown_chart: {
|
||
|
fields: {
|
||
|
date: { string: "Date", type: "date", store: true, sortable: true },
|
||
|
project_id: { string: "Project", type: "many2one", relation: "project", store: true, sortable: true },
|
||
|
stage_id: { string: "Stage", type: "many2one", relation: "stage", store: true, sortable: true },
|
||
|
nb_tasks: { string: "Number of Tasks", type: "integer", store: true, sortable: true, group_operator: "sum" }
|
||
|
},
|
||
|
records: [
|
||
|
{ id: 1, project_id: 1, stage_id: 1, date: "2020-01-01", nb_tasks: 10 },
|
||
|
{ id: 2, project_id: 1, stage_id: 2, date: "2020-02-01", nb_tasks: 5 },
|
||
|
{ id: 3, project_id: 1, stage_id: 3, date: "2020-03-01", nb_tasks: 2 },
|
||
|
],
|
||
|
},
|
||
|
project: {
|
||
|
fields: {
|
||
|
name: { string: "Project Name", type: "char" },
|
||
|
},
|
||
|
records: [{ id: 1, name: "Project A" }]
|
||
|
},
|
||
|
stage: {
|
||
|
fields: {
|
||
|
name: { string: "Stage Name", type: "char" },
|
||
|
},
|
||
|
records: [
|
||
|
{ id: 1, name: "Todo" },
|
||
|
{ id: 2, name: "In Progress" },
|
||
|
{ id: 3, name: "Done" },
|
||
|
],
|
||
|
},
|
||
|
"project.task.type": {
|
||
|
fields: {
|
||
|
name: { string: "Name", type: "char" },
|
||
|
sequence: { type: "integer" },
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
views: {
|
||
|
"burndown_chart,false,graph": `
|
||
|
<graph type="line">
|
||
|
<field name="date" string="Date" interval="month"/>
|
||
|
<field name="stage_id"/>
|
||
|
<field name="nb_tasks" type="measure"/>
|
||
|
</graph>
|
||
|
`,
|
||
|
"burndown_chart,false,search": `
|
||
|
<search/>
|
||
|
`,
|
||
|
},
|
||
|
};
|
||
|
makeViewParams = {
|
||
|
serverData,
|
||
|
resModel: "burndown_chart",
|
||
|
type: "burndown_chart",
|
||
|
};
|
||
|
setupControlPanelServiceRegistry();
|
||
|
const notificationMock = () => {
|
||
|
assert.step("notification_triggered");
|
||
|
return () => {};
|
||
|
};
|
||
|
registry.category("services").add("notification", makeFakeNotificationService(notificationMock), {
|
||
|
force: true,
|
||
|
});
|
||
|
});
|
||
|
|
||
|
QUnit.module("BurndownChart");
|
||
|
|
||
|
QUnit.test("check that the sort buttons are invisible", async function (assert) {
|
||
|
await makeView(makeViewParams);
|
||
|
assert.containsNone(target, '.o_cp_bottom_left:has(.btn-group[role=toolbar][aria-label="Sort graph"])', "The sort buttons are not rendered.");
|
||
|
});
|
||
|
|
||
|
async function makeBurnDownChartWithSearchView(makeViewOverwriteParams = { }) {
|
||
|
patchWithCleanup(browser, {
|
||
|
setTimeout: (fn) => fn(),
|
||
|
clearTimeout: () => {},
|
||
|
});
|
||
|
await makeView({
|
||
|
...makeViewParams,
|
||
|
searchViewId: false,
|
||
|
searchViewArch: `
|
||
|
<search string="Burndown Chart">
|
||
|
<filter string="Date" name="date" context="{'group_by': 'date'}" />
|
||
|
<filter string="Stage" name="stage" context="{'group_by': 'stage_id'}" />
|
||
|
</search>
|
||
|
`,
|
||
|
searchViewFields: {
|
||
|
date: {
|
||
|
name: "date",
|
||
|
string: "Date",
|
||
|
type: "date",
|
||
|
store: true,
|
||
|
sortable: true,
|
||
|
searchable: true,
|
||
|
},
|
||
|
stage_id: {
|
||
|
name: "stage_id",
|
||
|
string: "Stage",
|
||
|
type: "many2one",
|
||
|
store: true,
|
||
|
sortable: true,
|
||
|
searchable: true,
|
||
|
},
|
||
|
},
|
||
|
context: { ...makeViewParams.context, 'search_default_date': 1, 'search_default_stage': 1 },
|
||
|
...makeViewOverwriteParams,
|
||
|
});
|
||
|
}
|
||
|
|
||
|
async function testBurnDownChartWithSearchView(stepsTriggeringNotification, assert) {
|
||
|
await makeBurnDownChartWithSearchView();
|
||
|
await stepsTriggeringNotification();
|
||
|
assert.verifySteps(['notification_triggered']);
|
||
|
}
|
||
|
|
||
|
async function openGroupByMainMenu(target) {
|
||
|
await toggleSearchBarMenu(target);
|
||
|
}
|
||
|
|
||
|
async function openGroupByDateMenu(target) {
|
||
|
await openGroupByMainMenu(target);
|
||
|
await toggleMenuItem(target, 'Date');
|
||
|
}
|
||
|
|
||
|
async function toggleGroupByStageMenu(target) {
|
||
|
await openGroupByMainMenu(target);
|
||
|
await toggleMenuItem(target, 'Stage');
|
||
|
}
|
||
|
|
||
|
async function toggleSelectedGroupByDateItem(target) {
|
||
|
await openGroupByDateMenu(target);
|
||
|
const selectedGroupByDateItemXpath = `//div
|
||
|
[contains(@class, 'o_group_by_menu')]
|
||
|
//button
|
||
|
[contains(@class, 'o_menu_item')]
|
||
|
[contains(., 'Date')]
|
||
|
/following-sibling::div
|
||
|
/span
|
||
|
[contains(@class, 'o_item_option')]
|
||
|
[contains(@class, 'selected')]`;
|
||
|
const selectedGroupByDateItemElement = getFirstElementForXpath(target, selectedGroupByDateItemXpath);
|
||
|
await toggleMenuItemOption(target, 'Date', selectedGroupByDateItemElement.innerText);
|
||
|
}
|
||
|
|
||
|
QUnit.test("check that removing the group by 'Date: Month > Stage' in the search bar triggers a notification", async function (assert) {
|
||
|
|
||
|
const stepsTriggeringNotification = async () => {
|
||
|
// There's only one possibility here
|
||
|
await click(target, ".o_facet_remove");
|
||
|
};
|
||
|
await testBurnDownChartWithSearchView(stepsTriggeringNotification, assert);
|
||
|
});
|
||
|
|
||
|
QUnit.test("check that removing the group by 'Date' triggers a notification", async function (assert) {
|
||
|
const stepsTriggeringNotification = async () => {
|
||
|
await toggleSelectedGroupByDateItem(target);
|
||
|
};
|
||
|
await testBurnDownChartWithSearchView(stepsTriggeringNotification, assert);
|
||
|
});
|
||
|
|
||
|
QUnit.test("check that removing the group by 'Stage' triggers a notification", async function (assert) {
|
||
|
const stepsTriggeringNotification = async () => {
|
||
|
await toggleGroupByStageMenu(target);
|
||
|
};
|
||
|
await testBurnDownChartWithSearchView(stepsTriggeringNotification, assert);
|
||
|
});
|
||
|
|
||
|
QUnit.test("check that adding a group by 'Date' actually toggle it", async function (assert) {
|
||
|
await makeBurnDownChartWithSearchView();
|
||
|
await openGroupByDateMenu(target);
|
||
|
const firstNotSelectedGroupByDateItemXpath = `//div
|
||
|
[contains(@class, 'o_group_by_menu')]
|
||
|
//button
|
||
|
[contains(@class, 'o_menu_item')]
|
||
|
[contains(., 'Date')]
|
||
|
/following-sibling::div
|
||
|
/span
|
||
|
[contains(@class, 'o_item_option')]
|
||
|
[not(contains(@class, 'selected'))]`;
|
||
|
const firstNotSelectedGroupByDateItemElement = getFirstElementForXpath(target, firstNotSelectedGroupByDateItemXpath);
|
||
|
await toggleMenuItemOption(target, 'Date', firstNotSelectedGroupByDateItemElement.innerText);
|
||
|
const groupByDateSubMenuXpath = `//div
|
||
|
[contains(@class, 'o_group_by_menu')]
|
||
|
//button
|
||
|
[contains(@class, 'o_menu_item')]
|
||
|
[contains(., 'Date')]
|
||
|
/following-sibling::div`;
|
||
|
const groupByDateSubMenuElement = getFirstElementForXpath(target, groupByDateSubMenuXpath);
|
||
|
const selectedGroupByDateItemElements = groupByDateSubMenuElement.querySelectorAll('span.o_item_option.selected');
|
||
|
assert.equal(selectedGroupByDateItemElements.length, 1, 'There is only one selected item.');
|
||
|
assert.equal(firstNotSelectedGroupByDateItemElement.innerText, selectedGroupByDateItemElements[0].innerText, 'The selected item is the one we clicked on.');
|
||
|
});
|
||
|
|
||
|
function checkGroupByOrder(assert) {
|
||
|
const dateSearchFacetXpath = `//div[contains(@class, 'o_searchview_facet')]
|
||
|
[.//small[@class='o_facet_value']
|
||
|
[contains(., 'Date: Month')]]`;
|
||
|
const dateSearchFacetElement = getFirstElementForXpath(target, dateSearchFacetXpath);
|
||
|
const dateSearchFacetParts = dateSearchFacetElement.querySelectorAll('.o_facet_value');
|
||
|
assert.equal(dateSearchFacetParts.length, 2);
|
||
|
assert.equal(dateSearchFacetParts[0].innerText, 'Date: Month');
|
||
|
assert.equal(dateSearchFacetParts[1].innerText, 'Stage');
|
||
|
}
|
||
|
|
||
|
QUnit.test("check that the group by is always sorted 'Date' first, 'Stage' second", async function (assert) {
|
||
|
await makeBurnDownChartWithSearchView({context: {...makeViewParams.context, 'search_default_date': 1, 'search_default_stage': 1}});
|
||
|
checkGroupByOrder(assert);
|
||
|
});
|
||
|
|
||
|
QUnit.test("check that the group by is always sorted 'Date' first, 'Stage' second", async function (assert) {
|
||
|
await makeBurnDownChartWithSearchView({context: {...makeViewParams.context, 'search_default_stage': 1, 'search_default_date': 1}});
|
||
|
checkGroupByOrder(assert);
|
||
|
});
|
||
|
});
|
||
|
});
|