[FW][MERGE] hr_timesheet,web: add owl tests and fix bugs
This PR purpose is to ensure that tests are created on OWL Components that have been created in the context of the OWL migration PR odoo/odoo#100729. This PR also addresses some bugs that have been discovered during tests writings. task-3001470 closes odoo/odoo#103033 Forward-port-of: odoo/odoo#101967 Signed-off-by: Laurent Stukkens (ltu) <ltu@odoo.com>
This commit is contained in:
@@ -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,140 @@
|
||||
odoo.define("hr_timesheet.timesheet_uom_tests", function (require) {
|
||||
"use strict";
|
||||
|
||||
const session = require('web.session');
|
||||
const SetupTimesheetUOMWidgetsTestEnvironment = require('hr_timesheet.timesheet_uom_tests_env');
|
||||
const fieldUtils = require('web.field_utils');
|
||||
const TimesheetUOM = require('hr_timesheet.timesheet_uom');
|
||||
|
||||
QUnit.module('Timesheet UOM Widgets', function (hooks) {
|
||||
let env;
|
||||
let sessionUserCompaniesBackup;
|
||||
let sessionUserContextBackup;
|
||||
let sessionUOMIdsBackup;
|
||||
let sessionUIDBackup;
|
||||
hooks.beforeEach(async function (assert) {
|
||||
env = new SetupTimesheetUOMWidgetsTestEnvironment();
|
||||
// Backups session parts that this testing module will alter in order to restore it at the end.
|
||||
sessionUserCompaniesBackup = session.user_companies || false;
|
||||
sessionUserContextBackup = session.user_context || false;
|
||||
sessionUOMIdsBackup = session.uom_ids || false;
|
||||
sessionUIDBackup = session.uid || false;
|
||||
});
|
||||
hooks.afterEach(async function (assert) {
|
||||
// Restores the session
|
||||
const sessionToApply = Object.assign(
|
||||
{ },
|
||||
sessionUserCompaniesBackup && {
|
||||
user_companies: sessionUserCompaniesBackup,
|
||||
} || { },
|
||||
sessionUserContextBackup && {
|
||||
user_context: sessionUserContextBackup,
|
||||
} || { },
|
||||
sessionUOMIdsBackup && {
|
||||
uom_ids: sessionUOMIdsBackup,
|
||||
} || { },
|
||||
sessionUIDBackup && {
|
||||
uid: sessionUIDBackup,
|
||||
} || { });
|
||||
await env.patchSessionAndStartServices(sessionToApply, true);
|
||||
});
|
||||
QUnit.module('timesheet_uom', function (hooks) {
|
||||
QUnit.module('fieldRegistry', function (hooks) {
|
||||
let FieldTimesheetTimeBackup;
|
||||
let FieldTimesheetToggleBackup;
|
||||
hooks.beforeEach(function (assert) {
|
||||
// Backups the FieldTimesheetTime widget as it will be altered in this testing module
|
||||
// in order to to ease testing.
|
||||
FieldTimesheetTimeBackup = TimesheetUOM.FieldTimesheetTime;
|
||||
TimesheetUOM.FieldTimesheetTime.include({
|
||||
_render: function () {
|
||||
const $widgetIdentification = $('<div>').addClass('i_am_a_timesheet_time_widget');
|
||||
this.$el.append($widgetIdentification);
|
||||
},
|
||||
});
|
||||
FieldTimesheetToggleBackup = TimesheetUOM.FieldTimesheetToggle;
|
||||
TimesheetUOM.FieldTimesheetToggle.include({
|
||||
_render: function () {
|
||||
const $widgetIdentification = $('<div>').addClass('i_am_a_timesheet_toggle_widget');
|
||||
this.$el.append($widgetIdentification);
|
||||
},
|
||||
});
|
||||
});
|
||||
hooks.afterEach(async function (hooks) {
|
||||
// Restores the widgets and trigger reload in FieldRegistry.
|
||||
TimesheetUOM.FieldTimesheetTime = FieldTimesheetTimeBackup;
|
||||
TimesheetUOM.FieldTimesheetToggle = FieldTimesheetToggleBackup;
|
||||
await env.patchSessionAndStartServices({ }, true);
|
||||
});
|
||||
QUnit.test('the timesheet_uom widget added to the fieldRegistry is company related', async function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
let view = await env.createView();
|
||||
assert.ok(view.$('.i_am_a_timesheet_time_widget').length, 'FieldTimesheetTime is rendered when company uom is hour');
|
||||
view.destroy();
|
||||
|
||||
let option = {
|
||||
session: {
|
||||
user_context: env.singleCompanyDayUOMUser,
|
||||
},
|
||||
};
|
||||
view = await env.createView(option);
|
||||
assert.ok(view.$('.i_am_a_timesheet_toggle_widget').length, 'FieldTimesheetToggle is rendered when company uom is day');
|
||||
view.destroy();
|
||||
});
|
||||
QUnit.test('the timesheet_uom widget added to the fieldRegistry in a multi company environment is the current company', async function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
let option = {
|
||||
session: {
|
||||
user_context: env.multiCompanyHourUOMUser,
|
||||
},
|
||||
};
|
||||
let view = await env.createView(option);
|
||||
assert.ok(view.$('.i_am_a_timesheet_time_widget').length, 'FieldTimesheetTime is rendered when current company uom is hour');
|
||||
view.destroy();
|
||||
|
||||
option = {
|
||||
session: {
|
||||
user_context: env.multiCompanyDayUOMUser,
|
||||
},
|
||||
};
|
||||
view = await env.createView(option);
|
||||
assert.ok(view.$('.i_am_a_timesheet_toggle_widget').length, 'FieldTimesheetToggle is rendered when current company uom is day');
|
||||
view.destroy();
|
||||
});
|
||||
});
|
||||
QUnit.module('timesheet_uom_factor', function (hooks) {
|
||||
QUnit.test('the timesheet_uom_factor usage in formatters and parsers is company related', async function (assert) {
|
||||
assert.expect(4);
|
||||
|
||||
await env.patchSessionAndStartServices();
|
||||
assert.strictEqual(fieldUtils.format.timesheet_uom(1), '01:00', 'The format is taking the timesheet_uom_factor into account');
|
||||
assert.strictEqual(fieldUtils.parse.timesheet_uom('01:00'), 1, 'The parsing is taking the timesheet_uom_factor into account');
|
||||
|
||||
const sessionToApply = {
|
||||
user_context: env.singleCompanyDayUOMUser,
|
||||
};
|
||||
await env.patchSessionAndStartServices(sessionToApply);
|
||||
assert.strictEqual(fieldUtils.format.timesheet_uom(8), '1.00', 'The format is taking the timesheet_uom_factor into account');
|
||||
assert.strictEqual(fieldUtils.parse.timesheet_uom('1.00'), 8, 'The parsing is taking the timesheet_uom_factor into account');
|
||||
});
|
||||
QUnit.test('the timesheet_uom_factor taken into account in a multi company environment is the current company', async function (assert) {
|
||||
assert.expect(4);
|
||||
|
||||
let sessionToApply = {
|
||||
user_context: env.multiCompanyHourUOMUser,
|
||||
};
|
||||
await env.patchSessionAndStartServices(sessionToApply);
|
||||
assert.strictEqual(fieldUtils.format.timesheet_uom(1), '01:00', 'The format is taking the timesheet_uom_factor into account');
|
||||
assert.strictEqual(fieldUtils.parse.timesheet_uom('01:00'), 1, 'The parsing is taking the timesheet_uom_factor into account');
|
||||
|
||||
sessionToApply.user_context = env.singleCompanyDayUOMUser;
|
||||
await env.patchSessionAndStartServices(sessionToApply);
|
||||
assert.strictEqual(fieldUtils.format.timesheet_uom(8), '1.00', 'The format is taking the timesheet_uom_factor into account');
|
||||
assert.strictEqual(fieldUtils.parse.timesheet_uom('1.00'), 8, 'The parsing is taking the timesheet_uom_factor into account');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
});
|
||||
@@ -11,7 +11,7 @@ import { setupControlPanelServiceRegistry } from "@web/../tests/search/helpers";
|
||||
|
||||
const serviceRegistry = registry.category("services");
|
||||
|
||||
QUnit.module('Views', function (hooks) {
|
||||
QUnit.module('hr_timesheet', function (hooks) {
|
||||
let serverData;
|
||||
hooks.beforeEach(() => {
|
||||
serverData = {
|
||||
@@ -40,7 +40,7 @@ QUnit.module('Views', function (hooks) {
|
||||
serviceRegistry.add("dialog", dialogService);
|
||||
});
|
||||
|
||||
QUnit.module("hrTimesheetGraphView");
|
||||
QUnit.module("hr_timesheet_graphview");
|
||||
|
||||
QUnit.test('the timesheet graph view data are not multiplied by a factor that is company related (factor = 1)', async function (assert) {
|
||||
assert.expect(1);
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import { session } from "@web/session";
|
||||
|
||||
import { makeView } from "@web/../tests/views/helpers";
|
||||
import { getFixture, patchWithCleanup } 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, { unit_amount: "timesheet_uom_no_toggle" });
|
||||
target = getFixture();
|
||||
});
|
||||
|
||||
QUnit.module("timesheet_uom_no_toggle");
|
||||
|
||||
QUnit.test("FloatTimeField is used when current company uom uses float_time widget", async function (assert) {
|
||||
await makeView({
|
||||
serverData,
|
||||
type: "form",
|
||||
resModel: "account.analytic.line",
|
||||
resId: 1,
|
||||
});
|
||||
const unitAmountInput = target.querySelector('div[name="unit_amount"] input');
|
||||
assert.equal(unitAmountInput.value, "01:00", "unit_amount is displayed as time");
|
||||
});
|
||||
|
||||
QUnit.test("FloatTimeField is not dependent of timesheet_uom_factor of the current company when current company uom uses float_time widget", async function (assert) {
|
||||
patchWithCleanup(session.user_companies.allowed_companies[1], { timesheet_uom_factor: 2 });
|
||||
await makeView({
|
||||
serverData,
|
||||
type: "form",
|
||||
resModel: "account.analytic.line",
|
||||
resId: 1,
|
||||
});
|
||||
const unitAmountInput = target.querySelector('div[name="unit_amount"] input');
|
||||
assert.equal(unitAmountInput.value, "01:00", "timesheet_uom_factor is not taken into account");
|
||||
});
|
||||
|
||||
QUnit.test("FloatToggleField is not used when current company uom uses float_toggle widget, FloatFactorField is used instead", async function (assert) {
|
||||
patchWithCleanup(session.user_companies.allowed_companies[1], { timesheet_uom_id: 2 });
|
||||
await makeView({
|
||||
serverData,
|
||||
type: "form",
|
||||
resModel: "account.analytic.line",
|
||||
resId: 1,
|
||||
});
|
||||
assert.containsNone(target, 'div[name="unit_amount"] .o_field_float_toggle', "unit_amount is not displayed as float toggle");
|
||||
const unitAmountInput = target.querySelector('div[name="unit_amount"] input');
|
||||
assert.containsOnce(target, 'div[name="unit_amount"] input[inputmode="numeric"]', "unit_amount is displayed as float");
|
||||
assert.equal(unitAmountInput.value, "1.00", "unit_amount is not displayed as float and not as time");
|
||||
});
|
||||
|
||||
QUnit.test("FloatFactorField is used when the current_company uom is not part of the session uom", async function (assert) {
|
||||
patchWithCleanup(session.user_companies.allowed_companies[1], { timesheet_uom_id: 'dummy' });
|
||||
await makeView({
|
||||
serverData,
|
||||
type: "form",
|
||||
resModel: "account.analytic.line",
|
||||
resId: 1,
|
||||
});
|
||||
const unitAmountInput = target.querySelector('div[name="unit_amount"] input');
|
||||
assert.containsOnce(target, 'div[name="unit_amount"] input[inputmode="numeric"]', "unit_amount is displayed as float");
|
||||
assert.equal(unitAmountInput.value, "1.00", "unit_amount is not displayed as float and not as time");
|
||||
assert.containsNone(target, 'div[name="unit_amount"].o_field_float_toggle', "unit_amount is not displayed as float toggle");
|
||||
});
|
||||
|
||||
QUnit.test("FloatFactorField is dependent of timesheet_uom_factor of the current company when current company uom uses float_toggle widget", async function (assert) {
|
||||
patchWithCleanup(session.user_companies.allowed_companies[1], { timesheet_uom_id: 'dummy', timesheet_uom_factor: 2 });
|
||||
await makeView({
|
||||
serverData,
|
||||
type: "form",
|
||||
resModel: "account.analytic.line",
|
||||
resId: 1,
|
||||
});
|
||||
const unitAmountInput = target.querySelector('div[name="unit_amount"] input');
|
||||
assert.equal(unitAmountInput.value, "2.00", "timesheet_uom_factor is taken into account");
|
||||
});
|
||||
|
||||
});
|
||||
@@ -1,140 +1,94 @@
|
||||
odoo.define("hr_timesheet.timesheet_uom_tests", function (require) {
|
||||
"use strict";
|
||||
/** @odoo-module */
|
||||
|
||||
const session = require('web.session');
|
||||
const SetupTimesheetUOMWidgetsTestEnvironment = require('hr_timesheet.timesheet_uom_tests_env');
|
||||
const fieldUtils = require('web.field_utils');
|
||||
const TimesheetUOM = require('hr_timesheet.timesheet_uom');
|
||||
import { session } from "@web/session";
|
||||
|
||||
QUnit.module('Timesheet UOM Widgets', function (hooks) {
|
||||
let env;
|
||||
let sessionUserCompaniesBackup;
|
||||
let sessionUserContextBackup;
|
||||
let sessionUOMIdsBackup;
|
||||
let sessionUIDBackup;
|
||||
import { makeView } from "@web/../tests/views/helpers";
|
||||
import { getFixture, patchWithCleanup } 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) {
|
||||
env = new SetupTimesheetUOMWidgetsTestEnvironment();
|
||||
// Backups session parts that this testing module will alter in order to restore it at the end.
|
||||
sessionUserCompaniesBackup = session.user_companies || false;
|
||||
sessionUserContextBackup = session.user_context || false;
|
||||
sessionUOMIdsBackup = session.uom_ids || false;
|
||||
sessionUIDBackup = session.uid || false;
|
||||
setupTestEnv();
|
||||
serverData = getServerData();
|
||||
updateArch(serverData, { unit_amount: "timesheet_uom" });
|
||||
target = getFixture();
|
||||
});
|
||||
hooks.afterEach(async function (assert) {
|
||||
// Restores the session
|
||||
const sessionToApply = Object.assign(
|
||||
{ },
|
||||
sessionUserCompaniesBackup && {
|
||||
user_companies: sessionUserCompaniesBackup,
|
||||
} || { },
|
||||
sessionUserContextBackup && {
|
||||
user_context: sessionUserContextBackup,
|
||||
} || { },
|
||||
sessionUOMIdsBackup && {
|
||||
uom_ids: sessionUOMIdsBackup,
|
||||
} || { },
|
||||
sessionUIDBackup && {
|
||||
uid: sessionUIDBackup,
|
||||
} || { });
|
||||
await env.patchSessionAndStartServices(sessionToApply, true);
|
||||
});
|
||||
QUnit.module('timesheet_uom', function (hooks) {
|
||||
QUnit.module('fieldRegistry', function (hooks) {
|
||||
let FieldTimesheetTimeBackup;
|
||||
let FieldTimesheetToggleBackup;
|
||||
hooks.beforeEach(function (assert) {
|
||||
// Backups the FieldTimesheetTime widget as it will be altered in this testing module
|
||||
// in order to to ease testing.
|
||||
FieldTimesheetTimeBackup = TimesheetUOM.FieldTimesheetTime;
|
||||
TimesheetUOM.FieldTimesheetTime.include({
|
||||
_render: function () {
|
||||
const $widgetIdentification = $('<div>').addClass('i_am_a_timesheet_time_widget');
|
||||
this.$el.append($widgetIdentification);
|
||||
},
|
||||
});
|
||||
FieldTimesheetToggleBackup = TimesheetUOM.FieldTimesheetToggle;
|
||||
TimesheetUOM.FieldTimesheetToggle.include({
|
||||
_render: function () {
|
||||
const $widgetIdentification = $('<div>').addClass('i_am_a_timesheet_toggle_widget');
|
||||
this.$el.append($widgetIdentification);
|
||||
},
|
||||
});
|
||||
});
|
||||
hooks.afterEach(async function (hooks) {
|
||||
// Restores the widgets and trigger reload in FieldRegistry.
|
||||
TimesheetUOM.FieldTimesheetTime = FieldTimesheetTimeBackup;
|
||||
TimesheetUOM.FieldTimesheetToggle = FieldTimesheetToggleBackup;
|
||||
await env.patchSessionAndStartServices({ }, true);
|
||||
});
|
||||
QUnit.test('the timesheet_uom widget added to the fieldRegistry is company related', async function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
let view = await env.createView();
|
||||
assert.ok(view.$('.i_am_a_timesheet_time_widget').length, 'FieldTimesheetTime is rendered when company uom is hour');
|
||||
view.destroy();
|
||||
QUnit.module("timesheet_uom");
|
||||
|
||||
let option = {
|
||||
session: {
|
||||
user_context: env.singleCompanyDayUOMUser,
|
||||
},
|
||||
};
|
||||
view = await env.createView(option);
|
||||
assert.ok(view.$('.i_am_a_timesheet_toggle_widget').length, 'FieldTimesheetToggle is rendered when company uom is day');
|
||||
view.destroy();
|
||||
});
|
||||
QUnit.test('the timesheet_uom widget added to the fieldRegistry in a multi company environment is the current company', async function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
let option = {
|
||||
session: {
|
||||
user_context: env.multiCompanyHourUOMUser,
|
||||
},
|
||||
};
|
||||
let view = await env.createView(option);
|
||||
assert.ok(view.$('.i_am_a_timesheet_time_widget').length, 'FieldTimesheetTime is rendered when current company uom is hour');
|
||||
view.destroy();
|
||||
|
||||
option = {
|
||||
session: {
|
||||
user_context: env.multiCompanyDayUOMUser,
|
||||
},
|
||||
};
|
||||
view = await env.createView(option);
|
||||
assert.ok(view.$('.i_am_a_timesheet_toggle_widget').length, 'FieldTimesheetToggle is rendered when current company uom is day');
|
||||
view.destroy();
|
||||
});
|
||||
});
|
||||
QUnit.module('timesheet_uom_factor', function (hooks) {
|
||||
QUnit.test('the timesheet_uom_factor usage in formatters and parsers is company related', async function (assert) {
|
||||
assert.expect(4);
|
||||
|
||||
await env.patchSessionAndStartServices();
|
||||
assert.strictEqual(fieldUtils.format.timesheet_uom(1), '01:00', 'The format is taking the timesheet_uom_factor into account');
|
||||
assert.strictEqual(fieldUtils.parse.timesheet_uom('01:00'), 1, 'The parsing is taking the timesheet_uom_factor into account');
|
||||
|
||||
const sessionToApply = {
|
||||
user_context: env.singleCompanyDayUOMUser,
|
||||
};
|
||||
await env.patchSessionAndStartServices(sessionToApply);
|
||||
assert.strictEqual(fieldUtils.format.timesheet_uom(8), '1.00', 'The format is taking the timesheet_uom_factor into account');
|
||||
assert.strictEqual(fieldUtils.parse.timesheet_uom('1.00'), 8, 'The parsing is taking the timesheet_uom_factor into account');
|
||||
});
|
||||
QUnit.test('the timesheet_uom_factor taken into account in a multi company environment is the current company', async function (assert) {
|
||||
assert.expect(4);
|
||||
|
||||
let sessionToApply = {
|
||||
user_context: env.multiCompanyHourUOMUser,
|
||||
};
|
||||
await env.patchSessionAndStartServices(sessionToApply);
|
||||
assert.strictEqual(fieldUtils.format.timesheet_uom(1), '01:00', 'The format is taking the timesheet_uom_factor into account');
|
||||
assert.strictEqual(fieldUtils.parse.timesheet_uom('01:00'), 1, 'The parsing is taking the timesheet_uom_factor into account');
|
||||
|
||||
sessionToApply.user_context = env.singleCompanyDayUOMUser;
|
||||
await env.patchSessionAndStartServices(sessionToApply);
|
||||
assert.strictEqual(fieldUtils.format.timesheet_uom(8), '1.00', 'The format is taking the timesheet_uom_factor into account');
|
||||
assert.strictEqual(fieldUtils.parse.timesheet_uom('1.00'), 8, 'The parsing is taking the timesheet_uom_factor into account');
|
||||
});
|
||||
QUnit.test("FloatTimeField is used when current company uom uses float_time widget", async function (assert) {
|
||||
await makeView({
|
||||
serverData,
|
||||
type: "form",
|
||||
resModel: "account.analytic.line",
|
||||
resId: 1,
|
||||
});
|
||||
const unitAmountInput = target.querySelector('div[name="unit_amount"] input');
|
||||
assert.equal(unitAmountInput.value, "01:00", "unit_amount is displayed as time");
|
||||
});
|
||||
});
|
||||
|
||||
QUnit.test("FloatTimeField is not dependent of timesheet_uom_factor of the current company when current company uom uses float_time widget", async function (assert) {
|
||||
patchWithCleanup(session.user_companies.allowed_companies[1], { timesheet_uom_factor: 2 });
|
||||
await makeView({
|
||||
serverData,
|
||||
type: "form",
|
||||
resModel: "account.analytic.line",
|
||||
resId: 1,
|
||||
});
|
||||
const unitAmountInput = target.querySelector('div[name="unit_amount"] input');
|
||||
assert.equal(unitAmountInput.value, "01:00", "timesheet_uom_factor is not taken into account");
|
||||
});
|
||||
|
||||
QUnit.test("FloatToggleField is used when current company uom uses float_toggle widget", async function (assert) {
|
||||
patchWithCleanup(session.user_companies.allowed_companies[1], { timesheet_uom_id: 2 });
|
||||
await makeView({
|
||||
serverData,
|
||||
type: "form",
|
||||
resModel: "account.analytic.line",
|
||||
resId: 1,
|
||||
});
|
||||
assert.containsOnce(target, 'div[name="unit_amount"] .o_field_float_toggle', "unit_amount is displayed as float toggle");
|
||||
});
|
||||
|
||||
QUnit.test("FloatToggleField is dependent of timesheet_uom_factor of the current company when current company uom uses float_toggle widget", async function (assert) {
|
||||
patchWithCleanup(session.user_companies.allowed_companies[1], { timesheet_uom_id: 2, timesheet_uom_factor: 2 });
|
||||
await makeView({
|
||||
serverData,
|
||||
type: "form",
|
||||
resModel: "account.analytic.line",
|
||||
resId: 1,
|
||||
});
|
||||
assert.containsOnce(target, 'div[name="unit_amount"] .o_field_float_toggle:contains("2.00")', "timesheet_uom_factor is taken into account");
|
||||
});
|
||||
|
||||
QUnit.test("FloatFactorField is used when the current_company uom is not part of the session uom", async function (assert) {
|
||||
patchWithCleanup(session.user_companies.allowed_companies[1], { timesheet_uom_id: 'dummy' });
|
||||
await makeView({
|
||||
serverData,
|
||||
type: "form",
|
||||
resModel: "account.analytic.line",
|
||||
resId: 1,
|
||||
});
|
||||
const unitAmountInput = target.querySelector('div[name="unit_amount"] input');
|
||||
assert.containsOnce(target, 'div[name="unit_amount"] input[inputmode="numeric"]', "unit_amount is displayed as float");
|
||||
assert.equal(unitAmountInput.value, "1.00", "unit_amount is not displayed as float and not as time");
|
||||
assert.containsNone(target, 'div[name="unit_amount"].o_field_float_toggle', "unit_amount is not displayed as float toggle");
|
||||
});
|
||||
|
||||
QUnit.test("FloatFactorField is dependent of timesheet_uom_factor of the current company when current company uom uses float_toggle widget", async function (assert) {
|
||||
patchWithCleanup(session.user_companies.allowed_companies[1], { timesheet_uom_id: 'dummy', timesheet_uom_factor: 2 });
|
||||
await makeView({
|
||||
serverData,
|
||||
type: "form",
|
||||
resModel: "account.analytic.line",
|
||||
resId: 1,
|
||||
});
|
||||
const unitAmountInput = target.querySelector('div[name="unit_amount"] input');
|
||||
assert.equal(unitAmountInput.value, "2.00", "timesheet_uom_factor is taken into account");
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -51,18 +51,10 @@ export class Many2OneField extends Component {
|
||||
this.autocompleteContainerRef.el.querySelector("input").focus();
|
||||
};
|
||||
|
||||
const computeActiveActions = (props) => {
|
||||
this.state.activeActions = {
|
||||
create: props.canCreate,
|
||||
createEdit: props.canCreateEdit,
|
||||
write: props.canWrite,
|
||||
};
|
||||
};
|
||||
|
||||
this.state = useState({
|
||||
isFloating: !this.props.value,
|
||||
});
|
||||
computeActiveActions(this.props);
|
||||
this.computeActiveActions(this.props);
|
||||
|
||||
this.openMany2X = useOpenMany2XRecord({
|
||||
resModel: this.relation,
|
||||
@@ -102,7 +94,7 @@ export class Many2OneField extends Component {
|
||||
|
||||
onWillUpdateProps(async (nextProps) => {
|
||||
this.state.isFloating = !nextProps.value;
|
||||
computeActiveActions(nextProps);
|
||||
this.computeActiveActions(nextProps);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -151,6 +143,13 @@ export class Many2OneField extends Component {
|
||||
autocomplete_container: this.autocompleteContainerRef,
|
||||
};
|
||||
}
|
||||
computeActiveActions(props) {
|
||||
this.state.activeActions = {
|
||||
create: props.canCreate,
|
||||
createEdit: props.canCreateEdit,
|
||||
write: props.canWrite,
|
||||
};
|
||||
}
|
||||
getDomain() {
|
||||
return this.domain.toList(this.context);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user