[IMP] web: improve eval context dates

This commit handles 2 things:

1) the merging of the `py_utils.context()` into the evaluation context
returned by `BasicModel._getEvalContext` to access the same time-related
keys,

2) the addition of 2 new keys into the `py_utils.context` (thus
transmitted to the basic model): `today` (an alias for the already
present `current_date`) and `now` which represents the current date and
time value.

Task 2269697
This commit is contained in:
Julien Mougenot
2020-07-14 09:10:32 +00:00
parent b9ad60d5eb
commit 669c2ebaec
5 changed files with 155 additions and 20 deletions
@@ -2037,8 +2037,9 @@ odoo.define('web.basic_model_tests', function (require) {
});
QUnit.test('has a proper evaluation context', async function (assert) {
assert.expect(1);
assert.expect(6);
const unpatchDate = testUtils.mock.patchDate(1997, 0, 9, 12, 0, 0);
this.params.fieldNames = Object.keys(this.data.partner.fields);
this.params.res_id = 1;
@@ -2048,8 +2049,24 @@ odoo.define('web.basic_model_tests', function (require) {
});
var resultID = await model.load(this.params);
var record = model.get(resultID);
assert.deepEqual(record.evalContext, {
const { evalContext } = model.get(resultID);
assert.strictEqual(typeof evalContext.datetime, "object");
assert.strictEqual(typeof evalContext.relativedelta, "object");
assert.strictEqual(typeof evalContext.time, "object");
assert.strictEqual(typeof evalContext.context_today, "function");
assert.strictEqual(typeof evalContext.tz_offset, "function");
const blackListedKeys = [
"time",
"datetime",
"relativedelta",
"context_today",
"tz_offset",
];
// Remove uncomparable values from the evaluation context
for (const key of blackListedKeys) {
delete evalContext[key];
}
assert.deepEqual(evalContext, {
active: true,
active_id: 1,
active_ids: [1],
@@ -2058,6 +2075,8 @@ odoo.define('web.basic_model_tests', function (require) {
category: [12],
current_company_id: false,
current_date: moment().format('YYYY-MM-DD'),
today: moment().format('YYYY-MM-DD'),
now: moment().utc().format('YYYY-MM-DD HH:mm:ss'),
date: "2017-01-25",
display_name: "first partner",
foo: "blip",
@@ -2070,6 +2089,7 @@ odoo.define('web.basic_model_tests', function (require) {
x_active: true,
}, "should use the proper eval context");
model.destroy();
unpatchDate();
});
QUnit.test('x2manys in contexts and domains are correctly evaluated', async function (assert) {
@@ -10320,6 +10320,95 @@ QUnit.module('Views', {
list.destroy();
});
QUnit.test("Date in evaluation context works with date field", async function (assert) {
assert.expect(11);
const dateRegex = /^\d{4}-\d{2}-\d{2}$/;
const unpatchDate = testUtils.mock.patchDate(1997, 0, 9, 12, 0, 0);
testUtils.mock.patch(BasicModel, {
_getEvalContext() {
const evalContext = this._super(...arguments);
assert.ok(dateRegex.test(evalContext.today));
assert.strictEqual(evalContext.current_date, evalContext.today);
return evalContext;
},
});
this.data.foo.fields.birthday = { string: "Birthday", type: 'date' };
this.data.foo.records[0].birthday = "1997-01-08";
this.data.foo.records[1].birthday = "1997-01-09";
this.data.foo.records[2].birthday = "1997-01-10";
const list = await createView({
arch: `
<tree>
<field name="birthday" decoration-danger="birthday > today"/>
</tree>`,
data: this.data,
model: 'foo',
View: ListView,
});
assert.containsOnce(list, ".o_data_row .text-danger");
list.destroy();
unpatchDate();
testUtils.mock.unpatch(BasicModel);
});
QUnit.test("Datetime in evaluation context works with datetime field", async function (assert) {
assert.expect(6);
const datetimeRegex = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/;
const unpatchDate = testUtils.mock.patchDate(1997, 0, 9, 12, 0, 0);
testUtils.mock.patch(BasicModel, {
_getEvalContext() {
const evalContext = this._super(...arguments);
assert.ok(datetimeRegex.test(evalContext.now));
return evalContext;
},
});
/**
* Returns "1997-01-DD HH:MM:00" with D, H and M holding current UTC values
* from patched date + (deltaMinutes) minutes.
* This is done to allow testing from any timezone since UTC values are
* calculated with the offset of the current browser.
*/
function dateStringDelta(deltaMinutes) {
const d = new Date(Date.now() + 1000 * 60 * deltaMinutes);
return `1997-01-${
String(d.getUTCDate()).padStart(2, '0')
} ${
String(d.getUTCHours()).padStart(2, '0')
}:${
String(d.getUTCMinutes()).padStart(2, '0')
}:00`;
}
// "datetime" field may collide with "datetime" object in context
this.data.foo.fields.birthday = { string: "Birthday", type: 'datetime' };
this.data.foo.records[0].birthday = dateStringDelta(-30);
this.data.foo.records[1].birthday = dateStringDelta(0);
this.data.foo.records[2].birthday = dateStringDelta(+30);
const list = await createView({
arch: `
<tree>
<field name="birthday" decoration-danger="birthday > now"/>
</tree>`,
data: this.data,
model: 'foo',
View: ListView,
});
assert.containsOnce(list, ".o_data_row .text-danger");
list.destroy();
unpatchDate();
testUtils.mock.unpatch(BasicModel);
});
});
});