diff --git a/addons/web/static/src/core/datepicker/datepicker.js b/addons/web/static/src/core/datepicker/datepicker.js index ba14e5fb0f0..9c0d9e4c455 100644 --- a/addons/web/static/src/core/datepicker/datepicker.js +++ b/addons/web/static/src/core/datepicker/datepicker.js @@ -189,7 +189,7 @@ export class DatePicker extends Component { }; for (const prop in params) { if (params[prop] instanceof DateTime) { - params[prop] = params[prop].isValid ? luxonToMoment(params[prop]) : null; + params[prop] = luxonToMoment(params[prop]); } } commandOrParams = params; diff --git a/addons/web/static/src/core/l10n/dates.js b/addons/web/static/src/core/l10n/dates.js index 8a252e3c1ad..12be603286e 100644 --- a/addons/web/static/src/core/l10n/dates.js +++ b/addons/web/static/src/core/l10n/dates.js @@ -174,9 +174,13 @@ export const luxonToMomentFormat = memoize(function luxonToMomentFormat(format) * @returns {moment} a moment.js object in the browser's timezone */ export function luxonToMoment(dt) { - const o = dt.toObject(); - // Note: the month is 0-based in moment.js, but 1-based in luxon.js - return moment({ ...o, month: o.month - 1 }); + if (dt.isValid) { + const o = dt.toObject(); + // Note: the month is 0-based in moment.js, but 1-based in luxon.js + return moment({ ...o, month: o.month - 1 }); + } else { + return moment.invalid(); + } } /** diff --git a/addons/web/static/tests/views/fields/domain_field_tests.js b/addons/web/static/tests/views/fields/domain_field_tests.js index a3d906ff86b..674c006f93f 100644 --- a/addons/web/static/tests/views/fields/domain_field_tests.js +++ b/addons/web/static/tests/views/fields/domain_field_tests.js @@ -3,6 +3,7 @@ import { makeView, setupViewRegistries } from "@web/../tests/views/helpers"; import { click, + clickDiscard, clickSave, editInput, getFixture, @@ -121,6 +122,49 @@ QUnit.module("Fields", (hooks) => { } ); + QUnit.test( + "The domain editor should not crash the view when given a dynamic filter ( datetime )", + async function (assert) { + // dynamic filters (containing variables, such as uid, parent or today) + // are not handled by the domain editor, but it shouldn't crash the view + serverData.models.partner.records[0].foo = `[("datetime", "=", context_today())]`; + serverData.models.partner.fields.datetime = { string: "A date", type: "datetime" }; + + await makeView({ + type: "form", + resModel: "partner", + resId: 1, + serverData, + arch: ` +
+ + `, + }); + + // The input field should display that the date is invalid + assert.equal(target.querySelector(".o_datepicker_input").value, "Invalid DateTime"); + + // Change the date in the datepicker + await click(target, ".o_datepicker_input"); + // Select a date in the datepicker + await click( + document.body.querySelector( + `.bootstrap-datetimepicker-widget :not(.today)[data-action="selectDay"]` + ) + ); + // Close the datepicker + await click( + document.body.querySelector( + `.bootstrap-datetimepicker-widget a[data-action="close"]` + ) + ); + await clickDiscard(target); + + // Open the datepicker again + await click(target, ".o_datepicker_input"); + } + ); + QUnit.test("basic domain field usage is ok", async function (assert) { serverData.models.partner.records[0].foo = "[]";