[FIX] hr_timesheet: ensure task_with_hours widget works as expected

Prior to this commit, altought the widget was working from the UI, tests
have detected that `activeActions` from the state was not updated when
props where updated.

task-3001470

X-original-commit: 0fb1ff059c40b2489e315fe630a3b39625c468ec
This commit is contained in:
Laurent Stukkens (LTU)
2022-10-11 13:06:06 +02:00
parent d0987e0b25
commit 63f95986a7
3 changed files with 207 additions and 8 deletions
@@ -6,14 +6,6 @@ import { Many2OneField } from "@web/views/fields/many2one/many2one_field";
class TaskWithHours extends Many2OneField {
setup() {
super.setup();
const activeActions = this.state.activeActions;
activeActions.canCreate = activeActions.canCreate && this.canCreate;
activeActions.canQuickCreate = activeActions.canQuickCreate || this.canCreate;
activeActions.canCreateEdit = activeActions.canCreate;
}
get canCreate() {
return Boolean(this.context.default_project_id);
}
@@ -44,6 +36,16 @@ class TaskWithHours extends Many2OneField {
return props;
}
/**
* @override
*/
computeActiveActions(props) {
super.computeActiveActions(props);
const activeActions = this.state.activeActions;
activeActions.create = activeActions.create && this.canCreate;
activeActions.createEdit = activeActions.create;
}
}
registry.category("fields").add("task_with_hours", TaskWithHours);
@@ -0,0 +1,130 @@
/** @odoo-module */
import { registry } from "@web/core/registry";
import { session } from "@web/session";
import { companyService } from "@web/webclient/company_service";
import { patchWithCleanup } from "@web/../tests/helpers/utils";
import { setupViewRegistries } from "@web/../tests/views/helpers";
export const getServerData = () => JSON.parse(JSON.stringify({
models: {
'account.analytic.line': {
fields: {
project_id: { string: "Project", type: "many2one", relation: "project.project" },
task_id: { string: "Task", type: "many2one", relation: "project.task" },
unit_amount: { string: "Unit Amount", type: "integer" },
},
records: [
{ id: 1, project_id: 1, task_id: 3, unit_amount: 1 },
{ id: 2, project_id: 1, task_id: false, unit_amount: 1 },
{ id: 3, project_id: false, task_id: false, unit_amount: 1 },
],
},
'project.project': {
fields: {
name: { string: "Name", type: "string" },
},
records: [
{ id: 1, name: "Project 1" },
],
},
'project.task': {
fields: {
name: { string: "Name", type: "string" },
project_id: { string: "Project", type: "many2one", relation: "project.project" },
},
records: [
{ id: 1, name: "Task 1\u00A0AdditionalInfo", project_id: 1 },
{ id: 2, name: "Task 2\u00A0AdditionalInfo", project_id: 1 },
{ id: 3, name: "Task 3\u00A0AdditionalInfo", project_id: 1 },
],
},
},
views: {
"account.analytic.line,false,form": `
<form>
<field name="project_id"/>
<field name="task_id"/>
<field name="unit_amount"/>
</form>
`,
"account.analytic.line,false,list": `
<tree editable="bottom">
<field name="project_id"/>
<field name="task_id"/>
<field name="unit_amount"/>
</tree>
`,
},
}));
export function updateArch(serverData, fieldNameWidgetNameMapping = {}, fieldNameContextMapping = {}) {
for (const viewKey in serverData.views) {
for (const [fieldName, widgetName] of Object.entries(fieldNameWidgetNameMapping)) {
serverData.views[viewKey] = serverData.views[viewKey].replace(
`name="${fieldName}"`,
`name="${fieldName}" widget="${widgetName}"`
);
}
for (const [fieldName, context] of Object.entries(fieldNameContextMapping)) {
serverData.views[viewKey] = serverData.views[viewKey].replace(
`name="${fieldName}"`,
`name="${fieldName}" context="${context}"`
);
}
}
}
export function addFieldsInArch(serverData, fields, beforeField) {
let fieldsArch = "";
for (const field of fields) {
fieldsArch += `<field name="${field}"/>
`;
}
for (const viewKey in serverData.views) {
serverData.views[viewKey] = serverData.views[viewKey].replace(
`<field name="${beforeField}"`,
`${fieldsArch}<field name="${beforeField}"`
);
}
}
export function setupTestEnv() {
setupViewRegistries();
patchWithCleanup(session, {
user_companies: {
current_company: 1,
allowed_companies: {
1: {
id: 1,
name: 'Company',
timesheet_uom_id: 1,
timesheet_uom_factor: 1,
},
},
},
user_context: {
allowed_company_ids: [1],
},
uom_ids: {
1: {
id: 1,
name: 'hour',
rounding: 0.01,
timesheet_widget: 'float_time',
},
2: {
id: 2,
name: 'day',
rounding: 0.01,
timesheet_widget: 'float_toggle',
},
},
});
const serviceRegistry = registry.category("services");
serviceRegistry.add("company", companyService, { force: true });
}
@@ -0,0 +1,67 @@
/** @odoo-module */
import { makeView } from "@web/../tests/views/helpers";
import { click, clickDropdown, editInput, getFixture } from "@web/../tests/helpers/utils";
import { getServerData, updateArch, setupTestEnv } from "./hr_timesheet_common_tests";
QUnit.module("hr_timesheet", (hooks) => {
let target;
let serverData;
hooks.beforeEach(async function (assert) {
setupTestEnv();
serverData = getServerData();
updateArch(
serverData,
{ task_id: "task_with_hours" },
{ task_id: "{ 'default_project_id': project_id }" });
target = getFixture();
});
QUnit.module("task_with_hours");
async function _testCreateAndEdit(target, visible, assert) {
await click(target, ".o_list_many2one[name=task_id]");
await click(target, ".o_list_many2one[name=task_id] input");
await editInput(target, ".o_list_many2one[name=task_id] input", "NonExistingTask");
await click(target, ".o_list_many2one[name=task_id] input");
await clickDropdown(target, "task_id");
const testFunction = visible ? assert.containsOnce : assert.containsNone;
testFunction(target, '.o_list_many2one[name=task_id] .dropdown ul li:contains("Create and edit...")');
}
QUnit.test("quick create is enabled when project_id is set", async function (assert) {
await makeView({
serverData,
type: "list",
resModel: "account.analytic.line",
});
const secondRow = target.querySelector(".o_list_table .o_data_row:nth-of-type(2)");
await _testCreateAndEdit(secondRow, true, assert);
});
QUnit.test("quick create is no enabled when project_id is not set", async function (assert) {
await makeView({
serverData,
type: "list",
resModel: "account.analytic.line",
});
const thirdRow = target.querySelector(".o_list_table .o_data_row:nth-of-type(3)");
await _testCreateAndEdit(thirdRow, false, assert);
});
QUnit.test("the text of the task includes hours in the drop down but not in the line", async function (assert) {
await makeView({
serverData,
type: "list",
resModel: "account.analytic.line",
});
const firstRow = target.querySelector(".o_list_table .o_data_row:first-of-type");
assert.containsNone(firstRow, '.o_list_many2one[name=task_id]:contains("AdditionalInfo")');
await click(firstRow, ".o_list_many2one[name=task_id]");
await clickDropdown(firstRow, "task_id");
assert.containsN(firstRow, '.o_list_many2one[name=task_id] .dropdown ul li:contains("AdditionalInfo")', 3);
});
});