Skip to content

Commit 2b8785f

Browse files
committed
test(material-experimental/mdc-slider): add unit tests for sliders with set min and max
* add support for changing the min, max, or step after the component has already been initialized
1 parent 6fd09ef commit 2b8785f

File tree

2 files changed

+149
-9
lines changed

2 files changed

+149
-9
lines changed

src/material-experimental/mdc-slider/slider.spec.ts

Lines changed: 117 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,13 @@ describe('MDC-based MatSlider' , () => {
3737
}
3838

3939
describe('standard slider', () => {
40-
let fixture: ComponentFixture<StandardSlider>;
41-
let sliderDebugElement: DebugElement;
4240
let sliderInstance: MatSlider;
4341
let inputInstance: MatSliderThumb;
4442

4543
beforeEach(waitForAsync(() => {
46-
fixture = createComponent(StandardSlider);
44+
const fixture = createComponent(StandardSlider);
4745
fixture.detectChanges();
48-
sliderDebugElement = fixture.debugElement.query(By.directive(MatSlider));
46+
const sliderDebugElement = fixture.debugElement.query(By.directive(MatSlider));
4947
sliderInstance = sliderDebugElement.componentInstance;
5048
inputInstance = sliderInstance._getInput(Thumb.END);
5149
}));
@@ -364,6 +362,101 @@ describe('MDC-based MatSlider' , () => {
364362
expect(isRippleVisible('focus')).toBeFalse();
365363
}));
366364
});
365+
366+
describe('slider with set min and max', () => {
367+
let fixture: ComponentFixture<SliderWithMinAndMax>;
368+
let sliderInstance: MatSlider;
369+
let inputInstance: MatSliderThumb;
370+
371+
beforeEach(waitForAsync(() => {
372+
fixture = createComponent(SliderWithMinAndMax);
373+
fixture.detectChanges();
374+
const sliderDebugElement = fixture.debugElement.query(By.directive(MatSlider));
375+
sliderInstance = sliderDebugElement.componentInstance;
376+
inputInstance = sliderInstance._getInput(Thumb.END);
377+
}));
378+
379+
it('should set the default values from the attributes', () => {
380+
expect(inputInstance.value).toBe(25);
381+
expect(sliderInstance.min).toBe(25);
382+
expect(sliderInstance.max).toBe(75);
383+
});
384+
385+
it('should set the correct value on mousedown', () => {
386+
setValueByClick(sliderInstance, 33, platform.IOS);
387+
expect(inputInstance.value).toBe(33);
388+
});
389+
390+
it('should set the correct value on slide', () => {
391+
slideToValue(sliderInstance, 55, Thumb.END, platform.IOS);
392+
expect(inputInstance.value).toBe(55);
393+
});
394+
395+
it('should be able to set the min and max values when they are more precise ' +
396+
'than the step', () => {
397+
sliderInstance.step = 10;
398+
fixture.detectChanges();
399+
slideToValue(sliderInstance, 25, Thumb.END, platform.IOS);
400+
expect(inputInstance.value).toBe(25);
401+
slideToValue(sliderInstance, 75, Thumb.END, platform.IOS);
402+
expect(inputInstance.value).toBe(75);
403+
});
404+
});
405+
406+
describe('range slider with set min and max', () => {
407+
let fixture: ComponentFixture<RangeSliderWithMinAndMax>;
408+
let sliderInstance: MatSlider;
409+
let startInputInstance: MatSliderThumb;
410+
let endInputInstance: MatSliderThumb;
411+
412+
beforeEach(waitForAsync(() => {
413+
fixture = createComponent(RangeSliderWithMinAndMax);
414+
fixture.detectChanges();
415+
const sliderDebugElement = fixture.debugElement.query(By.directive(MatSlider));
416+
sliderInstance = sliderDebugElement.componentInstance;
417+
startInputInstance = sliderInstance._getInput(Thumb.START);
418+
endInputInstance = sliderInstance._getInput(Thumb.END);
419+
}));
420+
421+
it('should set the default values from the attributes', () => {
422+
expect(startInputInstance.value).toBe(25);
423+
expect(endInputInstance.value).toBe(75);
424+
expect(sliderInstance.min).toBe(25);
425+
expect(sliderInstance.max).toBe(75);
426+
});
427+
428+
it('should set the correct start value on mousedown behind the start thumb', () => {
429+
sliderInstance._setValue(50, Thumb.START);
430+
setValueByClick(sliderInstance, 33, platform.IOS);
431+
expect(startInputInstance.value).toBe(33);
432+
});
433+
434+
it('should set the correct end value on mousedown behind the end thumb', () => {
435+
sliderInstance._setValue(50, Thumb.END);
436+
setValueByClick(sliderInstance, 66, platform.IOS);
437+
expect(endInputInstance.value).toBe(66);
438+
});
439+
440+
it('should set the correct start value on slide', () => {
441+
slideToValue(sliderInstance, 40, Thumb.START, platform.IOS);
442+
expect(startInputInstance.value).toBe(40);
443+
});
444+
445+
it('should set the correct end value on slide', () => {
446+
slideToValue(sliderInstance, 60, Thumb.END, platform.IOS);
447+
expect(endInputInstance.value).toBe(60);
448+
});
449+
450+
it('should be able to set the min and max values when they are more precise ' +
451+
'than the step', () => {
452+
sliderInstance.step = 10;
453+
fixture.detectChanges();
454+
slideToValue(sliderInstance, 25, Thumb.START, platform.IOS);
455+
expect(startInputInstance.value).toBe(25);
456+
slideToValue(sliderInstance, 75, Thumb.END, platform.IOS);
457+
expect(endInputInstance.value).toBe(75);
458+
});
459+
});
367460
});
368461

