diff --git a/.changeset/clever-parrots-sniff.md b/.changeset/clever-parrots-sniff.md new file mode 100644 index 000000000..802a9597e --- /dev/null +++ b/.changeset/clever-parrots-sniff.md @@ -0,0 +1,5 @@ +--- +'@lion/ui': patch +--- + +don't set unparseable for negative timezones diff --git a/packages/ui/components/input-amount/test/formatters.test.js b/packages/ui/components/input-amount/test/formatters.test.js index b46b4afab..feefc3f8b 100644 --- a/packages/ui/components/input-amount/test/formatters.test.js +++ b/packages/ui/components/input-amount/test/formatters.test.js @@ -1,10 +1,12 @@ import { expect } from '@open-wc/testing'; -import { localize } from '@lion/ui/localize.js'; +import { getLocalizeManager } from '@lion/ui/localize-no-side-effects.js'; import { localizeTearDown } from '@lion/ui/localize-test-helpers.js'; import { formatAmount } from '@lion/ui/input-amount.js'; describe('formatAmount()', () => { + const localizeManager = getLocalizeManager(); + afterEach(() => { localizeTearDown(); }); @@ -67,9 +69,9 @@ describe('formatAmount()', () => { }); it('fallbacks to global locale and EUR by default', async () => { - localize.locale = 'en-GB'; + localizeManager.locale = 'en-GB'; expect(formatAmount(12345678)).to.equal('12,345,678.00'); - localize.locale = 'nl-NL'; + localizeManager.locale = 'nl-NL'; expect(formatAmount(12345678)).to.equal('12.345.678,00'); }); }); diff --git a/packages/ui/components/input-date/test/lion-input-date.test.js b/packages/ui/components/input-date/test/lion-input-date.test.js index 035d138d0..0a4aeff72 100644 --- a/packages/ui/components/input-date/test/lion-input-date.test.js +++ b/packages/ui/components/input-date/test/lion-input-date.test.js @@ -1,7 +1,7 @@ import { html } from 'lit'; import { getLocalizeManager } from '@lion/ui/localize-no-side-effects.js'; import { localizeTearDown } from '@lion/ui/localize-test-helpers.js'; -import { MaxDate } from '@lion/ui/form-core.js'; +import { MinDate, MaxDate } from '@lion/ui/form-core.js'; import { expect, fixture as _fixture } from '@open-wc/testing'; import { getInputMembers } from '@lion/ui/input-test-helpers.js'; import '@lion/ui/define/lion-input-date.js'; @@ -67,49 +67,95 @@ describe('', () => { expect(el.validationStates.error).not.to.have.property('MaxDate'); }); - it('uses formatOptions.locale', async () => { - const el = await fixture(html` - - `); - expect(el.formattedValue).to.equal('15/06/2017'); + describe('locale', () => { + it('uses formatOptions.locale', async () => { + const el = await fixture(html` + + `); + expect(el.formattedValue).to.equal('15/06/2017'); - const el2 = await fixture(html` - - `); - expect(el2.formattedValue).to.equal('06/15/2017'); + const el2 = await fixture(html` + + `); + expect(el2.formattedValue).to.equal('06/15/2017'); + }); + + it('uses global locale when formatOptions.locale is not defined', async () => { + localizeManager.locale = 'fr-FR'; + const el = await fixture(html` + + `); + expect(el.formattedValue).to.equal('15/06/2017'); + + localizeManager.locale = 'en-US'; + const el2 = await fixture(html` + + `); + expect(el2.formattedValue).to.equal('06/15/2017'); + }); + + it('ignores global locale change if formatOptions.locale is provided', async () => { + const el = await fixture(html` + + `); + expect(el.formattedValue).to.equal('15/06/2017'); // british + localizeManager.locale = 'en-US'; + await el.updateComplete; + expect(el.formattedValue).to.equal('15/06/2017'); // should stay british + }); }); - it('uses global locale when formatOptions.locale is not defined', async () => { - localizeManager.locale = 'fr-FR'; - const el = await fixture(html` - - `); - expect(el.formattedValue).to.equal('15/06/2017'); + describe('timezones', async () => { + const dateAmsterdam = new Date( + new Date('2017/06/15').toLocaleString('en-US', { timeZone: 'Europe/Amsterdam' }), + ); + const dateManila = new Date( + new Date('2017/06/15').toLocaleString('en-US', { timeZone: 'Asia/Manila' }), + ); + const dateNewYork = new Date( + new Date('2017/06/15').toLocaleString('en-US', { timeZone: 'America/New_York' }), + ); - localizeManager.locale = 'en-US'; - const el2 = await fixture(html` - - `); - expect(el2.formattedValue).to.equal('06/15/2017'); - }); + it('works with different timezones', async () => { + const el = await fixture(html` + + `); + expect(el.formattedValue).to.equal('15/06/2017', 'Europe/Amsterdam'); - it('ignores global locale change if formatOptions.locale is provided', async () => { - const el = await fixture(html` - - `); - expect(el.formattedValue).to.equal('15/06/2017'); // british - localizeManager.locale = 'en-US'; - await el.updateComplete; - expect(el.formattedValue).to.equal('15/06/2017'); // should stay british + el.modelValue = dateManila; + expect(el.formattedValue).to.equal('15/06/2017', 'Asia/Manila'); + + el.modelValue = dateNewYork; + expect(el.formattedValue).to.equal('14/06/2017', 'America/New_York'); + }); + + it('validators work with different timezones', async () => { + const el = await fixture(html` + + `); + expect(el.formattedValue).to.equal('15/06/2017', 'Europe/Amsterdam'); + expect(el.hasFeedbackFor).not.to.include('error', 'Europe/Amsterdam'); + + el.modelValue = dateManila; + expect(el.formattedValue).to.equal('15/06/2017', 'Asia/Manila'); + expect(el.hasFeedbackFor).not.to.include('error', 'Asia/Manila'); + + el.modelValue = dateNewYork; + expect(el.formattedValue).to.equal('14/06/2017', 'America/New_York'); + expect(el.hasFeedbackFor).not.to.include('error', 'America/New_York'); + }); }); it('is accessible', async () => { diff --git a/packages/ui/components/localize/src/date/parseDate.js b/packages/ui/components/localize/src/date/parseDate.js index fb3a31dee..cd55735d3 100644 --- a/packages/ui/components/localize/src/date/parseDate.js +++ b/packages/ui/components/localize/src/date/parseDate.js @@ -58,7 +58,7 @@ export function parseDate(dateString) { } const [year, month, day] = parsedString.split('/').map(Number); - const parsedDate = new Date(Date.UTC(year, month - 1, day)); + const parsedDate = new Date(new Date(year, month - 1, day)); // Check if parsedDate is not `Invalid Date` or that the date has changed (e.g. the not existing 31.02.2020) if ( diff --git a/packages/ui/components/localize/test/date/parseDate.test.js b/packages/ui/components/localize/test/date/parseDate.test.js index f68385725..08a1edecd 100644 --- a/packages/ui/components/localize/test/date/parseDate.test.js +++ b/packages/ui/components/localize/test/date/parseDate.test.js @@ -5,13 +5,13 @@ import { localizeTearDown } from '@lion/ui/localize-test-helpers.js'; /** * * @param {Date | undefined} value - * @param {Date} date + * @param {Date | undefined} date */ function equalsDate(value, date) { return ( Object.prototype.toString.call(value) === '[object Date]' && // is Date Object value && - value.getDate() === date.getDate() && // day + value.getDate() === date?.getDate() && // day value.getMonth() === date.getMonth() && // month value.getFullYear() === date.getFullYear() // year ); @@ -52,6 +52,20 @@ describe('parseDate()', () => { expect(equalsDate(parseDate('12-31-1976'), new Date('1976/12/31'))).to.equal(true); }); + it('handles timezones of the browser and parsed date correctly', () => { + const referenceDate = new Date('2020/01/30'); + localizeManager.locale = 'nl-NL'; + const parsedDate = parseDate('30-01-2020'); + // time zone offset of parsed date: this value is dependent on the browser (basically where the ci or local machine it runs in is located) + const parseDateOffset = parsedDate?.getTimezoneOffset(); + // The parseDate time zone should be equal to the default offset of the browser + const browserTimeZoneOffset = referenceDate.getTimezoneOffset(); + // This will pass, since parseDate respects browser timezone, and not UTC format + expect(parseDateOffset).to.equal(browserTimeZoneOffset); + // Optional: verify we are dealing with the same date (this is already tested in other tests?) + expect(equalsDate(referenceDate, parsedDate)).to.be.true; + }); + it('return undefined when no valid date provided', () => { expect(parseDate('12.12.1976.,')).to.equal(undefined); // wrong delimiter expect(parseDate('foo')).to.equal(undefined); // no date