Files
odoo_source/addons/web/static/tests/fields/field_utils_tests.js
T
Michael Mattiello (mcm) a5cca2cda3 [IMP] web: add smart date input on date field
This commit adds smart date inputs for date and datetime fields.

The goal of smart date input is to provide the user some shortcuts
when setting dates.

The rule is [+-]\d+[dwmy]?
So we can enter inputs like:
  +3  to have today + 3 days
  -2w to have today - 2 weeks
  +1y to have today + 1 year
  +5m to have today + 5 months
  -4d to have today - 4 days

closes odoo/odoo#55602

Task: 2270347
Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
2020-08-11 14:15:43 +00:00

435 lines
17 KiB
JavaScript

odoo.define('web.field_utils_tests', function (require) {
"use strict";
var core = require('web.core');
var session = require('web.session');
var fieldUtils = require('web.field_utils');
QUnit.module('fields', {}, function () {
QUnit.module('field_utils');
QUnit.test('format integer', function(assert) {
assert.expect(5);
var originalGrouping = core._t.database.parameters.grouping;
core._t.database.parameters.grouping = [3, 3, 3, 3];
assert.strictEqual(fieldUtils.format.integer(1000000), '1,000,000');
core._t.database.parameters.grouping = [3, 2, -1];
assert.strictEqual(fieldUtils.format.integer(106500), '1,06,500');
core._t.database.parameters.grouping = [1, 2, -1];
assert.strictEqual(fieldUtils.format.integer(106500), '106,50,0');
assert.strictEqual(fieldUtils.format.integer(0), "0");
assert.strictEqual(fieldUtils.format.integer(false), "");
core._t.database.parameters.grouping = originalGrouping;
});
QUnit.test('format float', function(assert) {
assert.expect(5);
var originalParameters = $.extend(true, {}, core._t.database.parameters);
core._t.database.parameters.grouping = [3, 3, 3, 3];
assert.strictEqual(fieldUtils.format.float(1000000), '1,000,000.00');
core._t.database.parameters.grouping = [3, 2, -1];
assert.strictEqual(fieldUtils.format.float(106500), '1,06,500.00');
core._t.database.parameters.grouping = [1, 2, -1];
assert.strictEqual(fieldUtils.format.float(106500), '106,50,0.00');
_.extend(core._t.database.parameters, {
grouping: [3, 0],
decimal_point: ',',
thousands_sep: '.'
});
assert.strictEqual(fieldUtils.format.float(6000), '6.000,00');
assert.strictEqual(fieldUtils.format.float(false), '');
core._t.database.parameters = originalParameters;
});
QUnit.test("format_datetime", function (assert) {
assert.expect(1);
var date_string = "2009-05-04 12:34:23";
var date = fieldUtils.parse.datetime(date_string, {}, {timezone: false});
var str = fieldUtils.format.datetime(date, {}, {timezone: false});
assert.strictEqual(str, moment(date).format("MM/DD/YYYY HH:mm:ss"));
});
QUnit.test("format_datetime (with different timezone offset)", function (assert) {
assert.expect(2);
// mock the date format to avoid issues due to localisation
var dateFormat = core._t.database.parameters.date_format;
core._t.database.parameters.date_format = '%m/%d/%Y';
session.getTZOffset = function (date) {
// simulate daylight saving time
var startDate = new Date(2017, 2, 26);
var endDate = new Date(2017, 9, 29);
if (startDate < date && date < endDate) {
return 120; // UTC+2
} else {
return 60; // UTC+1
}
};
var str = fieldUtils.format.datetime(moment.utc('2017-01-01T10:00:00Z'));
assert.strictEqual(str, '01/01/2017 11:00:00');
str = fieldUtils.format.datetime(moment.utc('2017-06-01T10:00:00Z'));
assert.strictEqual(str, '06/01/2017 12:00:00');
core._t.database.parameters.date_format = dateFormat;
});
QUnit.test("format_many2one", function (assert) {
assert.expect(2);
assert.strictEqual('', fieldUtils.format.many2one(null));
assert.strictEqual('A M2O value', fieldUtils.format.many2one({
data: { display_name: 'A M2O value' },
}));
});
QUnit.test('format monetary', function(assert) {
assert.expect(1);
assert.strictEqual(fieldUtils.format.monetary(false), '');
});
QUnit.test('format char', function(assert) {
assert.expect(1);
assert.strictEqual(fieldUtils.format.char(), '',
"undefined char should be formatted as an empty string");
});
QUnit.test('format many2many', function(assert) {
assert.expect(3);
assert.strictEqual(fieldUtils.format.many2many({data: []}), 'No records');
assert.strictEqual(fieldUtils.format.many2many({data: [1]}), '1 record');
assert.strictEqual(fieldUtils.format.many2many({data: [1, 2]}), '2 records');
});
QUnit.test('format one2many', function(assert) {
assert.expect(3);
assert.strictEqual(fieldUtils.format.one2many({data: []}), 'No records');
assert.strictEqual(fieldUtils.format.one2many({data: [1]}), '1 record');
assert.strictEqual(fieldUtils.format.one2many({data: [1, 2]}), '2 records');
});
QUnit.test('format binary', function (assert) {
assert.expect(1);
// base64 estimated size (bytes) = value.length / 1.37 (http://en.wikipedia.org/wiki/Base64#MIME)
// Here: 4 / 1.37 = 2.91970800 => 2.92 (rounded 2 decimals by utils.human_size)
assert.strictEqual(fieldUtils.format.binary('Cg=='), '2.92 Bytes');
});
QUnit.test('format percentage', function (assert) {
assert.expect(12);
var originalParameters = _.clone(core._t.database.parameters);
assert.strictEqual(fieldUtils.format.percentage(0), '0%');
assert.strictEqual(fieldUtils.format.percentage(0.5), '50%');
assert.strictEqual(fieldUtils.format.percentage(1), '100%');
assert.strictEqual(fieldUtils.format.percentage(-0.2), '-20%');
assert.strictEqual(fieldUtils.format.percentage(2.5), '250%');
assert.strictEqual(fieldUtils.format.percentage(0.125), '12.5%');
assert.strictEqual(fieldUtils.format.percentage(0.666666), '66.67%');
assert.strictEqual(fieldUtils.format.percentage(false), '0%');
assert.strictEqual(fieldUtils.format.percentage(50, null,
{humanReadable: function (val) {return true;}}), '5k%'
);
_.extend(core._t.database.parameters, {
grouping: [3, 0],
decimal_point: ',',
thousands_sep: '.'
});
assert.strictEqual(fieldUtils.format.percentage(0.125), '12,5%');
assert.strictEqual(fieldUtils.format.percentage(0.666666), '66,67%');
assert.strictEqual(fieldUtils.format.percentage(0.5, null, { noSymbol: true }), '50');
core._t.database.parameters = originalParameters;
});
QUnit.test('format float time', function (assert) {
assert.expect(7);
assert.strictEqual(fieldUtils.format.float_time(2), '02:00');
assert.strictEqual(fieldUtils.format.float_time(3.5), '03:30');
assert.strictEqual(fieldUtils.format.float_time(0.25), '00:15');
assert.strictEqual(fieldUtils.format.float_time(-0.5), '-00:30');
const options = {
noLeadingZeroHour: true,
};
assert.strictEqual(fieldUtils.format.float_time(2, null, options), '2:00');
assert.strictEqual(fieldUtils.format.float_time(3.5, null, options), '3:30');
assert.strictEqual(fieldUtils.format.float_time(-0.5, null, options), '-0:30');
});
QUnit.test('parse float', function(assert) {
assert.expect(10);
var originalParameters = _.clone(core._t.database.parameters);
_.extend(core._t.database.parameters, {
grouping: [3, 0],
decimal_point: '.',
thousands_sep: ','
});
assert.strictEqual(fieldUtils.parse.float(""), 0);
assert.strictEqual(fieldUtils.parse.float("0"), 0);
assert.strictEqual(fieldUtils.parse.float("100.00"), 100);
assert.strictEqual(fieldUtils.parse.float("-100.00"), -100);
assert.strictEqual(fieldUtils.parse.float("1,000.00"), 1000);
assert.strictEqual(fieldUtils.parse.float("1,000,000.00"), 1000000);
assert.strictEqual(fieldUtils.parse.float('1,234.567'), 1234.567);
assert.throws(function () {
fieldUtils.parse.float("1.000.000");
}, "Throw an exception if it's not a valid number");
_.extend(core._t.database.parameters, {
grouping: [3, 0],
decimal_point: ',',
thousands_sep: '.'
});
assert.strictEqual(fieldUtils.parse.float('1.234,567'), 1234.567);
assert.throws(function () {
fieldUtils.parse.float("1,000,000");
}, "Throw an exception if it's not a valid number");
_.extend(core._t.database.parameters, originalParameters);
});
QUnit.test('parse integer', function(assert) {
assert.expect(11);
var originalParameters = _.clone(core._t.database.parameters);
_.extend(core._t.database.parameters, {
grouping: [3, 0],
decimal_point: '.',
thousands_sep: ','
});
assert.strictEqual(fieldUtils.parse.integer(""), 0);
assert.strictEqual(fieldUtils.parse.integer("0"), 0);
assert.strictEqual(fieldUtils.parse.integer("100"), 100);
assert.strictEqual(fieldUtils.parse.integer("-100"), -100);
assert.strictEqual(fieldUtils.parse.integer("1,000"), 1000);
assert.strictEqual(fieldUtils.parse.integer("1,000,000"), 1000000);
assert.throws(function () {
fieldUtils.parse.integer("1.000.000");
}, "Throw an exception if it's not a valid number");
assert.throws(function () {
fieldUtils.parse.integer("1,234.567");
}, "Throw an exception if the number is a float");
_.extend(core._t.database.parameters, {
grouping: [3, 0],
decimal_point: ',',
thousands_sep: '.'
});
assert.strictEqual(fieldUtils.parse.integer("1.000.000"), 1000000);
assert.throws(function () {
fieldUtils.parse.integer("1,000,000");
}, "Throw an exception if it's not a valid number");
assert.throws(function () {
fieldUtils.parse.integer("1.234,567");
}, "Throw an exception if the number is a float");
_.extend(core._t.database.parameters, originalParameters);
});
QUnit.test('parse monetary', function(assert) {
assert.expect(11);
var originalCurrencies = session.currencies;
session.currencies = {
1: {
digits: [69, 2],
position: "after",
symbol: "€"
},
3: {
digits: [69, 2],
position: "before",
symbol: "$"
}
};
assert.strictEqual(fieldUtils.parse.monetary(""), 0);
assert.strictEqual(fieldUtils.parse.monetary("0"), 0);
assert.strictEqual(fieldUtils.parse.monetary("100.00"), 100);
assert.strictEqual(fieldUtils.parse.monetary("-100.00"), -100);
assert.strictEqual(fieldUtils.parse.monetary("1,000.00"), 1000);
assert.strictEqual(fieldUtils.parse.monetary("1,000,000.00"), 1000000);
assert.strictEqual(fieldUtils.parse.monetary("$&nbsp;125.00", {}, {currency_id: 3}), 125);
assert.strictEqual(fieldUtils.parse.monetary("1,000.00&nbsp;€", {}, {currency_id: 1}), 1000);
assert.throws(function() {fieldUtils.parse.monetary("$ 12.00", {}, {currency_id: 3})}, /is not a correct/);
assert.throws(function() {fieldUtils.parse.monetary("$&nbsp;12.00", {}, {currency_id: 1})}, /is not a correct/);
assert.throws(function() {fieldUtils.parse.monetary("$&nbsp;12.00&nbsp;34", {}, {currency_id: 3})}, /is not a correct/);
session.currencies = originalCurrencies;
});
QUnit.test('parse percentage', function(assert) {
assert.expect(7);
var originalParameters = _.clone(core._t.database.parameters);
assert.strictEqual(fieldUtils.parse.percentage(""), 0);
assert.strictEqual(fieldUtils.parse.percentage("0"), 0);
assert.strictEqual(fieldUtils.parse.percentage("0.5"), 0.005);
assert.strictEqual(fieldUtils.parse.percentage("1"), 0.01);
assert.strictEqual(fieldUtils.parse.percentage("100"), 1);
_.extend(core._t.database.parameters, {
grouping: [3, 0],
decimal_point: ',',
thousands_sep: '.'
});
assert.strictEqual(fieldUtils.parse.percentage("1.234,56"), 12.3456);
assert.strictEqual(fieldUtils.parse.percentage("6,02"), 0.0602);
core._t.database.parameters = originalParameters;
});
QUnit.test('parse datetime', function (assert) {
assert.expect(6);
var originalParameters = _.clone(core._t.database.parameters);
var originalLocale = moment.locale();
var dateStr, date1, date2;
moment.defineLocale('englishForTest', {
dayOfMonthOrdinalParse: /\d{1,2}(st|nd|rd|th)/,
ordinal: function (number) {
var b = number % 10,
output = (~~(number % 100 / 10) === 1) ? 'th' :
(b === 1) ? 'st' :
(b === 2) ? 'nd' :
(b === 3) ? 'rd' : 'th';
return number + output;
},
});
moment.defineLocale('norvegianForTest', {
monthsShort: 'jan._feb._mars_april_mai_juni_juli_aug._sep._okt._nov._des.'.split('_'),
monthsParseExact: true,
dayOfMonthOrdinalParse: /\d{1,2}\./,
ordinal: '%d.',
});
moment.locale('englishForTest');
_.extend(core._t.database.parameters, {date_format: '%m/%d/%Y', time_format: '%H:%M:%S'});
assert.throws(function () {
fieldUtils.parse.datetime("13/01/2019 12:00:00", {}, {});
}, /is not a correct/, "Wrongly formated dates should be invalid");
assert.throws(function () {
fieldUtils.parse.datetime("10000-01-01 12:00:00", {}, {});
}, /is not a correct/, "Dates after 9999 should be invalid");
dateStr = '01/13/2019 10:05:45';
date1 = fieldUtils.parse.datetime(dateStr);
date2 = moment.utc(dateStr, ['MM/DD/YYYY HH:mm:ss'], true);
assert.equal(date1.format(), date2.format(), "Date with leading 0");
dateStr = '1/14/2019 10:5:45';
date1 = fieldUtils.parse.datetime(dateStr);
date2 = moment.utc(dateStr, ['M/D/YYYY H:m:s'], true);
assert.equal(date1.format(), date2.format(), "Date without leading 0");
dateStr = '01/01/0001 10:15:45';
date1 = fieldUtils.parse.datetime(dateStr);
date2 = moment.utc(dateStr, ['MM/DD/YYYY HH:mm:ss'], true);
assert.equal(date1.format(), date2.format(), "can parse dates of year 1");
moment.locale('norvegianForTest');
_.extend(core._t.database.parameters, {date_format: '%d. %b %Y', time_format: '%H:%M:%S'});
dateStr = '16. jan. 2019 10:05:45';
date1 = fieldUtils.parse.datetime(dateStr);
date2 = moment.utc(dateStr, ['DD. MMM YYYY HH:mm:ss'], true);
assert.equal(date1.format(), date2.format(), "Day/month inverted + month i18n");
moment.locale(originalLocale);
moment.updateLocale("englishForTest", null);
moment.updateLocale("norvegianForTest", null);
core._t.database.parameters = originalParameters;
});
QUnit.test('parse date without separator', function (assert) {
assert.expect(8);
var originalParameters = _.clone(core._t.database.parameters);
_.extend(core._t.database.parameters, {date_format: '%d.%m/%Y'});
var dateFormat = "DD.MM/YYYY";
assert.throws(function () {fieldUtils.parse.date("1197")}, /is not a correct/, "Wrongly formated dates should be invalid");
assert.throws(function () {fieldUtils.parse.date("0131")}, /is not a correct/, "Wrongly formated dates should be invalid");
assert.throws(function () {fieldUtils.parse.date("970131")}, /is not a correct/, "Wrongly formated dates should be invalid");
assert.equal(fieldUtils.parse.date("3101").format(dateFormat), "31.01/" + moment.utc().year());
assert.equal(fieldUtils.parse.date("31.01").format(dateFormat), "31.01/" + moment.utc().year());
assert.equal(fieldUtils.parse.date("310197").format(dateFormat), "31.01/1997");
assert.equal(fieldUtils.parse.date("310117").format(dateFormat), "31.01/2017");
assert.equal(fieldUtils.parse.date("31011985").format(dateFormat), "31.01/1985");
core._t.database.parameters = originalParameters;
});
QUnit.test('parse datetime without separator', function (assert) {
assert.expect(3);
var originalParameters = _.clone(core._t.database.parameters);
_.extend(core._t.database.parameters, {date_format: '%d.%m/%Y', time_format: '%H:%M/%S'});
var dateTimeFormat = "DD.MM/YYYY HH:mm/ss";
assert.equal(fieldUtils.parse.datetime("3101198508").format(dateTimeFormat), "31.01/1985 08:00/00");
assert.equal(fieldUtils.parse.datetime("310119850833").format(dateTimeFormat), "31.01/1985 08:33/00");
assert.equal(fieldUtils.parse.datetime("31/01/1985 08").format(dateTimeFormat), "31.01/1985 08:00/00");
core._t.database.parameters = originalParameters;
});
});
QUnit.test('parse smart date input', function (assert) {
assert.expect(10);
const format = "DD MM YYYY";
assert.strictEqual(fieldUtils.parse.date("+1d").format(format), moment().add(1, 'days').format(format));
assert.strictEqual(fieldUtils.parse.datetime("+2w").format(format), moment().add(2, 'weeks').format(format));
assert.strictEqual(fieldUtils.parse.date("+3m").format(format), moment().add(3, 'months').format(format));
assert.strictEqual(fieldUtils.parse.datetime("+4y").format(format), moment().add(4, 'years').format(format));
assert.strictEqual(fieldUtils.parse.date("+5").format(format), moment().add(5, 'days').format(format));
assert.strictEqual(fieldUtils.parse.datetime("-5").format(format), moment().subtract(5, 'days').format(format));
assert.strictEqual(fieldUtils.parse.date("-4y").format(format), moment().subtract(4, 'years').format(format));
assert.strictEqual(fieldUtils.parse.datetime("-3m").format(format), moment().subtract(3, 'months').format(format));
assert.strictEqual(fieldUtils.parse.date("-2w").format(format), moment().subtract(2, 'weeks').format(format));
assert.strictEqual(fieldUtils.parse.datetime("-1d").format(format), moment().subtract(1, 'days').format(format));
});
});