369462

@@ -405,6 +498,25 @@ class DisabledSlider {}
405498
})
406499
class DisabledRangeSlider {}
407500

501+
@Component({
502+
template: `
503+
<mat-slider min="25" max="75">
504+
<input matSliderThumb>
505+
</mat-slider>
506+
`,
507+
})
508+
class SliderWithMinAndMax {}
509+
510+
@Component({
511+
template: `
512+
<mat-slider min="25" max="75">
513+
<input matSliderStartThumb>
514+
<input matSliderEndThumb>
515+
</mat-slider>
516+
`,
517+
})
518+
class RangeSliderWithMinAndMax {}
519+
408520
/** The pointer event types used by the MDC Slider. */
409521
const enum PointerEventType {
410522
POINTER_DOWN = 'pointerdown',
@@ -442,7 +554,7 @@ function slideToValue(slider: MatSlider, value: number, thumbPosition: Thumb, is
442554
const thumbElement = slider._getThumbElement(thumbPosition);
443555

444556
const sliderDimensions = sliderElement.getBoundingClientRect();
445-
let thumbDimensions = thumbElement.getBoundingClientRect();
557+
const thumbDimensions = thumbElement.getBoundingClientRect();
446558

447559
const startX = thumbDimensions.left + (thumbDimensions.width / 2);
448560
const startY = thumbDimensions.top + (thumbDimensions.height / 2);

src/material-experimental/mdc-slider/slider.ts

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ export class MatSliderThumb implements AfterViewInit, ControlValueAccessor {
410410
* instead be capped at either the default min or max.
411411
*
412412
*/
413-
private _initializeInputState(): void {
413+
_initializeInputState(): void {
414414
const min = this._hostElement.hasAttribute('matSliderEndThumb')
415415
? this._slider._getInput(Thumb.START).value
416416
: this._slider.min;
@@ -523,19 +523,28 @@ export class MatSlider extends _MatSliderMixinBase implements AfterViewInit, OnD
523523
/** The minimum value that the slider can have. */
524524
@Input()
525525
get min(): number { return this._min; }
526-
set min(v: number) { this._min = coerceNumberProperty(v, this._min); }
526+
set min(v: number) {
527+
this._min = coerceNumberProperty(v, this._min);
528+
this._reinitialize();
529+
}
527530
private _min: number = 0;
528531

529532
/** The maximum value that the slider can have. */
530533
@Input()
531534
get max(): number { return this._max; }
532-
set max(v: number) { this._max = coerceNumberProperty(v, this._max); }
535+
set max(v: number) {
536+
this._max = coerceNumberProperty(v, this._max);
537+
this._reinitialize();
538+
}
533539
private _max: number = 100;
534540

535541
/** The values at which the thumb will snap. */
536542
@Input()
537543
get step(): number { return this._step; }
538-
set step(v: number) { this._step = coerceNumberProperty(v, this._step); }
544+
set step(v: number) {
545+
this._step = coerceNumberProperty(v, this._step);
546+
this._reinitialize();
547+
}
539548
private _step: number = 1;
540549

541550
/**
@@ -611,6 +620,25 @@ export class MatSlider extends _MatSliderMixinBase implements AfterViewInit, OnD
611620
}
612621
}
613622

623+
/**
624+
* Reinitializes the slider foundation and input state(s).
625+
*
626+
* The MDC Foundation does not support changing some slider attributes after it has been
627+
* initialized (e.g. min, max, and step). To continue supporting this feature, we need to
628+
* destroy the foundation and re-initialize everything whenever we make these changes.
629+
*/
630+
private _reinitialize(): void {
631+
if (this._initialized) {
632+
this._foundation.destroy();
633+
if (this._isRange()) {
634+
this._getInput(Thumb.START)._initializeInputState();
635+
}
636+
this._getInput(Thumb.END)._initializeInputState();
637+
this._foundation.init();
638+
this._foundation.layout();
639+
}
640+
}
641+
614642
/** Sets the value of a slider thumb. */
615643
_setValue(value: number, thumbPosition: Thumb): void {
616644
thumbPosition === Thumb.START

0 commit comments

Comments
 (0)