From 05880d8447e6fef8caf8d0bec7986286f2b9bcbb Mon Sep 17 00:00:00 2001 From: wagnermaciel Date: Fri, 12 Mar 2021 12:35:34 -0800 Subject: [PATCH 1/2] test(material-experimental/mdc-slider): add tests for sliders with set steps --- .../mdc-slider/slider.spec.ts | 165 +++++++++++++++++- 1 file changed, 164 insertions(+), 1 deletion(-) diff --git a/src/material-experimental/mdc-slider/slider.spec.ts b/src/material-experimental/mdc-slider/slider.spec.ts index e7821e37c4ff..c501004691f8 100644 --- a/src/material-experimental/mdc-slider/slider.spec.ts +++ b/src/material-experimental/mdc-slider/slider.spec.ts @@ -392,7 +392,6 @@ describe('MDC-based MatSlider' , () => { it('should be able to set the min and max values when they are more precise ' + 'than the step', () => { sliderInstance.step = 10; - fixture.detectChanges(); slideToValue(sliderInstance, 25, Thumb.END, platform.IOS); expect(inputInstance.value).toBe(25); slideToValue(sliderInstance, 75, Thumb.END, platform.IOS); @@ -521,6 +520,130 @@ describe('MDC-based MatSlider' , () => { expect(endInputInstance.value).toBe(99); }); }); + + describe('slider with set step', () => { + let sliderInstance: MatSlider; + let inputInstance: MatSliderThumb; + + beforeEach(waitForAsync(() => { + const fixture = createComponent(SliderWithStep); + fixture.detectChanges(); + const sliderDebugElement = fixture.debugElement.query(By.directive(MatSlider)); + sliderInstance = sliderDebugElement.componentInstance; + inputInstance = sliderInstance._getInput(Thumb.END); + })); + + it('should set the correct step value on mousedown', () => { + expect(inputInstance.value).toBe(0); + setValueByClick(sliderInstance, 13, platform.IOS); + expect(inputInstance.value).toBe(25); + }); + + it('should set the correct step value on slide', () => { + slideToValue(sliderInstance, 12, Thumb.END, platform.IOS); + expect(inputInstance.value).toBe(0); + }); + + it('should not add decimals to the value if it is a whole number', () => { + sliderInstance.step = 0.1; + slideToValue(sliderInstance, 100, Thumb.END, platform.IOS); + expect(inputInstance.value).toBe(100); + }); + + it('should truncate long decimal values when using a decimal step', () => { + // TODO(wagnermaciel): Uncomment this test once b/182504575 is resolved. + // sliderInstance.step = 0.1; + // slideToValue(sliderInstance, 33.3333, Thumb.END, platform.IOS); + // expect(inputInstance.value).toBe(33); + }); + + it('should truncate long decimal values when using a decimal step and the arrow keys', () => { + sliderInstance.step = 0.1; + changeValueUsingArrowKeys(sliderInstance, ArrowKey.RIGHT, Thumb.END); + changeValueUsingArrowKeys(sliderInstance, ArrowKey.RIGHT, Thumb.END); + changeValueUsingArrowKeys(sliderInstance, ArrowKey.RIGHT, Thumb.END); + expect(inputInstance.value).toBe(0.3); + }); + }); + + describe('range slider with set step', () => { + let sliderInstance: MatSlider; + let startInputInstance: MatSliderThumb; + let endInputInstance: MatSliderThumb; + + beforeEach(waitForAsync(() => { + const fixture = createComponent(RangeSliderWithStep); + fixture.detectChanges(); + const sliderDebugElement = fixture.debugElement.query(By.directive(MatSlider)); + sliderInstance = sliderDebugElement.componentInstance; + startInputInstance = sliderInstance._getInput(Thumb.START); + endInputInstance = sliderInstance._getInput(Thumb.END); + })); + + it('should set the correct step value on mousedown behind the start thumb', () => { + sliderInstance._setValue(50, Thumb.START); + setValueByClick(sliderInstance, 13, platform.IOS); + expect(startInputInstance.value).toBe(25); + }); + + it('should set the correct step value on mousedown in front of the end thumb', () => { + sliderInstance._setValue(50, Thumb.END); + setValueByClick(sliderInstance, 63, platform.IOS); + expect(endInputInstance.value).toBe(75); + }); + + it('should set the correct start thumb step value on slide', () => { + slideToValue(sliderInstance, 26, Thumb.START, platform.IOS); + expect(startInputInstance.value).toBe(25); + }); + + it('should set the correct end thumb step value on slide', () => { + slideToValue(sliderInstance, 45, Thumb.END, platform.IOS); + expect(endInputInstance.value).toBe(50); + }); + + it('should not add decimals to the end value if it is a whole number', () => { + sliderInstance.step = 0.1; + slideToValue(sliderInstance, 100, Thumb.END, platform.IOS); + expect(endInputInstance.value).toBe(100); + }); + + it('should not add decimals to the start value if it is a whole number', () => { + sliderInstance.step = 0.1; + slideToValue(sliderInstance, 100, Thumb.END, platform.IOS); + expect(endInputInstance.value).toBe(100); + }); + + it('should truncate long decimal start values when using a decimal step', () => { + // TODO(wagnermaciel): Uncomment this test once b/182504575 is resolved. + // sliderInstance.step = 0.1; + // slideToValue(sliderInstance, 33.3333, Thumb.START, platform.IOS); + // expect(startInputInstance.value).toBe(33); + }); + + it('should truncate long decimal end values when using a decimal step', () => { + // TODO(wagnermaciel): Uncomment this test once b/182504575 is resolved. + // sliderInstance.step = 0.1; + // slideToValue(sliderInstance, 66.6666, Thumb.END, platform.IOS); + // expect(endInputInstance.value).toBe(66); + }); + + it('should truncate long decimal start values when using a decimal step arrow keys', () => { + sliderInstance.step = 0.1; + changeValueUsingArrowKeys(sliderInstance, ArrowKey.RIGHT, Thumb.START); + changeValueUsingArrowKeys(sliderInstance, ArrowKey.RIGHT, Thumb.START); + changeValueUsingArrowKeys(sliderInstance, ArrowKey.RIGHT, Thumb.START); + expect(startInputInstance.value).toBe(0.3); + }); + + it('should truncate long decimal end values when using a decimal step arrow keys', () => { + sliderInstance.step = 0.1; + changeValueUsingArrowKeys(sliderInstance, ArrowKey.LEFT, Thumb.END); + changeValueUsingArrowKeys(sliderInstance, ArrowKey.LEFT, Thumb.END); + changeValueUsingArrowKeys(sliderInstance, ArrowKey.LEFT, Thumb.END); + expect(endInputInstance.value).toBe(99.7); + }); + }); }); @@ -600,6 +723,25 @@ class SliderWithValue {} }) class RangeSliderWithValue {} +@Component({ + template: ` + + + + `, +}) +class SliderWithStep {} + +@Component({ + template: ` + + + + + `, +}) +class RangeSliderWithStep {} + /** The pointer event types used by the MDC Slider. */ const enum PointerEventType { POINTER_DOWN = 'pointerdown', @@ -614,6 +756,11 @@ const enum TouchEventType { TOUCH_MOVE = 'touchmove', } +const enum ArrowKey { + LEFT = 37, + RIGHT = 39, +} + /** Clicks on the MatSlider at the coordinates corresponding to the given value. */ function setValueByClick(slider: MatSlider, value: number, isIOS: boolean) { const {min, max} = slider; @@ -650,6 +797,22 @@ function slideToValue(slider: MatSlider, value: number, thumbPosition: Thumb, is dispatchPointerOrTouchEvent(sliderElement, PointerEventType.POINTER_UP, endX, endY, isIOS); } +/** + * Mimics changing the slider value using arrow keys. + * + * Dispatching keydown events on inputs do not trigger value changes. Thus, to mimic this behavior, + * we manually change the slider inputs value and then dispatch a change event (which is what the + * MDC Foundation is listening for & how it handles these updates). + */ +function changeValueUsingArrowKeys(slider: MatSlider, arrow: ArrowKey, thumbPosition: Thumb) { + const input = slider._getInput(thumbPosition); + const value = arrow === ArrowKey.RIGHT + ? input.value + slider.step + : input.value - slider.step; + input._hostElement.value = value.toString(); + input._hostElement.dispatchEvent(new Event('change')); +} + /** Dispatch a pointerdown or pointerup event if supported, otherwise dispatch the touch event. */ function dispatchPointerOrTouchEvent( node: Node, type: PointerEventType, x: number, y: number, isIOS: boolean) { From e5dc4adb87d4ba180727f7455b988c640581fb1c Mon Sep 17 00:00:00 2001 From: wagnermaciel Date: Mon, 15 Mar 2021 06:56:03 -0700 Subject: [PATCH 2/2] fixup! test(material-experimental/mdc-slider): add tests for sliders with set steps --- .../mdc-slider/slider.spec.ts | 31 +++++++++---------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/src/material-experimental/mdc-slider/slider.spec.ts b/src/material-experimental/mdc-slider/slider.spec.ts index c501004691f8..0a504b4b686f 100644 --- a/src/material-experimental/mdc-slider/slider.spec.ts +++ b/src/material-experimental/mdc-slider/slider.spec.ts @@ -6,8 +6,10 @@ * found in the LICENSE file at https://angular.io/license */ +import {LEFT_ARROW, RIGHT_ARROW} from '@angular/cdk/keycodes'; import {Platform} from '@angular/cdk/platform'; import { + dispatchEvent, dispatchMouseEvent, dispatchPointerEvent, dispatchTouchEvent, @@ -559,9 +561,9 @@ describe('MDC-based MatSlider' , () => { it('should truncate long decimal values when using a decimal step and the arrow keys', () => { sliderInstance.step = 0.1; - changeValueUsingArrowKeys(sliderInstance, ArrowKey.RIGHT, Thumb.END); - changeValueUsingArrowKeys(sliderInstance, ArrowKey.RIGHT, Thumb.END); - changeValueUsingArrowKeys(sliderInstance, ArrowKey.RIGHT, Thumb.END); + changeValueUsingArrowKeys(sliderInstance, RIGHT_ARROW, Thumb.END); + changeValueUsingArrowKeys(sliderInstance, RIGHT_ARROW, Thumb.END); + changeValueUsingArrowKeys(sliderInstance, RIGHT_ARROW, Thumb.END); expect(inputInstance.value).toBe(0.3); }); }); @@ -630,17 +632,17 @@ describe('MDC-based MatSlider' , () => { it('should truncate long decimal start values when using a decimal step arrow keys', () => { sliderInstance.step = 0.1; - changeValueUsingArrowKeys(sliderInstance, ArrowKey.RIGHT, Thumb.START); - changeValueUsingArrowKeys(sliderInstance, ArrowKey.RIGHT, Thumb.START); - changeValueUsingArrowKeys(sliderInstance, ArrowKey.RIGHT, Thumb.START); + changeValueUsingArrowKeys(sliderInstance, RIGHT_ARROW, Thumb.START); + changeValueUsingArrowKeys(sliderInstance, RIGHT_ARROW, Thumb.START); + changeValueUsingArrowKeys(sliderInstance, RIGHT_ARROW, Thumb.START); expect(startInputInstance.value).toBe(0.3); }); it('should truncate long decimal end values when using a decimal step arrow keys', () => { sliderInstance.step = 0.1; - changeValueUsingArrowKeys(sliderInstance, ArrowKey.LEFT, Thumb.END); - changeValueUsingArrowKeys(sliderInstance, ArrowKey.LEFT, Thumb.END); - changeValueUsingArrowKeys(sliderInstance, ArrowKey.LEFT, Thumb.END); + changeValueUsingArrowKeys(sliderInstance, LEFT_ARROW, Thumb.END); + changeValueUsingArrowKeys(sliderInstance, LEFT_ARROW, Thumb.END); + changeValueUsingArrowKeys(sliderInstance, LEFT_ARROW, Thumb.END); expect(endInputInstance.value).toBe(99.7); }); }); @@ -756,11 +758,6 @@ const enum TouchEventType { TOUCH_MOVE = 'touchmove', } -const enum ArrowKey { - LEFT = 37, - RIGHT = 39, -} - /** Clicks on the MatSlider at the coordinates corresponding to the given value. */ function setValueByClick(slider: MatSlider, value: number, isIOS: boolean) { const {min, max} = slider; @@ -804,13 +801,13 @@ function slideToValue(slider: MatSlider, value: number, thumbPosition: Thumb, is * we manually change the slider inputs value and then dispatch a change event (which is what the * MDC Foundation is listening for & how it handles these updates). */ -function changeValueUsingArrowKeys(slider: MatSlider, arrow: ArrowKey, thumbPosition: Thumb) { +function changeValueUsingArrowKeys(slider: MatSlider, arrow: number, thumbPosition: Thumb) { const input = slider._getInput(thumbPosition); - const value = arrow === ArrowKey.RIGHT + const value = arrow === RIGHT_ARROW ? input.value + slider.step : input.value - slider.step; input._hostElement.value = value.toString(); - input._hostElement.dispatchEvent(new Event('change')); + dispatchEvent(input._hostElement, new Event('change')); } /** Dispatch a pointerdown or pointerup event if supported, otherwise dispatch the touch event. */