Files
odoo_source/addons/web/static/tests/components/datepicker_tests.js
T
Nasreddin (bon)andLucas Perais 9a1de0ef05 [FIX] web: compute default locale of Date(Time)Picker at the right time
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>
2021-03-18 09:51:06 +00:00

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);
});
});
});