diff --git a/packages/elements/src/slider/__test__/slider.number-field.test.js b/packages/elements/src/slider/__test__/slider.number-field.test.js index 48d1d94143..3b658c354e 100644 --- a/packages/elements/src/slider/__test__/slider.number-field.test.js +++ b/packages/elements/src/slider/__test__/slider.number-field.test.js @@ -1,15 +1,20 @@ import '@refinitiv-ui/elements/slider'; import '@refinitiv-ui/elemental-theme/light/ef-slider'; -import { elementUpdated, expect, fixture, oneEvent } from '@refinitiv-ui/test-helpers'; +import { elementUpdated, expect, fixture, nextFrame, oneEvent } from '@refinitiv-ui/test-helpers'; + +import { tabSliderPosition } from './utils.js'; const getNumberField = (el, name) => el.shadowRoot.querySelector(`ef-number-field[name=${name}]`); +const getSliderTrackElement = (el) => el.sliderRef.value; describe('slider/NumberField', function () { let el; + let slider; beforeEach(async function () { el = await fixture(''); + slider = getSliderTrackElement(el); }); it('input number field has set value 40 it should be slider value has correct ', async function () { @@ -70,6 +75,41 @@ describe('slider/NumberField', function () { expect(input.value).to.equal(el.value); }); + it('Input field error state should reset when drag slider', async function () { + // Drag 'value' from 80 to 100 + const dragPosition80 = tabSliderPosition(el, 80); + const dragPositionToRight = tabSliderPosition(el, 100); + + el.showInputField = ''; + el.step = '5'; + await elementUpdated(el); + + // Input invalid value to show error state + const numberField = getNumberField(el, 'value'); + const input = numberField.shadowRoot.querySelector('input'); + input.value = '77'; + setTimeout(() => input.dispatchEvent(new Event('input'))); + numberField.reportValidity(); + expect(numberField.error).to.equal(true); + + // Drag slider + setTimeout(() => + slider.dispatchEvent(new MouseEvent('mousedown', { clientX: dragPosition80, clientY: 0 })) + ); + await oneEvent(slider, 'mousedown'); + setTimeout(() => + window.dispatchEvent( + new MouseEvent('mousemove', { + clientX: dragPositionToRight, + clientY: 0 + }) + ) + ); + await oneEvent(window, 'mousemove'); + await nextFrame(); + expect(numberField.error).to.equal(false); + }); + it('Input field should in readonly state when show-input-field value is equal "readonly"', async function () { el.showInputField = 'readonly'; await elementUpdated(el); diff --git a/packages/elements/src/slider/index.ts b/packages/elements/src/slider/index.ts index 7efabfad71..8fa82ea4d4 100644 --- a/packages/elements/src/slider/index.ts +++ b/packages/elements/src/slider/index.ts @@ -904,6 +904,7 @@ export class Slider extends ControlElement { } this.onDrag(event); + this.validateNumberField(); if ((event as TouchEvent).changedTouches) { this.addEventListener('touchmove', this.onDrag); @@ -1009,6 +1010,18 @@ export class Slider extends ControlElement { return this.fromNumber + this.minRangeNumber; } + /** + * Validate number field from changed thumb + * @returns {void} + */ + private validateNumberField(): void { + if (this.isShowInputField) { + const name = this.changedThumb?.getAttribute('name') as SliderDataName; + const numberField = this[`${name}Input`]; + requestAnimationFrame(() => numberField.reportValidity()); + } + } + /** * Calculate the nearest possible step value depending on step interval * @param thumbPosition current thumb position in fraction