@@ -38,7 +38,6 @@ describe('MdSlider', () => {
38
38
let sliderDimensions : ClientRect ;
39
39
let thumbElement : HTMLElement ;
40
40
let thumbDimensions : ClientRect ;
41
- let thumbWidth : number ;
42
41
43
42
beforeEach ( async ( ( ) => {
44
43
builder . createAsync ( StandardSlider ) . then ( f => {
@@ -56,8 +55,6 @@ describe('MdSlider', () => {
56
55
57
56
thumbElement = < HTMLElement > sliderNativeElement . querySelector ( '.md-slider-thumb-position' ) ;
58
57
thumbDimensions = thumbElement . getBoundingClientRect ( ) ;
59
- thumbWidth =
60
- sliderNativeElement . querySelector ( '.md-slider-thumb' ) . getBoundingClientRect ( ) . width ;
61
58
} ) ;
62
59
} ) ) ;
63
60
@@ -71,16 +68,14 @@ describe('MdSlider', () => {
71
68
expect ( sliderInstance . value ) . toBe ( 0 ) ;
72
69
dispatchClickEvent ( sliderTrackElement , 0.19 ) ;
73
70
// The expected value is 19 from: percentage * difference of max and min.
74
- let difference = Math . abs ( sliderInstance . value - 19 ) ;
75
- expect ( difference ) . toBeLessThan ( 1 ) ;
71
+ expect ( sliderInstance . value ) . toBe ( 19 ) ;
76
72
} ) ;
77
73
78
74
it ( 'should update the value on a drag' , ( ) => {
79
75
expect ( sliderInstance . value ) . toBe ( 0 ) ;
80
76
dispatchDragEvent ( sliderTrackElement , sliderNativeElement , 0 , 0.89 , gestureConfig ) ;
81
77
// The expected value is 89 from: percentage * difference of max and min.
82
- let difference = Math . abs ( sliderInstance . value - 89 ) ;
83
- expect ( difference ) . toBeLessThan ( 1 ) ;
78
+ expect ( sliderInstance . value ) . toBe ( 89 ) ;
84
79
} ) ;
85
80
86
81
it ( 'should set the value as min when dragging before the track' , ( ) => {
@@ -100,40 +95,49 @@ describe('MdSlider', () => {
100
95
dispatchClickEvent ( sliderTrackElement , 0.39 ) ;
101
96
102
97
trackFillDimensions = trackFillElement . getBoundingClientRect ( ) ;
103
- // The fill should be close to the slider's width * the percentage from the click.
104
- let difference = Math . abs ( trackFillDimensions . width - ( sliderDimensions . width * 0.39 ) ) ;
105
- expect ( difference ) . toBeLessThan ( 1 ) ;
98
+ thumbDimensions = thumbElement . getBoundingClientRect ( ) ;
99
+
100
+ // The thumb and track fill positions are relative to the viewport, so to get the thumb's
101
+ // offset relative to the track, subtract the offset on the track fill.
102
+ let thumbPosition = thumbDimensions . left - trackFillDimensions . left ;
103
+ // The track fill width should be equal to the thumb's position.
104
+ expect ( Math . round ( trackFillDimensions . width ) ) . toBe ( Math . round ( thumbPosition ) ) ;
106
105
} ) ;
107
106
108
107
it ( 'should update the thumb position on click' , ( ) => {
109
- expect ( thumbDimensions . left ) . toBe ( sliderDimensions . left - ( thumbWidth / 2 ) ) ;
110
- dispatchClickEvent ( sliderTrackElement , 0.16 ) ;
108
+ expect ( thumbDimensions . left ) . toBe ( sliderDimensions . left ) ;
109
+ // 50% is used here because the click event that is dispatched truncates the position and so
110
+ // a value had to be used that would not be truncated.
111
+ dispatchClickEvent ( sliderTrackElement , 0.5 ) ;
111
112
112
113
thumbDimensions = thumbElement . getBoundingClientRect ( ) ;
113
- // The thumb's offset is expected to be equal to the slider's offset + 0.16 * the slider's
114
- // width - half the thumb width (to center the thumb).
115
- let offset = sliderDimensions . left + ( sliderDimensions . width * 0.16 ) - ( thumbWidth / 2 ) ;
116
- let difference = Math . abs ( thumbDimensions . left - offset ) ;
117
- expect ( difference ) . toBeLessThan ( 1 ) ;
114
+ // The thumb position should be at 50% of the slider's width + the offset of the slider.
115
+ // Both the thumb and the slider are affected by this offset.
116
+ expect ( thumbDimensions . left ) . toBe ( sliderDimensions . width * 0.5 + sliderDimensions . left ) ;
118
117
} ) ;
119
118
120
119
it ( 'should update the track fill on drag' , ( ) => {
121
120
expect ( trackFillDimensions . width ) . toBe ( 0 ) ;
122
121
dispatchDragEvent ( sliderTrackElement , sliderNativeElement , 0 , 0.86 , gestureConfig ) ;
123
122
124
123
trackFillDimensions = trackFillElement . getBoundingClientRect ( ) ;
125
- let difference = Math . abs ( trackFillDimensions . width - ( sliderDimensions . width * 0.86 ) ) ;
126
- expect ( difference ) . toBeLessThan ( 1 ) ;
124
+ thumbDimensions = thumbElement . getBoundingClientRect ( ) ;
125
+
126
+ // The thumb and track fill positions are relative to the viewport, so to get the thumb's
127
+ // offset relative to the track, subtract the offset on the track fill.
128
+ let thumbPosition = thumbDimensions . left - trackFillDimensions . left ;
129
+ // The track fill width should be equal to the thumb's position.
130
+ expect ( Math . round ( trackFillDimensions . width ) ) . toBe ( Math . round ( thumbPosition ) ) ;
127
131
} ) ;
128
132
129
133
it ( 'should update the thumb position on drag' , ( ) => {
130
- expect ( thumbDimensions . left ) . toBe ( sliderDimensions . left - ( thumbWidth / 2 ) ) ;
131
- dispatchDragEvent ( sliderTrackElement , sliderNativeElement , 0 , 0.27 , gestureConfig ) ;
134
+ expect ( thumbDimensions . left ) . toBe ( sliderDimensions . left ) ;
135
+ // The drag event also truncates the position passed in, so 50% is used here as well to
136
+ // ensure the ability to calculate the expected position.
137
+ dispatchDragEvent ( sliderTrackElement , sliderNativeElement , 0 , 0.5 , gestureConfig ) ;
132
138
133
139
thumbDimensions = thumbElement . getBoundingClientRect ( ) ;
134
- let offset = sliderDimensions . left + ( sliderDimensions . width * 0.27 ) - ( thumbWidth / 2 ) ;
135
- let difference = Math . abs ( thumbDimensions . left - offset ) ;
136
- expect ( difference ) . toBeLessThan ( 1 ) ;
140
+ expect ( thumbDimensions . left ) . toBe ( sliderDimensions . width * 0.5 + sliderDimensions . left ) ;
137
141
} ) ;
138
142
139
143
it ( 'should add the md-slider-active class on click' , ( ) => {
@@ -237,6 +241,9 @@ describe('MdSlider', () => {
237
241
let sliderNativeElement : HTMLElement ;
238
242
let sliderInstance : MdSlider ;
239
243
let sliderTrackElement : HTMLElement ;
244
+ let sliderDimensions : ClientRect ;
245
+ let trackFillElement : HTMLElement ;
246
+ let thumbElement : HTMLElement ;
240
247
241
248
beforeEach ( async ( ( ) => {
242
249
builder . createAsync ( SliderWithMinAndMax ) . then ( f => {
@@ -247,31 +254,62 @@ describe('MdSlider', () => {
247
254
sliderNativeElement = sliderDebugElement . nativeElement ;
248
255
sliderInstance = sliderDebugElement . injector . get ( MdSlider ) ;
249
256
sliderTrackElement = < HTMLElement > sliderNativeElement . querySelector ( '.md-slider-track' ) ;
257
+ sliderDimensions = sliderTrackElement . getBoundingClientRect ( ) ;
258
+ trackFillElement = < HTMLElement > sliderNativeElement . querySelector ( '.md-slider-track-fill' ) ;
259
+ thumbElement = < HTMLElement > sliderNativeElement . querySelector ( '.md-slider-thumb-position' ) ;
250
260
} ) ;
251
261
} ) ) ;
252
262
253
263
it ( 'should set the default values from the attributes' , ( ) => {
254
- expect ( sliderInstance . value ) . toBe ( 5 ) ;
255
- expect ( sliderInstance . min ) . toBe ( 5 ) ;
256
- expect ( sliderInstance . max ) . toBe ( 15 ) ;
264
+ expect ( sliderInstance . value ) . toBe ( 4 ) ;
265
+ expect ( sliderInstance . min ) . toBe ( 4 ) ;
266
+ expect ( sliderInstance . max ) . toBe ( 6 ) ;
257
267
} ) ;
258
268
259
269
it ( 'should set the correct value on click' , ( ) => {
260
270
dispatchClickEvent ( sliderTrackElement , 0.09 ) ;
261
271
// Computed by multiplying the difference between the min and the max by the percentage from
262
272
// the click and adding that to the minimum.
263
- let value = 5 + ( 0.09 * ( 15 - 5 ) ) ;
264
- let difference = Math . abs ( sliderInstance . value - value ) ;
265
- expect ( difference ) . toBeLessThan ( 1 ) ;
273
+ let value = Math . round ( 4 + ( 0.09 * ( 6 - 4 ) ) ) ;
274
+ expect ( sliderInstance . value ) . toBe ( value ) ;
266
275
} ) ;
267
276
268
277
it ( 'should set the correct value on drag' , ( ) => {
269
278
dispatchDragEvent ( sliderTrackElement , sliderNativeElement , 0 , 0.62 , gestureConfig ) ;
270
279
// Computed by multiplying the difference between the min and the max by the percentage from
271
280
// the click and adding that to the minimum.
272
- let value = 5 + ( 0.62 * ( 15 - 5 ) ) ;
273
- let difference = Math . abs ( sliderInstance . value - value ) ;
274
- expect ( difference ) . toBeLessThan ( 1 ) ;
281
+ let value = Math . round ( 4 + ( 0.62 * ( 6 - 4 ) ) ) ;
282
+ expect ( sliderInstance . value ) . toBe ( value ) ;
283
+ } ) ;
284
+
285
+ it ( 'should snap the thumb and fill to the nearest value on click' , ( ) => {
286
+ dispatchClickEvent ( sliderTrackElement , 0.68 ) ;
287
+ fixture . detectChanges ( ) ;
288
+
289
+ let trackFillDimensions = trackFillElement . getBoundingClientRect ( ) ;
290
+ let thumbDimensions = thumbElement . getBoundingClientRect ( ) ;
291
+ let thumbPosition = thumbDimensions . left - trackFillDimensions . left ;
292
+
293
+ // The closest snap is halfway on the slider.
294
+ expect ( thumbDimensions . left ) . toBe ( sliderDimensions . width * 0.5 + sliderDimensions . left ) ;
295
+ expect ( Math . round ( trackFillDimensions . width ) ) . toBe ( Math . round ( thumbPosition ) ) ;
296
+ } ) ;
297
+
298
+ it ( 'should snap the thumb and fill to the nearest value on drag' , ( ) => {
299
+ dispatchDragEvent ( sliderTrackElement , sliderNativeElement , 0 , 0.74 , gestureConfig ) ;
300
+ fixture . detectChanges ( ) ;
301
+
302
+ dispatchDragEndEvent ( sliderNativeElement , 0.74 , gestureConfig ) ;
303
+ fixture . detectChanges ( ) ;
304
+
305
+ let trackFillDimensions = trackFillElement . getBoundingClientRect ( ) ;
306
+ let thumbDimensions = thumbElement . getBoundingClientRect ( ) ;
307
+ let thumbPosition = thumbDimensions . left - trackFillDimensions . left ;
308
+
309
+ // The closest snap is at the halfway point on the slider.
310
+ expect ( thumbDimensions . left ) . toBe ( sliderDimensions . left + sliderDimensions . width * 0.5 ) ;
311
+ expect ( Math . round ( trackFillDimensions . width ) ) . toBe ( Math . round ( thumbPosition ) ) ;
312
+
275
313
} ) ;
276
314
} ) ;
277
315
@@ -302,16 +340,85 @@ describe('MdSlider', () => {
302
340
dispatchClickEvent ( sliderTrackElement , 0.92 ) ;
303
341
// On a slider with default max and min the value should be approximately equal to the
304
342
// percentage clicked. This should be the case regardless of what the original set value was.
305
- let value = 92 ;
306
- let difference = Math . abs ( sliderInstance . value - value ) ;
307
- expect ( difference ) . toBeLessThan ( 1 ) ;
343
+ expect ( sliderInstance . value ) . toBe ( 92 ) ;
308
344
} ) ;
309
345
310
346
it ( 'should set the correct value on drag' , ( ) => {
311
347
dispatchDragEvent ( sliderTrackElement , sliderNativeElement , 0 , 0.32 , gestureConfig ) ;
312
348
expect ( sliderInstance . value ) . toBe ( 32 ) ;
313
349
} ) ;
314
350
} ) ;
351
+
352
+ describe ( 'slider with set step' , ( ) => {
353
+ let fixture : ComponentFixture < SliderWithStep > ;
354
+ let sliderDebugElement : DebugElement ;
355
+ let sliderNativeElement : HTMLElement ;
356
+ let sliderInstance : MdSlider ;
357
+ let sliderTrackElement : HTMLElement ;
358
+ let sliderDimensions : ClientRect ;
359
+ let trackFillElement : HTMLElement ;
360
+ let thumbElement : HTMLElement ;
361
+
362
+ beforeEach ( async ( ( ) => {
363
+ builder . createAsync ( SliderWithStep ) . then ( f => {
364
+ fixture = f ;
365
+ fixture . detectChanges ( ) ;
366
+
367
+ sliderDebugElement = fixture . debugElement . query ( By . directive ( MdSlider ) ) ;
368
+ sliderNativeElement = sliderDebugElement . nativeElement ;
369
+ sliderInstance = sliderDebugElement . injector . get ( MdSlider ) ;
370
+ sliderTrackElement = < HTMLElement > sliderNativeElement . querySelector ( '.md-slider-track' ) ;
371
+ sliderDimensions = sliderTrackElement . getBoundingClientRect ( ) ;
372
+ trackFillElement = < HTMLElement > sliderNativeElement . querySelector ( '.md-slider-track-fill' ) ;
373
+ thumbElement = < HTMLElement > sliderNativeElement . querySelector ( '.md-slider-thumb-position' ) ;
374
+ } ) ;
375
+ } ) ) ;
376
+
377
+ it ( 'should set the correct step value on click' , ( ) => {
378
+ expect ( sliderInstance . value ) . toBe ( 0 ) ;
379
+
380
+ dispatchClickEvent ( sliderTrackElement , 0.13 ) ;
381
+ fixture . detectChanges ( ) ;
382
+
383
+ expect ( sliderInstance . value ) . toBe ( 25 ) ;
384
+ } ) ;
385
+
386
+ it ( 'should snap the thumb and fill to a step on click' , ( ) => {
387
+ dispatchClickEvent ( sliderNativeElement , 0.66 ) ;
388
+ fixture . detectChanges ( ) ;
389
+
390
+ let trackFillDimensions = trackFillElement . getBoundingClientRect ( ) ;
391
+ let thumbDimensions = thumbElement . getBoundingClientRect ( ) ;
392
+ let thumbPosition = thumbDimensions . left - trackFillDimensions . left ;
393
+
394
+ // The closest step is at 75% of the slider.
395
+ expect ( thumbDimensions . left ) . toBe ( sliderDimensions . width * 0.75 + sliderDimensions . left ) ;
396
+ expect ( Math . round ( trackFillDimensions . width ) ) . toBe ( Math . round ( thumbPosition ) ) ;
397
+ } ) ;
398
+
399
+ it ( 'should set the correct step value on drag' , ( ) => {
400
+ dispatchDragEvent ( sliderTrackElement , sliderNativeElement , 0 , 0.07 , gestureConfig ) ;
401
+ fixture . detectChanges ( ) ;
402
+
403
+ expect ( sliderInstance . value ) . toBe ( 0 ) ;
404
+ } ) ;
405
+
406
+ it ( 'should snap the thumb and fill to a step on drag' , ( ) => {
407
+ dispatchDragEvent ( sliderTrackElement , sliderNativeElement , 0 , 0.88 , gestureConfig ) ;
408
+ fixture . detectChanges ( ) ;
409
+
410
+ dispatchDragEndEvent ( sliderNativeElement , 0.88 , gestureConfig ) ;
411
+ fixture . detectChanges ( ) ;
412
+
413
+ let trackFillDimensions = trackFillElement . getBoundingClientRect ( ) ;
414
+ let thumbDimensions = thumbElement . getBoundingClientRect ( ) ;
415
+ let thumbPosition = thumbDimensions . left - trackFillDimensions . left ;
416
+
417
+ // The closest snap is at the end of the slider.
418
+ expect ( thumbDimensions . left ) . toBe ( sliderDimensions . width + sliderDimensions . left ) ;
419
+ expect ( Math . round ( trackFillDimensions . width ) ) . toBe ( Math . round ( thumbPosition ) ) ;
420
+ } ) ;
421
+ } ) ;
315
422
} ) ;
316
423
317
424
// The transition has to be removed in order to test the updated positions without setTimeout.
@@ -335,7 +442,13 @@ class DisabledSlider { }
335
442
336
443
@Component ( {
337
444
directives : [ MD_SLIDER_DIRECTIVES ] ,
338
- template : `<md-slider min="5" max="15"></md-slider>`
445
+ template : `<md-slider min="4" max="6"></md-slider>` ,
446
+ styles : [ `
447
+ .md-slider-track-fill, .md-slider-thumb-position {
448
+ transition: none !important;
449
+ }
450
+ ` ] ,
451
+ encapsulation : ViewEncapsulation . None
339
452
} )
340
453
class SliderWithMinAndMax { }
341
454
@@ -345,8 +458,21 @@ class SliderWithMinAndMax { }
345
458
} )
346
459
class SliderWithValue { }
347
460
461
+ @Component ( {
462
+ directives : [ MD_SLIDER_DIRECTIVES ] ,
463
+ template : `<md-slider step="25"></md-slider>` ,
464
+ styles : [ `
465
+ .md-slider-track-fill, .md-slider-thumb-position {
466
+ transition: none !important;
467
+ }
468
+ ` ] ,
469
+ encapsulation : ViewEncapsulation . None
470
+ } )
471
+ class SliderWithStep { }
472
+
348
473
/**
349
474
* Dispatches a click event from an element.
475
+ * Note: The mouse event truncates the position for the click.
350
476
* @param element The element from which the event will be dispatched.
351
477
* @param percentage The percentage of the slider where the click should occur. Used to find the
352
478
* physical location of the click.
0 commit comments