Skip to content

Commit cdf00b4

Browse files
committed
Finish tests for slider
1 parent 0632795 commit cdf00b4

File tree

2 files changed

+246
-31
lines changed

2 files changed

+246
-31
lines changed

src/components/slider/slider.spec.ts

Lines changed: 244 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
11
import {
22
it,
3-
iit,
43
describe,
54
beforeEach,
65
beforeEachProviders,
76
inject,
87
async,
9-
fakeAsync,
10-
tick,
118
} from '@angular/core/testing';
129
import {TestComponentBuilder, ComponentFixture} from '@angular/compiler/testing';
13-
import {Component, DebugElement, provide} from '@angular/core';
10+
import {Component, DebugElement, provide, ViewEncapsulation} from '@angular/core';
1411
import {By} from '@angular/platform-browser';
1512
import {MdSlider} from './slider';
1613
import {HAMMER_GESTURE_CONFIG} from '@angular/platform-browser';
@@ -60,7 +57,7 @@ describe('MdSlider', () => {
6057
it('should update the value on a click', () => {
6158
expect(sliderInstance.value).toBe(0);
6259
dispatchClickEvent(sliderNativeElement, 0.5);
63-
// 50% is the same as the value 50 in this case (0 -> 100, middle = 50).
60+
// 50% is the same as the value 50 in this case.
6461
expect(sliderInstance.value).toBe(50);
6562
});
6663

@@ -70,34 +67,158 @@ describe('MdSlider', () => {
7067
expect(sliderInstance.value).toBe(50);
7168
});
7269

73-
iit('should update the track fill on click', fakeAsync(() => {
74-
let trackFillDimensions =
75-
sliderNativeElement.querySelector('.md-slider-track-fill').getBoundingClientRect();
70+
it('should set the value as min when dragging before the track', () => {
71+
expect(sliderInstance.value).toBe(0);
72+
dispatchDragEvent(sliderNativeElement, 0, -1.5, gestureConfig);
73+
expect(sliderInstance.value).toBe(0);
74+
});
75+
76+
it('should set the value as max when dragging past the track', () => {
77+
expect(sliderInstance.value).toBe(0);
78+
dispatchDragEvent(sliderNativeElement, 0, 1.5, gestureConfig);
79+
expect(sliderInstance.value).toBe(100);
80+
});
81+
82+
it('should update the track fill on click', () => {
83+
let trackFillElement = sliderNativeElement.querySelector('.md-slider-track-fill');
84+
let trackFillDimensions = trackFillElement.getBoundingClientRect();
7685
let sliderDimensions =
7786
sliderNativeElement.querySelector('.md-slider-track').getBoundingClientRect();
87+
7888
expect(trackFillDimensions.width).toBe(0);
89+
dispatchClickEvent(sliderNativeElement, 0.5);
90+
91+
trackFillDimensions = trackFillElement.getBoundingClientRect();
92+
expect(trackFillDimensions.width).toBe(sliderDimensions.width * 0.5);
93+
});
94+
95+
it('should update the thumb position on click', () => {
96+
let thumbElement = sliderNativeElement.querySelector('.md-slider-thumb-position');
97+
let thumbDimensions = thumbElement.getBoundingClientRect();
98+
let thumbWidth =
99+
sliderNativeElement.querySelector('.md-slider-thumb').getBoundingClientRect().width;
100+
let sliderDimensions =
101+
sliderNativeElement.querySelector('.md-slider-track').getBoundingClientRect();
102+
103+
expect(thumbDimensions.left).toBe(sliderDimensions.left - (thumbWidth / 2));
104+
dispatchClickEvent(sliderNativeElement, 0.5);
105+
106+
thumbDimensions = thumbElement.getBoundingClientRect();
107+
// The thumb's offset is expected to be equal to the slider's offset + half the slider's width
108+
// (from the click event) - half the thumb width (to center the thumb).
109+
let offset = sliderDimensions.left + (sliderDimensions.width * 0.5) - (thumbWidth / 2);
110+
expect(thumbDimensions.left).toBe(offset);
111+
});
112+
113+
it('should add the md-slider-active class on click', () => {
114+
let containerElement = sliderNativeElement.querySelector('.md-slider-container');
115+
expect(containerElement.classList).not.toContain('md-slider-active');
116+
79117
dispatchClickEvent(sliderNativeElement, 0.5);
80118
fixture.detectChanges();
81-
tick();
82-
tick();
83119

84-
let test = sliderNativeElement.querySelector('.md-slider-track-fill');
85-
let testDimensions = test.getBoundingClientRect();
120+
expect(containerElement.classList).toContain('md-slider-active');
121+
});
122+
123+
it('should remove the md-slider-active class on blur', () => {
124+
let containerElement = sliderNativeElement.querySelector('.md-slider-container');
125+
126+
dispatchClickEvent(sliderNativeElement, 0.5);
127+
fixture.detectChanges();
128+
129+
expect(containerElement.classList).toContain('md-slider-active');
130+
131+
// The test won't activate the onBlur function. Tried clicking/focusing the body and neither
132+
// worked. Should update this if a way is ever found.
133+
sliderInstance.onBlur();
134+
fixture.detectChanges();
135+
136+
expect(containerElement.classList).not.toContain('md-slider-active');
137+
});
138+
139+
it('should add and remove the md-slider-dragging class when dragging', () => {
140+
let containerElement = sliderNativeElement.querySelector('.md-slider-container');
141+
let classes = containerElement.classList;
142+
expect(classes).not.toContain('md-slider-dragging');
143+
144+
dispatchDragStartEvent(sliderNativeElement, 0, gestureConfig);
145+
fixture.detectChanges();
146+
147+
expect(containerElement.classList).toContain('md-slider-dragging');
148+
149+
dispatchDragEndEvent(sliderNativeElement, 0.5, gestureConfig);
150+
fixture.detectChanges();
151+
152+
expect(containerElement.classList).not.toContain('md-slider-dragging');
153+
});
154+
});
86155

87-
console.log(testDimensions.width);
88-
expect(testDimensions.width).toBe(sliderDimensions.width * 0.5);
156+
describe('disabled slider', () => {
157+
let fixture: ComponentFixture<DisabledSlider>;
158+
let sliderDebugElement: DebugElement;
159+
let sliderNativeElement: HTMLElement;
160+
let sliderInstance: MdSlider;
161+
let testComponent: DisabledSlider;
162+
163+
beforeEach(async(() => {
164+
builder.createAsync(DisabledSlider).then(f => {
165+
fixture = f;
166+
fixture.detectChanges();
167+
168+
testComponent = fixture.debugElement.componentInstance;
169+
170+
sliderDebugElement = fixture.debugElement.query(By.directive(MdSlider));
171+
sliderNativeElement = sliderDebugElement.nativeElement;
172+
sliderInstance = sliderDebugElement.injector.get(MdSlider);
173+
});
89174
}));
175+
176+
it('should be disabled', () => {
177+
expect(sliderInstance.disabled).toBeTruthy();
178+
});
179+
180+
it('should not change the value on click when disabled', () => {
181+
expect(sliderInstance.value).toBe(0);
182+
dispatchClickEvent(sliderNativeElement, 0.5);
183+
expect(sliderInstance.value).toBe(0);
184+
});
185+
186+
it('should not change the value on drag when disabled', () => {
187+
expect(sliderInstance.value).toBe(0);
188+
dispatchDragEvent(sliderNativeElement, 0, 0.5, gestureConfig);
189+
expect(sliderInstance.value).toBe(0);
190+
});
191+
192+
it('should not add the md-slider-active class on click when disabled', () => {
193+
let containerElement = sliderNativeElement.querySelector('.md-slider-container');
194+
expect(containerElement.classList).not.toContain('md-slider-active');
195+
196+
dispatchClickEvent(sliderNativeElement, 0.5);
197+
fixture.detectChanges();
198+
199+
expect(containerElement.classList).not.toContain('md-slider-active');
200+
});
201+
202+
it('should not add the md-slider-dragging class on drag when disabled', () => {
203+
let containerElement = sliderNativeElement.querySelector('.md-slider-container');
204+
expect(containerElement.classList).not.toContain('md-slider-dragging');
205+
206+
dispatchDragStartEvent(sliderNativeElement, 0.5, gestureConfig);
207+
fixture.detectChanges();
208+
209+
expect(containerElement.classList).not.toContain('md-slider-dragging');
210+
});
90211
});
91212

92-
describe('min max disabled slider', () => {
93-
let fixture: ComponentFixture<MinMaxDisabledSlider>;
213+
describe('slider with set min and max', () => {
214+
let fixture: ComponentFixture<SliderWithMinAndMax>;
94215
let sliderDebugElement: DebugElement;
95216
let sliderNativeElement: HTMLElement;
96217
let sliderInstance: MdSlider;
97-
let testComponent: MinMaxDisabledSlider;
218+
let testComponent: SliderWithMinAndMax;
98219

99220
beforeEach(async(() => {
100-
builder.createAsync(MinMaxDisabledSlider).then(f => {
221+
builder.createAsync(SliderWithMinAndMax).then(f => {
101222
fixture = f;
102223
fixture.detectChanges();
103224

@@ -113,39 +234,95 @@ describe('MdSlider', () => {
113234
expect(sliderInstance.value).toBe(5);
114235
expect(sliderInstance.min).toBe(5);
115236
expect(sliderInstance.max).toBe(15);
116-
expect(sliderInstance.disabled).toBeTruthy();
117237
});
118238

119-
it('should not change the value on click when disabled', () => {
120-
expect(sliderInstance.value).toBe(5);
239+
it('should set the correct value on click', () => {
121240
dispatchClickEvent(sliderNativeElement, 0.5);
122-
expect(sliderInstance.value).toBe(5);
241+
// 50% of the slider would be 10 given a min of 5 and a max of 15. (5 + 15) / 2 = 10
242+
expect(sliderInstance.value).toBe(10);
123243
});
124244

125-
it('should not change the value on drag when disabled', () => {
126-
expect(sliderInstance.value).toBe(5);
245+
it('should set the correct value on drag', () => {
127246
dispatchDragEvent(sliderNativeElement, 0, 0.5, gestureConfig);
128-
expect(sliderInstance.value).toBe(5);
247+
expect(sliderInstance.value).toBe(10);
129248
});
130249
});
131-
});
132250

251+
describe('slider with set value', () => {
252+
let fixture: ComponentFixture<SliderWithValue>;
253+
let sliderDebugElement: DebugElement;
254+
let sliderNativeElement: HTMLElement;
255+
let sliderInstance: MdSlider;
256+
let testComponent: SliderWithValue;
257+
258+
beforeEach(async(() => {
259+
builder.createAsync(SliderWithValue).then(f => {
260+
fixture = f;
261+
fixture.detectChanges();
133262

263+
testComponent = fixture.debugElement.componentInstance;
264+
265+
sliderDebugElement = fixture.debugElement.query(By.directive(MdSlider));
266+
sliderNativeElement = sliderDebugElement.nativeElement;
267+
sliderInstance = sliderDebugElement.injector.get(MdSlider);
268+
});
269+
}));
270+
271+
it('should set the default value from the attribute', () => {
272+
expect(sliderInstance.value).toBe(26);
273+
});
274+
275+
it('should set the correct value on click', () => {
276+
dispatchClickEvent(sliderNativeElement, 0.5);
277+
// It should still be 50 regardless of what the original value was.
278+
expect(sliderInstance.value).toBe(50);
279+
});
280+
281+
it('should set the correct value on drag', () => {
282+
dispatchDragEvent(sliderNativeElement, 0, 0.5, gestureConfig);
283+
expect(sliderInstance.value).toBe(50);
284+
});
285+
});
286+
});
287+
288+
// The transition has to be removed in order to test the updated positions without setTimeout.
134289
@Component({
135290
directives: [[MdSlider]],
136291
template: `
137292
<md-slider></md-slider>
138-
`
293+
`,
294+
styles: [`
295+
.md-slider-track-fill, .md-slider-thumb-position {
296+
transition: none !important;
297+
}
298+
`],
299+
encapsulation: ViewEncapsulation.None
139300
})
140301
class StandardSlider { }
141302

142303
@Component({
143304
directives: [[MdSlider]],
144305
template: `
145-
<md-slider min="5" max="15" disabled></md-slider>
306+
<md-slider disabled></md-slider>
146307
`
147308
})
148-
class MinMaxDisabledSlider { }
309+
class DisabledSlider { }
310+
311+
@Component({
312+
directives: [[MdSlider]],
313+
template: `
314+
<md-slider min="5" max="15"></md-slider>
315+
`
316+
})
317+
class SliderWithMinAndMax { }
318+
319+
@Component({
320+
directives: [[MdSlider]],
321+
template: `
322+
<md-slider value="26"></md-slider>
323+
`
324+
})
325+
class SliderWithValue { }
149326

150327
/**
151328
* Dispatches a click event from an element.
@@ -193,3 +370,41 @@ function dispatchDragEvent(element: HTMLElement, startPercent: number, endPercen
193370
srcEvent: { preventDefault: jasmine.createSpy('preventDefault') }
194371
});
195372
}
373+
374+
/**
375+
* Dispatches a dragstart event from an element.
376+
* @param element The element from which the event will be dispatched.
377+
* @param startPercent The percentage of the slider where the drag will begin.
378+
* @param gestureConfig The gesture config for the test to handle emitting the drag events.
379+
*/
380+
function dispatchDragStartEvent(element: HTMLElement, startPercent: number,
381+
gestureConfig: TestGestureConfig): void {
382+
let dimensions = element.getBoundingClientRect();
383+
let width = dimensions.width;
384+
let left = dimensions.left;
385+
let x = left + (width * startPercent);
386+
387+
gestureConfig.emitEventForElement('dragstart', element, {
388+
center: { x: x },
389+
srcEvent: { preventDefault: jasmine.createSpy('preventDefault') }
390+
});
391+
}
392+
393+
/**
394+
* Dispatches a dragend event from an element.
395+
* @param element The element from which the event will be dispatched.
396+
* @param endPercent The percentage of the slider where the drag will end.
397+
* @param gestureConfig The gesture config for the test to handle emitting the drag events.
398+
*/
399+
function dispatchDragEndEvent(element: HTMLElement, endPercent: number,
400+
gestureConfig: TestGestureConfig): void {
401+
let dimensions = element.getBoundingClientRect();
402+
let width = dimensions.width;
403+
let left = dimensions.left;
404+
let x = left + (width * endPercent);
405+
406+
gestureConfig.emitEventForElement('dragend', element, {
407+
center: { x: x },
408+
srcEvent: { preventDefault: jasmine.createSpy('preventDefault') }
409+
});
410+
}

src/components/slider/slider.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ export class MdSlider implements AfterContentInit {
105105
}
106106

107107
set value(v: number) {
108-
this._value = v;
108+
this._value = Number(v);
109109
this._isValueInitialized = true;
110110
this.updatePercentFromValue();
111111
}
@@ -197,7 +197,7 @@ export class MdSlider implements AfterContentInit {
197197
}
198198

199199
/**
200-
* Return a number between the given or default min and max.
200+
* Return a number between two numbers.
201201
*/
202202
clamp(value: number, min = 0, max = 1) {
203203
return Math.max(min, Math.min(value, max));

0 commit comments

Comments
 (0)