diff --git a/packages/ods/src/components/datepicker/package.json b/packages/ods/src/components/datepicker/package.json index f829d46ee7..157064c7e8 100644 --- a/packages/ods/src/components/datepicker/package.json +++ b/packages/ods/src/components/datepicker/package.json @@ -11,7 +11,7 @@ "lint:scss": "stylelint 'src/components/**/*.scss'", "lint:ts": "eslint '{src,tests}/**/*.{js,ts,tsx}'", "start": "stencil build --dev --watch --serve", - "test:e2e": "stencil test --e2e --config stencil.config.ts", + "test:e2e": "stencil test --e2e --runInBand --config stencil.config.ts", "test:e2e:ci": "tsc --noEmit && stencil test --e2e --ci --runInBand --config stencil.config.ts", "test:spec": "stencil test --spec --config stencil.config.ts --coverage", "test:spec:ci": "tsc --noEmit && stencil test --config stencil.config.ts --spec --ci --coverage" diff --git a/packages/ods/src/components/datepicker/src/components/ods-datepicker/ods-datepicker.tsx b/packages/ods/src/components/datepicker/src/components/ods-datepicker/ods-datepicker.tsx index 9533978378..01934bd1e9 100644 --- a/packages/ods/src/components/datepicker/src/components/ods-datepicker/ods-datepicker.tsx +++ b/packages/ods/src/components/datepicker/src/components/ods-datepicker/ods-datepicker.tsx @@ -182,15 +182,17 @@ export class OdsDatepicker { // Manage the component value change // Triggered either by user selection or `setDate` instance method call this.inputElement.addEventListener('changeDate', (event: Event) => { - const newDate = (event as CustomEvent).detail.date; + const newDate: Date = (event as CustomEvent).detail.date; const formattedNewDate = formatDate(newDate, this.format); + const oldValue = this.value; this.value = newDate; setFormValue(this.internals, formattedNewDate); this.odsChange.emit({ formattedValue: formattedNewDate, name: this.name, + oldValue, validity: this.inputElement?.validity, value: this.value, }); diff --git a/packages/ods/src/components/datepicker/src/interfaces/events.ts b/packages/ods/src/components/datepicker/src/interfaces/events.ts index 50514bc921..4ab61e079c 100644 --- a/packages/ods/src/components/datepicker/src/interfaces/events.ts +++ b/packages/ods/src/components/datepicker/src/interfaces/events.ts @@ -1,6 +1,7 @@ interface OdsDatepickerEventChangeDetail { formattedValue?: string; name: string; + oldValue?: Date | null; validity?: ValidityState; value?: Date | null; } diff --git a/packages/ods/src/components/datepicker/tests/behaviour/ods-datepicker.e2e.ts b/packages/ods/src/components/datepicker/tests/behaviour/ods-datepicker.e2e.ts index 54aaa994b4..010b663d46 100644 --- a/packages/ods/src/components/datepicker/tests/behaviour/ods-datepicker.e2e.ts +++ b/packages/ods/src/components/datepicker/tests/behaviour/ods-datepicker.e2e.ts @@ -111,4 +111,31 @@ describe('ods-datepicker behaviour', () => { }); }); }); + + describe('event', () => { + describe('odsChange', () => { + it('should emit an odsChange event', async() => { + const value = new Date('10 May 2024'); + await setup(''); + await page.evaluate((value) => { + document.querySelector('ods-datepicker')!.value = value; + }, value); + const odsOdsChangeSpy = await page.spyOnEvent('odsChange'); + + await page.keyboard.press('Tab'); + await page.keyboard.type('11/05/2024'); + await page.keyboard.press('Enter'); + await page.waitForChanges(); + + expect(odsOdsChangeSpy).toHaveReceivedEventTimes(1); + expect(odsOdsChangeSpy).toHaveReceivedEventDetail({ + formattedValue: '11/05/2024', + name: 'ods-datepicker', + oldValue: value.toISOString(), + validity: {}, + value: '2024-05-10T22:00:00.000Z', + }); + }); + }); + }); }); diff --git a/packages/ods/src/components/input/tests/behaviour/ods-input.e2e.ts b/packages/ods/src/components/input/tests/behaviour/ods-input.e2e.ts index 3e500e1ac5..522b38f915 100644 --- a/packages/ods/src/components/input/tests/behaviour/ods-input.e2e.ts +++ b/packages/ods/src/components/input/tests/behaviour/ods-input.e2e.ts @@ -60,7 +60,7 @@ describe('ods-input behaviour', () => { describe('event:odsChange ', () => { it('should receive odsChange event', async() => { const typeValue = 'some text'; - await setup(''); + await setup(''); const odsChangeSpy = await page.spyOnEvent('odsChange'); await part.type(typeValue); @@ -68,6 +68,12 @@ describe('ods-input behaviour', () => { expect(await el.getProperty('value')).toBe(typeValue); expect(odsChangeSpy).toHaveReceivedEventTimes(typeValue.length); + expect(odsChangeSpy).toHaveReceivedEventDetail({ + name: 'ods-input', + oldValue: 'some tex', + validity: {}, + value: 'some text', + }); }); it('should do nothing because of disabled', async() => { diff --git a/packages/ods/src/components/password/tests/behaviour/ods-password.e2e.ts b/packages/ods/src/components/password/tests/behaviour/ods-password.e2e.ts index a3ad26bf38..b16458f537 100644 --- a/packages/ods/src/components/password/tests/behaviour/ods-password.e2e.ts +++ b/packages/ods/src/components/password/tests/behaviour/ods-password.e2e.ts @@ -57,7 +57,7 @@ describe('ods-password behaviour', () => { describe('event:odsChange ', () => { it('should receive odsChange event', async() => { const typeValue = 'some text'; - await setup(''); + await setup(''); const odsChangeSpy = await page.spyOnEvent('odsChange'); await page.keyboard.press('Tab'); @@ -66,6 +66,12 @@ describe('ods-password behaviour', () => { expect(await el.getProperty('value')).toBe(typeValue); expect(odsChangeSpy).toHaveReceivedEventTimes(typeValue.length); + expect(odsChangeSpy).toHaveReceivedEventDetail({ + name: 'ods-password', + oldValue: 'some tex', + validity: {}, + value: 'some text', + }); }); it('should do nothing because of disabled', async() => { diff --git a/packages/ods/src/components/phone-number/src/components/ods-phone-number/ods-phone-number.tsx b/packages/ods/src/components/phone-number/src/components/ods-phone-number/ods-phone-number.tsx index 08d8b92160..ba857f8fdf 100644 --- a/packages/ods/src/components/phone-number/src/components/ods-phone-number/ods-phone-number.tsx +++ b/packages/ods/src/components/phone-number/src/components/ods-phone-number/ods-phone-number.tsx @@ -118,6 +118,7 @@ export class OdsPhoneNumber { this.odsChange.emit({ isoCode: this.isoCode, name: this.name, + oldValue: event.detail.oldValue?.toString(), validity: getValidityState(this.hasError, event.detail.validity), value: formattedValue, }); diff --git a/packages/ods/src/components/phone-number/tests/behaviour/ods-phone-number.e2e.ts b/packages/ods/src/components/phone-number/tests/behaviour/ods-phone-number.e2e.ts index 5c2abf9e3d..b2e1b3b89c 100644 --- a/packages/ods/src/components/phone-number/tests/behaviour/ods-phone-number.e2e.ts +++ b/packages/ods/src/components/phone-number/tests/behaviour/ods-phone-number.e2e.ts @@ -115,4 +115,52 @@ describe('ods-phone-number behaviour', () => { }); }); }); + + describe('event', () => { + describe('odsChange', () => { + it('should emit an odsChange event', async() => { + await setup(''); + const odsChangeSpy = await page.spyOnEvent('odsChange'); + + const newValue = '0987654321'; + await page.keyboard.press('Tab'); + await page.keyboard.type(newValue); + await page.waitForChanges(); + + expect(await el.getProperty('value')).toBe(newValue); + expect(odsChangeSpy).toHaveReceivedEventTimes(newValue.length); + expect(odsChangeSpy).toHaveReceivedEventDetail({ + isoCode: 'fr', + name: 'ods-phone-number', + oldValue: newValue.slice(0, -1), + validity: { + badInput: false, + customError: false, + patternMismatch: false, + rangeOverflow: false, + rangeUnderflow: false, + stepMismatch: false, + tooLong: false, + tooShort: false, + typeMismatch: false, + valid: true, + valueMissing: false, + }, + value: `+33${newValue.substring(1)}`, + }); + }); + + it('should not emit an odsChange event if disabled', async() => { + await setup(''); + const odsChangeSpy = await page.spyOnEvent('odsChange'); + + const newValue = '0987654321'; + await page.keyboard.press('Tab'); + await page.keyboard.type(newValue); + await page.waitForChanges(); + + expect(odsChangeSpy).toHaveReceivedEventTimes(0); + }); + }); + }); }); diff --git a/packages/ods/src/components/quantity/tests/behaviour/ods-quantity.e2e.ts b/packages/ods/src/components/quantity/tests/behaviour/ods-quantity.e2e.ts index 1f787b4638..6a15c84560 100644 --- a/packages/ods/src/components/quantity/tests/behaviour/ods-quantity.e2e.ts +++ b/packages/ods/src/components/quantity/tests/behaviour/ods-quantity.e2e.ts @@ -47,21 +47,33 @@ describe('ods-quantity behaviour', () => { describe('button minus', () => { it('should decrement value', async() => { - await setup(''); + await setup(''); const odsChangeSpy = await page.spyOnEvent('odsChange'); await buttonMinus.click(); await page.waitForChanges(); expect(await el.getProperty('value')).toBe(-1); expect(odsChangeSpy).toHaveReceivedEventTimes(1); + expect(odsChangeSpy).toHaveReceivedEventDetail({ + name: 'ods-quantity', + oldValue: 0, + validity: {}, + value: -1, + }); }); it('should decrement value with step', async() => { - await setup(''); + await setup(''); const odsChangeSpy = await page.spyOnEvent('odsChange'); await buttonMinus.click(); await page.waitForChanges(); expect(await el.getProperty('value')).toBe(-10); expect(odsChangeSpy).toHaveReceivedEventTimes(1); + expect(odsChangeSpy).toHaveReceivedEventDetail({ + name: 'ods-quantity', + oldValue: 0, + validity: {}, + value: -10, + }); }); it('should not decrement value with is-disabled', async() => { @@ -103,21 +115,33 @@ describe('ods-quantity behaviour', () => { describe('button add', () => { it('should increment value', async() => { - await setup(''); + await setup(''); const odsChangeSpy = await page.spyOnEvent('odsChange'); await buttonAdd.click(); await page.waitForChanges(); expect(await el.getProperty('value')).toBe(1); expect(odsChangeSpy).toHaveReceivedEventTimes(1); + expect(odsChangeSpy).toHaveReceivedEventDetail({ + name: 'ods-quantity', + oldValue: 0, + validity: {}, + value: 1, + }); }); it('should increment value with step', async() => { - await setup(''); + await setup(''); const odsChangeSpy = await page.spyOnEvent('odsChange'); await buttonAdd.click(); await page.waitForChanges(); expect(await el.getProperty('value')).toBe(10); expect(odsChangeSpy).toHaveReceivedEventTimes(1); + expect(odsChangeSpy).toHaveReceivedEventDetail({ + name: 'ods-quantity', + oldValue: 0, + validity: {}, + value: 10, + }); }); it('should not increment value with is-disabled', async() => { diff --git a/packages/ods/src/components/radio/src/components/ods-radio/ods-radio.tsx b/packages/ods/src/components/radio/src/components/ods-radio/ods-radio.tsx index 2ebfa7ec37..40dfe3f15b 100644 --- a/packages/ods/src/components/radio/src/components/ods-radio/ods-radio.tsx +++ b/packages/ods/src/components/radio/src/components/ods-radio/ods-radio.tsx @@ -65,7 +65,7 @@ export class OdsRadio { return document.querySelectorAll(`ods-radio[name="${this.name}"]`); } - private onInput(event: Event): void { + private onInput(event: InputEvent): void { this.odsChange.emit({ checked: (event.target as HTMLInputElement)?.checked, name: this.name, @@ -84,7 +84,7 @@ export class OdsRadio { checked={ this.isChecked } disabled={ this.isDisabled } onBlur={ (): CustomEvent => this.odsBlur.emit() } - onInput={ (event: Event): void => this.onInput(event) } + onInput={ (event: InputEvent): void => this.onInput(event) } onFocus={ (): CustomEvent => this.odsFocus.emit() } id={ this.inputId } name={ this.name } diff --git a/packages/ods/src/components/textarea/tests/behaviour/ods-textarea.e2e.ts b/packages/ods/src/components/textarea/tests/behaviour/ods-textarea.e2e.ts index 81d7930162..72e198e3fc 100644 --- a/packages/ods/src/components/textarea/tests/behaviour/ods-textarea.e2e.ts +++ b/packages/ods/src/components/textarea/tests/behaviour/ods-textarea.e2e.ts @@ -77,7 +77,7 @@ describe('ods-textarea behaviour', () => { describe('on value change', () => { it('should emit an odsChange event', async() => { const dummyValue = 'dummy value'; - await setup(''); + await setup(''); const odsValueChangeSpy = await page.spyOnEvent('odsChange'); await textarea.type(dummyValue); @@ -85,6 +85,12 @@ describe('ods-textarea behaviour', () => { expect(await el.getProperty('value')).toBe(dummyValue); expect(odsValueChangeSpy).toHaveReceivedEventTimes(dummyValue.length); + expect(odsValueChangeSpy).toHaveReceivedEventDetail({ + name: 'ods-textarea', + oldValue: dummyValue.slice(0, -1), + validity: {}, + value: dummyValue, + }); }); it('should do nothing if disabled', async() => { diff --git a/packages/ods/src/components/timepicker/src/components/ods-timepicker/ods-timepicker.tsx b/packages/ods/src/components/timepicker/src/components/ods-timepicker/ods-timepicker.tsx index b4e26ebf64..ee63e0d83e 100644 --- a/packages/ods/src/components/timepicker/src/components/ods-timepicker/ods-timepicker.tsx +++ b/packages/ods/src/components/timepicker/src/components/ods-timepicker/ods-timepicker.tsx @@ -18,6 +18,7 @@ export class OdsTimepicker { private defaultCurrentTimezone?: OdsTimezone; private odsInput?: OdsInput & HTMLElement; private odsSelect?: OdsSelect & HTMLElement; + private oldValue?: string | null; private timezonesList: OdsTimezone[] = []; @Element() el!: HTMLElement; @@ -74,6 +75,7 @@ export class OdsTimepicker { const value = formatValue(this.odsInput?.value as string, this.withSeconds); if (value) { + this.oldValue = this.value ?? null; this.value = value; } setFormValue(this.internals, this.value); @@ -83,6 +85,7 @@ export class OdsTimepicker { if (!this.value) { this.value = this.defaultValue ?? null; } + console.log('this.value init', this.value) this.initTimezones(); this.formatValue(); this.defaultCurrentTimezone = this.currentTimezone; @@ -109,12 +112,13 @@ export class OdsTimepicker { if (isFromSelect) { this.currentTimezone = event.detail.value as OdsTimezone; } else { + this.oldValue = event.detail.oldValue as string; this.value = event.detail.value as string; } this.odsChange.emit({ currentTimezone: this.currentTimezone, name: this.name, - oldValue: '', + oldValue: this.oldValue ?? undefined, validity: await this.odsInput?.getValidity(), value: this.value ?? '', }); diff --git a/packages/ods/src/components/timepicker/tests/behavior/ods-timepicker.e2e.ts b/packages/ods/src/components/timepicker/tests/behavior/ods-timepicker.e2e.ts index 711cdc0698..701166b886 100644 --- a/packages/ods/src/components/timepicker/tests/behavior/ods-timepicker.e2e.ts +++ b/packages/ods/src/components/timepicker/tests/behavior/ods-timepicker.e2e.ts @@ -102,15 +102,22 @@ describe('ods-timepicker behavior', () => { describe('events', () => { it('should call odsChange event', async() => { - const value = '12:12'; - await setup(''); + const newValue = '12:12'; + const value = '11:11'; + await setup(``); const odsChangeSpy = await page.spyOnEvent('odsChange'); - await el.setProperty('value', value); + await el.setProperty('value', newValue); await page.waitForChanges(); - expect(await el.getProperty('value')).toBe(value); + expect(await el.getProperty('value')).toBe(newValue); expect(odsChangeSpy).toHaveReceivedEventTimes(1); + expect(odsChangeSpy).toHaveReceivedEventDetail({ + name: 'ods-timepicker', + oldValue: value, + validity: {}, + value: newValue, + }); }); }); });