Issue
- Install "Accounting"
- Change user language to arabic
- Go to Customer Invoices list view
- Try to filter on field "Created On"
Traceback is raised from the DatePicker Component
Cause
The cause is two fold:
There is an issue in moment that behaves abnormally when its internals
are not able to extract the month in a locale, and, instead of returning an
invalid moment, it returns a valid moment with the month set to January
which just happens to be the first month of moment's default locale
ref: https://github.com/moment/moment/issues/5600
Secondly, the defaultProps "locale" of the DatePicker was set to moment.locale()
at the file's initial loading, that is, before any user locale parameters were loaded
The bootstrap datepicker was then set with the wrong locale, and the case fell under moment's issue
After this commit, the locale of the DatePicker is always the one of the user, and there is no traceback
opw-2460156
closes odoo/odoo#68059
X-original-commit: e2c46bb80e1e312dd34ac554d79813ef35282e62
Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
Signed-off-by: bon-odoo <nboulif@users.noreply.github.com>
Co-authored-by: Lucas Perais <lpe@odoo.com>
351 lines
16 KiB
JavaScript
351 lines
16 KiB
JavaScript
odoo.define('web.datepicker_tests', function (require) {
|
|
"use strict";
|
|
|
|
const { DatePicker, DateTimePicker } = require('web.DatePickerOwl');
|
|
const testUtils = require('web.test_utils');
|
|
const time = require('web.time');
|
|
|
|
const { createComponent } = testUtils;
|
|
|
|
QUnit.module('Components', {}, function () {
|
|
|
|
QUnit.module('DatePicker');
|
|
|
|
QUnit.test("basic rendering", async function (assert) {
|
|
assert.expect(8);
|
|
|
|
const picker = await createComponent(DatePicker, {
|
|
props: { date: moment('01/09/1997') },
|
|
});
|
|
|
|
assert.containsOnce(picker, 'input.o_input.o_datepicker_input');
|
|
assert.containsOnce(picker, 'span.o_datepicker_button');
|
|
assert.containsNone(document.body, 'div.bootstrap-datetimepicker-widget');
|
|
|
|
const input = picker.el.querySelector('input.o_input.o_datepicker_input');
|
|
assert.strictEqual(input.value, '01/09/1997',
|
|
"Value should be the one given")
|
|
;
|
|
assert.strictEqual(input.dataset.target, `#${picker.el.id}`,
|
|
"DatePicker id should match its input target");
|
|
|
|
await testUtils.dom.click(input);
|
|
|
|
assert.containsOnce(document.body, 'div.bootstrap-datetimepicker-widget .datepicker');
|
|
assert.containsNone(document.body, 'div.bootstrap-datetimepicker-widget .timepicker');
|
|
assert.strictEqual(
|
|
document.querySelector('.datepicker .day.active').dataset.day,
|
|
'01/09/1997',
|
|
"Datepicker should have set the correct day"
|
|
);
|
|
|
|
picker.destroy();
|
|
});
|
|
|
|
QUnit.test("pick a date", async function (assert) {
|
|
assert.expect(5);
|
|
|
|
const picker = await createComponent(DatePicker, {
|
|
props: { date: moment('01/09/1997') },
|
|
intercepts: {
|
|
'datetime-changed': ev => {
|
|
assert.step('datetime-changed');
|
|
assert.strictEqual(ev.detail.date.format('MM/DD/YYYY'), '02/08/1997',
|
|
"Event should transmit the correct date");
|
|
},
|
|
}
|
|
});
|
|
const input = picker.el.querySelector('.o_datepicker_input');
|
|
|
|
await testUtils.dom.click(input);
|
|
await testUtils.dom.click(document.querySelector('.datepicker th.next')); // next month
|
|
|
|
assert.verifySteps([]);
|
|
|
|
await testUtils.dom.click(document.querySelectorAll('.datepicker table td')[15]); // previous day
|
|
|
|
assert.strictEqual(input.value, '02/08/1997');
|
|
assert.verifySteps(['datetime-changed']);
|
|
|
|
picker.destroy();
|
|
});
|
|
|
|
QUnit.test("pick a date with locale", async function (assert) {
|
|
assert.expect(4);
|
|
|
|
// weird shit of moment https://github.com/moment/moment/issues/5600
|
|
// When month regex returns undefined, january is taken (first month of the default "nameless" locale)
|
|
const originalLocale = moment.locale();
|
|
// Those parameters will make Moment's internal compute stuff that are relevant to the bug
|
|
const months = 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_');
|
|
const monthsShort = 'janv._févr._mars_avr._mai_juin_juil._août_custSept._oct._nov._déc.'.split('_');
|
|
moment.defineLocale('frenchForTests', { months, monthsShort, code: 'frTest' , monthsParseExact: true});
|
|
|
|
const hasChanged = testUtils.makeTestPromise();
|
|
const picker = await createComponent(DatePicker, {
|
|
translateParameters: {
|
|
date_format: "%d %b, %Y", // Those are important too
|
|
time_format: "%H:%M:%S",
|
|
},
|
|
props: { date: moment('09/01/1997', 'MM/DD/YYYY') },
|
|
intercepts: {
|
|
'datetime-changed': ev => {
|
|
assert.step('datetime-changed');
|
|
assert.strictEqual(ev.detail.date.format('MM/DD/YYYY'), '09/02/1997',
|
|
"Event should transmit the correct date");
|
|
hasChanged.resolve();
|
|
},
|
|
}
|
|
});
|
|
const input = picker.el.querySelector('.o_datepicker_input');
|
|
await testUtils.dom.click(input);
|
|
|
|
await testUtils.dom.click(document.querySelectorAll('.datepicker table td')[3]); // next day
|
|
|
|
assert.strictEqual(input.value, '02 custSept., 1997');
|
|
assert.verifySteps(['datetime-changed']);
|
|
|
|
moment.locale(originalLocale);
|
|
moment.updateLocale('englishForTest', null);
|
|
|
|
picker.destroy();
|
|
});
|
|
|
|
QUnit.test("enter a date value", async function (assert) {
|
|
assert.expect(5);
|
|
|
|
const picker = await createComponent(DatePicker, {
|
|
props: { date: moment('01/09/1997') },
|
|
intercepts: {
|
|
'datetime-changed': ev => {
|
|
assert.step('datetime-changed');
|
|
assert.strictEqual(ev.detail.date.format('MM/DD/YYYY'), '02/08/1997',
|
|
"Event should transmit the correct date");
|
|
},
|
|
}
|
|
});
|
|
const input = picker.el.querySelector('.o_datepicker_input');
|
|
|
|
assert.verifySteps([]);
|
|
|
|
await testUtils.fields.editAndTrigger(input, '02/08/1997', ['change']);
|
|
|
|
assert.verifySteps(['datetime-changed']);
|
|
|
|
await testUtils.dom.click(input);
|
|
|
|
assert.strictEqual(
|
|
document.querySelector('.datepicker .day.active').dataset.day,
|
|
'02/08/1997',
|
|
"Datepicker should have set the correct day"
|
|
);
|
|
|
|
picker.destroy();
|
|
});
|
|
|
|
QUnit.test("Date format is correctly set", async function (assert) {
|
|
assert.expect(2);
|
|
|
|
testUtils.patch(time, { getLangDateFormat: () => "YYYY/MM/DD" });
|
|
const picker = await createComponent(DatePicker, {
|
|
props: { date: moment('01/09/1997') },
|
|
});
|
|
const input = picker.el.querySelector('.o_datepicker_input');
|
|
|
|
assert.strictEqual(input.value, '1997/01/09');
|
|
|
|
// Forces an update to assert that the registered format is the correct one
|
|
await testUtils.dom.click(input);
|
|
|
|
assert.strictEqual(input.value, '1997/01/09');
|
|
|
|
picker.destroy();
|
|
testUtils.unpatch(time);
|
|
});
|
|
|
|
QUnit.module('DateTimePicker');
|
|
|
|
QUnit.test("basic rendering", async function (assert) {
|
|
assert.expect(11);
|
|
|
|
const picker = await createComponent(DateTimePicker, {
|
|
props: { date: moment('01/09/1997 12:30:01') },
|
|
});
|
|
|
|
assert.containsOnce(picker, 'input.o_input.o_datepicker_input');
|
|
assert.containsOnce(picker, 'span.o_datepicker_button');
|
|
assert.containsNone(document.body, 'div.bootstrap-datetimepicker-widget');
|
|
|
|
const input = picker.el.querySelector('input.o_input.o_datepicker_input');
|
|
assert.strictEqual(input.value, '01/09/1997 12:30:01', "Value should be the one given");
|
|
assert.strictEqual(input.dataset.target, `#${picker.el.id}`,
|
|
"DateTimePicker id should match its input target");
|
|
|
|
await testUtils.dom.click(input);
|
|
|
|
assert.containsOnce(document.body, 'div.bootstrap-datetimepicker-widget .datepicker');
|
|
assert.containsOnce(document.body, 'div.bootstrap-datetimepicker-widget .timepicker');
|
|
assert.strictEqual(
|
|
document.querySelector('.datepicker .day.active').dataset.day,
|
|
'01/09/1997',
|
|
"Datepicker should have set the correct day");
|
|
|
|
assert.strictEqual(document.querySelector('.timepicker .timepicker-hour').innerText.trim(), '12',
|
|
"Datepicker should have set the correct hour");
|
|
assert.strictEqual(document.querySelector('.timepicker .timepicker-minute').innerText.trim(), '30',
|
|
"Datepicker should have set the correct minute");
|
|
assert.strictEqual(document.querySelector('.timepicker .timepicker-second').innerText.trim(), '01',
|
|
"Datepicker should have set the correct second");
|
|
|
|
picker.destroy();
|
|
});
|
|
|
|
QUnit.test("pick a date and time", async function (assert) {
|
|
assert.expect(5);
|
|
|
|
const picker = await createComponent(DateTimePicker, {
|
|
props: { date: moment('01/09/1997 12:30:01') },
|
|
intercepts: {
|
|
'datetime-changed': ev => {
|
|
assert.step('datetime-changed');
|
|
assert.strictEqual(ev.detail.date.format('MM/DD/YYYY HH:mm:ss'), '02/08/1997 15:45:05',
|
|
"Event should transmit the correct date");
|
|
},
|
|
}
|
|
});
|
|
const input = picker.el.querySelector('input.o_input.o_datepicker_input');
|
|
|
|
await testUtils.dom.click(input);
|
|
await testUtils.dom.click(document.querySelector('.datepicker th.next')); // February
|
|
await testUtils.dom.click(document.querySelectorAll('.datepicker table td')[15]); // 08
|
|
await testUtils.dom.click(document.querySelector('a[title="Select Time"]'));
|
|
await testUtils.dom.click(document.querySelector('.timepicker .timepicker-hour'));
|
|
await testUtils.dom.click(document.querySelectorAll('.timepicker .hour')[15]); // 15h
|
|
await testUtils.dom.click(document.querySelector('.timepicker .timepicker-minute'));
|
|
await testUtils.dom.click(document.querySelectorAll('.timepicker .minute')[9]); // 45m
|
|
await testUtils.dom.click(document.querySelector('.timepicker .timepicker-second'));
|
|
|
|
assert.verifySteps([]);
|
|
|
|
await testUtils.dom.click(document.querySelectorAll('.timepicker .second')[1]); // 05s
|
|
|
|
assert.strictEqual(input.value, '02/08/1997 15:45:05');
|
|
assert.verifySteps(['datetime-changed']);
|
|
|
|
picker.destroy();
|
|
});
|
|
|
|
QUnit.test("pick a date and time with locale", async function (assert) {
|
|
assert.expect(5);
|
|
|
|
// weird shit of moment https://github.com/moment/moment/issues/5600
|
|
// When month regex returns undefined, january is taken (first month of the default "nameless" locale)
|
|
const originalLocale = moment.locale();
|
|
// Those parameters will make Moment's internal compute stuff that are relevant to the bug
|
|
const months = 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_');
|
|
const monthsShort = 'janv._févr._mars_avr._mai_juin_juil._août_custSept._oct._nov._déc.'.split('_');
|
|
moment.defineLocale('frenchForTests', { months, monthsShort, code: 'frTest' , monthsParseExact: true});
|
|
|
|
const hasChanged = testUtils.makeTestPromise();
|
|
const picker = await createComponent(DateTimePicker, {
|
|
translateParameters: {
|
|
date_format: "%d %b, %Y", // Those are important too
|
|
time_format: "%H:%M:%S",
|
|
},
|
|
props: { date: moment('09/01/1997 12:30:01', 'MM/DD/YYYY HH:mm:ss') },
|
|
intercepts: {
|
|
'datetime-changed': ev => {
|
|
assert.step('datetime-changed');
|
|
assert.strictEqual(ev.detail.date.format('MM/DD/YYYY HH:mm:ss'), '09/02/1997 15:45:05',
|
|
"Event should transmit the correct date");
|
|
hasChanged.resolve();
|
|
},
|
|
}
|
|
});
|
|
|
|
const input = picker.el.querySelector('input.o_input.o_datepicker_input');
|
|
|
|
await testUtils.dom.click(input);
|
|
await testUtils.dom.click(document.querySelectorAll('.datepicker table td')[3]); // next day
|
|
await testUtils.dom.click(document.querySelector('a[title="Select Time"]'));
|
|
await testUtils.dom.click(document.querySelector('.timepicker .timepicker-hour'));
|
|
await testUtils.dom.click(document.querySelectorAll('.timepicker .hour')[15]); // 15h
|
|
await testUtils.dom.click(document.querySelector('.timepicker .timepicker-minute'));
|
|
await testUtils.dom.click(document.querySelectorAll('.timepicker .minute')[9]); // 45m
|
|
await testUtils.dom.click(document.querySelector('.timepicker .timepicker-second'));
|
|
|
|
assert.verifySteps([]);
|
|
await testUtils.dom.click(document.querySelectorAll('.timepicker .second')[1]); // 05s
|
|
|
|
assert.strictEqual(input.value, '02 custSept., 1997 15:45:05');
|
|
assert.verifySteps(['datetime-changed']);
|
|
|
|
await hasChanged;
|
|
|
|
moment.locale(originalLocale);
|
|
moment.updateLocale('frenchForTests', null);
|
|
|
|
picker.destroy();
|
|
});
|
|
|
|
QUnit.test("enter a datetime value", async function (assert) {
|
|
assert.expect(9);
|
|
|
|
const picker = await createComponent(DateTimePicker, {
|
|
props: { date: moment('01/09/1997 12:30:01') },
|
|
intercepts: {
|
|
'datetime-changed': ev => {
|
|
assert.step('datetime-changed');
|
|
assert.strictEqual(ev.detail.date.format('MM/DD/YYYY HH:mm:ss'), '02/08/1997 15:45:05',
|
|
"Event should transmit the correct date");
|
|
},
|
|
}
|
|
});
|
|
const input = picker.el.querySelector('.o_datepicker_input');
|
|
|
|
assert.verifySteps([]);
|
|
|
|
await testUtils.fields.editAndTrigger(input, '02/08/1997 15:45:05', ['change']);
|
|
|
|
assert.verifySteps(['datetime-changed']);
|
|
|
|
await testUtils.dom.click(input);
|
|
|
|
assert.strictEqual(input.value, '02/08/1997 15:45:05');
|
|
assert.strictEqual(
|
|
document.querySelector('.datepicker .day.active').dataset.day,
|
|
'02/08/1997',
|
|
"Datepicker should have set the correct day"
|
|
);
|
|
assert.strictEqual(document.querySelector('.timepicker .timepicker-hour').innerText.trim(), '15',
|
|
"Datepicker should have set the correct hour");
|
|
assert.strictEqual(document.querySelector('.timepicker .timepicker-minute').innerText.trim(), '45',
|
|
"Datepicker should have set the correct minute");
|
|
assert.strictEqual(document.querySelector('.timepicker .timepicker-second').innerText.trim(), '05',
|
|
"Datepicker should have set the correct second");
|
|
|
|
picker.destroy();
|
|
});
|
|
|
|
QUnit.test("Date time format is correctly set", async function (assert) {
|
|
assert.expect(2);
|
|
|
|
testUtils.patch(time, { getLangDatetimeFormat: () => "hh:mm:ss YYYY/MM/DD" });
|
|
const picker = await createComponent(DateTimePicker, {
|
|
props: { date: moment('01/09/1997 12:30:01') },
|
|
});
|
|
const input = picker.el.querySelector('.o_datepicker_input');
|
|
|
|
assert.strictEqual(input.value, '12:30:01 1997/01/09');
|
|
|
|
// Forces an update to assert that the registered format is the correct one
|
|
await testUtils.dom.click(input);
|
|
|
|
assert.strictEqual(input.value, '12:30:01 1997/01/09');
|
|
|
|
picker.destroy();
|
|
testUtils.unpatch(time);
|
|
});
|
|
});
|
|
});
|