From e310c08af179fefb9da5bcaa3be98bc1fd77506e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Monika=20Naw=C3=B3j?= Date: Wed, 24 May 2023 11:51:26 +0200 Subject: [PATCH] fix(LionInputDatePicker): remove endless loop on InvalidDate modelValue (#1984) * refactor: used IsDate validator instead of custom isValidDate function * fix: used IsDate validator to validate modelValue before it's passed to lion-calendar's selctedDate * test: Updated lion-input-datepicker tests to include example of handling invalid modelValue * docs: Updated docs to include example with invalid modelValue * refactor: updated returned type of __getSyncDownValue method * changset: updated changeset for @lion/ui * refactor: linting fix * refactor: import path updated Co-authored-by: gerjanvangeest * refactor: label added to Faulty prefilled datepicker input Co-authored-by: gerjanvangeest * test: updated test to include more obvious invalid date value --------- Co-authored-by: gerjanvangeest --- .changeset/nasty-dodos-fold.md | 5 +++++ docs/components/input-datepicker/use-cases.md | 11 ++++++++++ .../input-date/src/LionInputDate.js | 13 ++---------- .../src/LionInputDatepicker.js | 7 +++++-- .../test/lion-input-datepicker.test.js | 20 +++++++++++++++++++ 5 files changed, 43 insertions(+), 13 deletions(-) create mode 100644 .changeset/nasty-dodos-fold.md diff --git a/.changeset/nasty-dodos-fold.md b/.changeset/nasty-dodos-fold.md new file mode 100644 index 000000000..83ca0b14f --- /dev/null +++ b/.changeset/nasty-dodos-fold.md @@ -0,0 +1,5 @@ +--- +'@lion/ui': minor +--- + +fix: LionInputDatePicker enters an endless loop on InvalidDate modelValue diff --git a/docs/components/input-datepicker/use-cases.md b/docs/components/input-datepicker/use-cases.md index f968371ac..38b663e7d 100644 --- a/docs/components/input-datepicker/use-cases.md +++ b/docs/components/input-datepicker/use-cases.md @@ -76,3 +76,14 @@ export const readOnly = () => html` `; ``` + +## Faulty prefilled + +Faulty prefilled input will be cleared + +```js preview-story +export const faultyPrefilled = () => html` + + +`; +``` diff --git a/packages/ui/components/input-date/src/LionInputDate.js b/packages/ui/components/input-date/src/LionInputDate.js index 7ef8edb85..3191033c5 100644 --- a/packages/ui/components/input-date/src/LionInputDate.js +++ b/packages/ui/components/input-date/src/LionInputDate.js @@ -2,16 +2,6 @@ import { IsDate } from '@lion/ui/form-core.js'; import { LionInput } from '@lion/ui/input.js'; import { formatDate, LocalizeMixin, parseDate } from '@lion/ui/localize-no-side-effects.js'; -/** - * @param {Date|number} date - */ -function isValidDate(date) { - // to make sure it is a valid date we use isNaN and not Number.isNaN - // @ts-ignore [allow]: dirty hack, you're not supposed to pass Date instances to isNaN - // eslint-disable-next-line no-restricted-globals - return date instanceof Date && !isNaN(date); -} - /** * `LionInputDate` has a .modelValue of type Date. It parses, formats and validates based * on locale. @@ -51,7 +41,8 @@ export class LionInputDate extends LocalizeMixin(LionInput) { */ // eslint-disable-next-line class-methods-use-this serializer(modelValue) { - if (!isValidDate(modelValue)) { + const isDate = new IsDate(); + if (isDate.execute(modelValue)) { return ''; } // modelValue is localized, so we take the timezone offset in milliseconds and subtract it diff --git a/packages/ui/components/input-datepicker/src/LionInputDatepicker.js b/packages/ui/components/input-datepicker/src/LionInputDatepicker.js index 8598442d1..d32569d27 100644 --- a/packages/ui/components/input-datepicker/src/LionInputDatepicker.js +++ b/packages/ui/components/input-datepicker/src/LionInputDatepicker.js @@ -4,6 +4,7 @@ import { ScopedElementsMixin } from '@open-wc/scoped-elements'; import { html, css } from 'lit'; import { ifDefined } from 'lit/directives/if-defined.js'; import { LionInputDate } from '@lion/ui/input-date.js'; +import { IsDate } from '@lion/ui/form-core.js'; import { OverlayMixin, withBottomSheetConfig, @@ -373,10 +374,12 @@ export class LionInputDatepicker extends ScopedElementsMixin( * The LionCalendar shouldn't know anything about the modelValue; * it can't handle Unparseable dates, but does handle 'undefined' * @param {?} modelValue - * @returns {Date|undefined} a 'guarded' modelValue + * @returns {Date | undefined} a 'guarded' modelValue */ static __getSyncDownValue(modelValue) { - return modelValue instanceof Date ? modelValue : undefined; + const isDate = new IsDate(); + const hasError = isDate.execute(modelValue); + return hasError ? undefined : modelValue; } /** diff --git a/packages/ui/components/input-datepicker/test/lion-input-datepicker.test.js b/packages/ui/components/input-datepicker/test/lion-input-datepicker.test.js index 56060448f..f5be2b4f3 100644 --- a/packages/ui/components/input-datepicker/test/lion-input-datepicker.test.js +++ b/packages/ui/components/input-datepicker/test/lion-input-datepicker.test.js @@ -360,6 +360,26 @@ describe('', () => { expect(el.__calendarMaxDate.toString()).to.equal(new Date('2019/07/15').toString()); }); + it('should show error on invalid date passed to modelValue', async () => { + const myDate = new Date('foo'); + const el = await fixture(html` + + `); + expect(el.hasFeedbackFor).to.include('error'); + expect(el.validationStates).to.have.property('error'); + expect(el.validationStates.error).to.have.property('IsDate'); + }); + + it('should show error on date with invalid format passed to modelValue', async () => { + const myDate = new Date('30/01/2022'); + const el = await fixture(html` + + `); + expect(el.hasFeedbackFor).to.include('error'); + expect(el.validationStates).to.have.property('error'); + expect(el.validationStates.error).to.have.property('IsDate'); + }); + /** * Not in scope: * - min/max attr (like platform has): could be added in future if observers needed