From a5ee470469d7541f20e9ef043905809188c9db37 Mon Sep 17 00:00:00 2001 From: wagnermaciel Date: Wed, 14 Apr 2021 09:26:31 -0700 Subject: [PATCH 1/2] test(material-experimental/mdc-slider): add change handler tests --- .../mdc-slider/slider.spec.ts | 288 ++++++++++++++++++ 1 file changed, 288 insertions(+) diff --git a/src/material-experimental/mdc-slider/slider.spec.ts b/src/material-experimental/mdc-slider/slider.spec.ts index 97fd39fb8848..e1f1051a8a79 100644 --- a/src/material-experimental/mdc-slider/slider.spec.ts +++ b/src/material-experimental/mdc-slider/slider.spec.ts @@ -773,6 +773,259 @@ describe('MDC-based MatSlider' , () => { }); }); + describe('slider with change handler', () => { + let sliderInstance: MatSlider; + let inputInstance: MatSliderThumb; + let sliderElement: HTMLElement; + let fixture: ComponentFixture; + let testComponent: SliderWithChangeHandler; + + beforeEach(waitForAsync(() => { + fixture = createComponent(SliderWithChangeHandler); + fixture.detectChanges(); + testComponent = fixture.debugElement.componentInstance; + spyOn(testComponent, 'onChange'); + spyOn(testComponent, 'onInput'); + const sliderDebugElement = fixture.debugElement.query(By.directive(MatSlider)); + sliderElement = sliderDebugElement.nativeElement; + sliderInstance = sliderDebugElement.componentInstance; + inputInstance = sliderInstance._getInput(Thumb.END); + })); + + it('should emit change on mouseup', () => { + expect(testComponent.onChange).not.toHaveBeenCalled(); + setValueByClick(sliderInstance, 20, platform.IOS); + expect(testComponent.onChange).toHaveBeenCalledTimes(1); + }); + + it('should emit change on slide', () => { + expect(testComponent.onChange).not.toHaveBeenCalled(); + slideToValue(sliderInstance, 40, Thumb.END, platform.IOS); + expect(testComponent.onChange).toHaveBeenCalledTimes(1); + }); + + it('should not emit multiple changes for the same value', () => { + expect(testComponent.onChange).not.toHaveBeenCalled(); + + setValueByClick(sliderInstance, 60, platform.IOS); + slideToValue(sliderInstance, 60, Thumb.END, platform.IOS); + setValueByClick(sliderInstance, 60, platform.IOS); + slideToValue(sliderInstance, 60, Thumb.END, platform.IOS); + + expect(testComponent.onChange).toHaveBeenCalledTimes(1); + }); + + it('should dispatch events when changing back to previously emitted value after ' + + 'programmatically setting value', () => { + const dispatchSliderEvent = (type: PointerEventType, value: number) => { + const {x, y} = getCoordsForValue(sliderInstance, value); + dispatchPointerOrTouchEvent(sliderElement, type, x, y, platform.IOS); + }; + + expect(testComponent.onChange).not.toHaveBeenCalled(); + expect(testComponent.onInput).not.toHaveBeenCalled(); + + dispatchSliderEvent(PointerEventType.POINTER_DOWN, 20); + fixture.detectChanges(); + + expect(testComponent.onChange).not.toHaveBeenCalled(); + expect(testComponent.onInput).toHaveBeenCalledTimes(1); + + dispatchSliderEvent(PointerEventType.POINTER_UP, 20); + fixture.detectChanges(); + + expect(testComponent.onChange).toHaveBeenCalledTimes(1); + expect(testComponent.onInput).toHaveBeenCalledTimes(1); + + inputInstance.value = 0; + fixture.detectChanges(); + + expect(testComponent.onChange).toHaveBeenCalledTimes(1); + expect(testComponent.onInput).toHaveBeenCalledTimes(1); + + dispatchSliderEvent(PointerEventType.POINTER_DOWN, 20); + fixture.detectChanges(); + dispatchSliderEvent(PointerEventType.POINTER_UP, 20); + + expect(testComponent.onChange).toHaveBeenCalledTimes(2); + expect(testComponent.onInput).toHaveBeenCalledTimes(2); + }); + }); + + describe('range slider with change handlers', () => { + let sliderInstance: MatSlider; + let startInputInstance: MatSliderThumb; + let endInputInstance: MatSliderThumb; + let sliderElement: HTMLElement; + let fixture: ComponentFixture; + let testComponent: RangeSliderWithChangeHandler; + + beforeEach(waitForAsync(() => { + fixture = createComponent(RangeSliderWithChangeHandler); + fixture.detectChanges(); + testComponent = fixture.debugElement.componentInstance; + spyOn(testComponent, 'onStartThumbChange'); + spyOn(testComponent, 'onStartThumbInput'); + spyOn(testComponent, 'onEndThumbChange'); + spyOn(testComponent, 'onEndThumbInput'); + const sliderDebugElement = fixture.debugElement.query(By.directive(MatSlider)); + sliderElement = sliderDebugElement.nativeElement; + sliderInstance = sliderDebugElement.componentInstance; + startInputInstance = sliderInstance._getInput(Thumb.START); + endInputInstance = sliderInstance._getInput(Thumb.END); + })); + + it('should emit change on mouseup on the start thumb', () => { + expect(testComponent.onStartThumbChange).not.toHaveBeenCalled(); + expect(testComponent.onEndThumbChange).not.toHaveBeenCalled(); + setValueByClick(sliderInstance, 20, platform.IOS); + expect(testComponent.onStartThumbChange).toHaveBeenCalledTimes(1); + expect(testComponent.onEndThumbChange).not.toHaveBeenCalled(); + }); + + it('should emit change on mouseup on the end thumb', () => { + expect(testComponent.onStartThumbChange).not.toHaveBeenCalled(); + expect(testComponent.onEndThumbChange).not.toHaveBeenCalled(); + setValueByClick(sliderInstance, 80, platform.IOS); + expect(testComponent.onStartThumbChange).not.toHaveBeenCalled(); + expect(testComponent.onEndThumbChange).toHaveBeenCalledTimes(1); + }); + + it('should emit change on start thumb slide', () => { + expect(testComponent.onStartThumbChange).not.toHaveBeenCalled(); + expect(testComponent.onEndThumbChange).not.toHaveBeenCalled(); + slideToValue(sliderInstance, 40, Thumb.START, platform.IOS); + expect(testComponent.onStartThumbChange).toHaveBeenCalledTimes(1); + expect(testComponent.onEndThumbChange).not.toHaveBeenCalled(); + }); + + it('should emit change on end thumb slide', () => { + expect(testComponent.onStartThumbChange).not.toHaveBeenCalled(); + expect(testComponent.onEndThumbChange).not.toHaveBeenCalled(); + slideToValue(sliderInstance, 60, Thumb.END, platform.IOS); + expect(testComponent.onStartThumbChange).not.toHaveBeenCalled(); + expect(testComponent.onEndThumbChange).toHaveBeenCalledTimes(1); + }); + + it('should not emit multiple changes for the same start thumb value', () => { + expect(testComponent.onStartThumbChange).not.toHaveBeenCalled(); + expect(testComponent.onEndThumbChange).not.toHaveBeenCalled(); + + setValueByClick(sliderInstance, 30, platform.IOS); + slideToValue(sliderInstance, 30, Thumb.START, platform.IOS); + setValueByClick(sliderInstance, 30, platform.IOS); + slideToValue(sliderInstance, 30, Thumb.START, platform.IOS); + + expect(testComponent.onStartThumbChange).toHaveBeenCalledTimes(1); + expect(testComponent.onEndThumbChange).not.toHaveBeenCalled(); + }); + + it('should not emit multiple changes for the same end thumb value', () => { + expect(testComponent.onStartThumbChange).not.toHaveBeenCalled(); + expect(testComponent.onEndThumbChange).not.toHaveBeenCalled(); + + setValueByClick(sliderInstance, 60, platform.IOS); + slideToValue(sliderInstance, 60, Thumb.END, platform.IOS); + setValueByClick(sliderInstance, 60, platform.IOS); + slideToValue(sliderInstance, 60, Thumb.END, platform.IOS); + + expect(testComponent.onStartThumbChange).not.toHaveBeenCalled(); + expect(testComponent.onEndThumbChange).toHaveBeenCalledTimes(1); + }); + + it('should dispatch events when changing back to previously emitted value after ' + + 'programmatically setting the start value', () => { + const dispatchSliderEvent = (type: PointerEventType, value: number) => { + const {x, y} = getCoordsForValue(sliderInstance, value); + dispatchPointerOrTouchEvent(sliderElement, type, x, y, platform.IOS); + }; + + expect(testComponent.onStartThumbChange).not.toHaveBeenCalled(); + expect(testComponent.onStartThumbInput).not.toHaveBeenCalled(); + expect(testComponent.onEndThumbChange).not.toHaveBeenCalled(); + expect(testComponent.onEndThumbInput).not.toHaveBeenCalled(); + + dispatchSliderEvent(PointerEventType.POINTER_DOWN, 20); + fixture.detectChanges(); + + expect(testComponent.onStartThumbChange).not.toHaveBeenCalled(); + expect(testComponent.onStartThumbInput).toHaveBeenCalledTimes(1); + expect(testComponent.onEndThumbChange).not.toHaveBeenCalled(); + expect(testComponent.onEndThumbInput).not.toHaveBeenCalled(); + + dispatchSliderEvent(PointerEventType.POINTER_UP, 20); + fixture.detectChanges(); + + expect(testComponent.onStartThumbChange).toHaveBeenCalledTimes(1); + expect(testComponent.onStartThumbInput).toHaveBeenCalledTimes(1); + expect(testComponent.onEndThumbChange).not.toHaveBeenCalled(); + expect(testComponent.onEndThumbInput).not.toHaveBeenCalled(); + + startInputInstance.value = 0; + fixture.detectChanges(); + + expect(testComponent.onStartThumbChange).toHaveBeenCalledTimes(1); + expect(testComponent.onStartThumbInput).toHaveBeenCalledTimes(1); + expect(testComponent.onEndThumbChange).not.toHaveBeenCalled(); + expect(testComponent.onEndThumbInput).not.toHaveBeenCalled(); + + dispatchSliderEvent(PointerEventType.POINTER_DOWN, 20); + fixture.detectChanges(); + dispatchSliderEvent(PointerEventType.POINTER_UP, 20); + + expect(testComponent.onStartThumbChange).toHaveBeenCalledTimes(2); + expect(testComponent.onStartThumbInput).toHaveBeenCalledTimes(2); + expect(testComponent.onEndThumbChange).not.toHaveBeenCalled(); + expect(testComponent.onEndThumbInput).not.toHaveBeenCalled(); + }); + + it('should dispatch events when changing back to previously emitted value after ' + + 'programmatically setting the end value', () => { + const dispatchSliderEvent = (type: PointerEventType, value: number) => { + const {x, y} = getCoordsForValue(sliderInstance, value); + dispatchPointerOrTouchEvent(sliderElement, type, x, y, platform.IOS); + }; + + expect(testComponent.onStartThumbChange).not.toHaveBeenCalled(); + expect(testComponent.onStartThumbInput).not.toHaveBeenCalled(); + expect(testComponent.onEndThumbChange).not.toHaveBeenCalled(); + expect(testComponent.onEndThumbInput).not.toHaveBeenCalled(); + + dispatchSliderEvent(PointerEventType.POINTER_DOWN, 80); + fixture.detectChanges(); + + expect(testComponent.onStartThumbChange).not.toHaveBeenCalled(); + expect(testComponent.onStartThumbInput).not.toHaveBeenCalled(); + expect(testComponent.onEndThumbChange).not.toHaveBeenCalled(); + expect(testComponent.onEndThumbInput).toHaveBeenCalledTimes(1); + + dispatchSliderEvent(PointerEventType.POINTER_UP, 80); + fixture.detectChanges(); + + expect(testComponent.onStartThumbChange).not.toHaveBeenCalled(); + expect(testComponent.onStartThumbInput).not.toHaveBeenCalled(); + expect(testComponent.onEndThumbChange).toHaveBeenCalledTimes(1); + expect(testComponent.onEndThumbInput).toHaveBeenCalledTimes(1); + + endInputInstance.value = 100; + fixture.detectChanges(); + + expect(testComponent.onStartThumbChange).not.toHaveBeenCalled(); + expect(testComponent.onStartThumbInput).not.toHaveBeenCalled(); + expect(testComponent.onEndThumbChange).toHaveBeenCalledTimes(1); + expect(testComponent.onEndThumbInput).toHaveBeenCalledTimes(1); + + dispatchSliderEvent(PointerEventType.POINTER_DOWN, 80); + fixture.detectChanges(); + dispatchSliderEvent(PointerEventType.POINTER_UP, 80); + + expect(testComponent.onStartThumbChange).not.toHaveBeenCalled(); + expect(testComponent.onStartThumbInput).not.toHaveBeenCalled(); + expect(testComponent.onEndThumbChange).toHaveBeenCalledTimes(2); + expect(testComponent.onEndThumbInput).toHaveBeenCalledTimes(2); + }); + }); + describe('slider with ngModel', () => { let fixture: ComponentFixture; let testComponent: SliderWithNgModel; @@ -1104,6 +1357,41 @@ class RangeSliderWithOneWayBinding { endValue = 75; } +@Component({ + template: ` + + + + `, +}) +class SliderWithChangeHandler { + onChange() { } + onInput() { } + @ViewChild(MatSlider) slider: MatSlider; +} + +@Component({ + template: ` + + + + + `, +}) +class RangeSliderWithChangeHandler { + onStartThumbChange() { } + onStartThumbInput() { } + onEndThumbChange() { } + onEndThumbInput() { } + @ViewChild(MatSlider) slider: MatSlider; +} + @Component({ template: ` From 3ee52704042b19e266064da431ca656228140545 Mon Sep 17 00:00:00 2001 From: wagnermaciel Date: Wed, 14 Apr 2021 10:36:43 -0700 Subject: [PATCH 2/2] fixup! test(material-experimental/mdc-slider): add change handler tests --- .../mdc-slider/slider.spec.ts | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/material-experimental/mdc-slider/slider.spec.ts b/src/material-experimental/mdc-slider/slider.spec.ts index e1f1051a8a79..abed47f16a2a 100644 --- a/src/material-experimental/mdc-slider/slider.spec.ts +++ b/src/material-experimental/mdc-slider/slider.spec.ts @@ -784,8 +784,6 @@ describe('MDC-based MatSlider' , () => { fixture = createComponent(SliderWithChangeHandler); fixture.detectChanges(); testComponent = fixture.debugElement.componentInstance; - spyOn(testComponent, 'onChange'); - spyOn(testComponent, 'onInput'); const sliderDebugElement = fixture.debugElement.query(By.directive(MatSlider)); sliderElement = sliderDebugElement.nativeElement; sliderInstance = sliderDebugElement.componentInstance; @@ -864,10 +862,6 @@ describe('MDC-based MatSlider' , () => { fixture = createComponent(RangeSliderWithChangeHandler); fixture.detectChanges(); testComponent = fixture.debugElement.componentInstance; - spyOn(testComponent, 'onStartThumbChange'); - spyOn(testComponent, 'onStartThumbInput'); - spyOn(testComponent, 'onEndThumbChange'); - spyOn(testComponent, 'onEndThumbInput'); const sliderDebugElement = fixture.debugElement.query(By.directive(MatSlider)); sliderElement = sliderDebugElement.nativeElement; sliderInstance = sliderDebugElement.componentInstance; @@ -1365,8 +1359,8 @@ class RangeSliderWithOneWayBinding { `, }) class SliderWithChangeHandler { - onChange() { } - onInput() { } + onChange = jasmine.createSpy('onChange'); + onInput = jasmine.createSpy('onChange'); @ViewChild(MatSlider) slider: MatSlider; } @@ -1385,10 +1379,10 @@ class SliderWithChangeHandler { `, }) class RangeSliderWithChangeHandler { - onStartThumbChange() { } - onStartThumbInput() { } - onEndThumbChange() { } - onEndThumbInput() { } + onStartThumbChange = jasmine.createSpy('onStartThumbChange'); + onStartThumbInput = jasmine.createSpy('onStartThumbInput'); + onEndThumbChange = jasmine.createSpy('onEndThumbChange'); + onEndThumbInput = jasmine.createSpy('onEndThumbInput'); @ViewChild(MatSlider) slider: MatSlider; }