Skip to content

Commit bb500b7

Browse files
devversionmmalerba
authored andcommitted
tests(checkbox, slide-toggle): use fakeAsync instead of whenStable (#5547)
* Most of the `whenStable()` promise calls can be replaced with the `flushMicrotasks` method, which just flushes them instead of waiting for them to really happen (when using `async`). * This reduces nesting of functions and also makes the tests in theory faster.
1 parent 24035b0 commit bb500b7

File tree

2 files changed

+68
-52
lines changed

2 files changed

+68
-52
lines changed

src/lib/checkbox/checkbox.spec.ts

Lines changed: 46 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ describe('MdCheckbox', () => {
102102
expect(inputElement.indeterminate).toBe(false);
103103
});
104104

105-
it('should set indeterminate to false when input clicked', async(() => {
105+
it('should set indeterminate to false when input clicked', fakeAsync(() => {
106106
testComponent.isIndeterminate = true;
107107
fixture.detectChanges();
108108

@@ -113,33 +113,40 @@ describe('MdCheckbox', () => {
113113
inputElement.click();
114114
fixture.detectChanges();
115115

116-
fixture.whenStable().then(() => {
117-
fixture.detectChanges();
118-
expect(checkboxInstance.checked).toBe(true);
119-
expect(inputElement.indeterminate).toBe(false);
120-
expect(inputElement.checked).toBe(true);
121-
expect(testComponent.isIndeterminate).toBe(false);
116+
// Flush the microtasks because the forms module updates the model state asynchronously.
117+
flushMicrotasks();
122118

123-
testComponent.isIndeterminate = true;
124-
fixture.detectChanges();
119+
// The checked property has been updated from the model and now the view needs
120+
// to reflect the state change.
121+
fixture.detectChanges();
125122

126-
expect(checkboxInstance.indeterminate).toBe(true);
127-
expect(inputElement.indeterminate).toBe(true);
128-
expect(inputElement.checked).toBe(true);
129-
expect(testComponent.isIndeterminate).toBe(true);
123+
expect(checkboxInstance.checked).toBe(true);
124+
expect(inputElement.indeterminate).toBe(false);
125+
expect(inputElement.checked).toBe(true);
126+
expect(testComponent.isIndeterminate).toBe(false);
130127

131-
inputElement.click();
132-
fixture.detectChanges();
128+
testComponent.isIndeterminate = true;
129+
fixture.detectChanges();
133130

134-
fixture.whenStable().then(() => {
135-
fixture.detectChanges();
136-
expect(checkboxInstance.checked).toBe(false);
137-
expect(inputElement.indeterminate).toBe(false);
138-
expect(inputElement.checked).toBe(false);
139-
expect(testComponent.isIndeterminate).toBe(false);
140-
});
141-
});
131+
expect(checkboxInstance.indeterminate).toBe(true);
132+
expect(inputElement.indeterminate).toBe(true);
133+
expect(inputElement.checked).toBe(true);
134+
expect(testComponent.isIndeterminate).toBe(true);
135+
136+
inputElement.click();
137+
fixture.detectChanges();
142138

139+
// Flush the microtasks because the forms module updates the model state asynchronously.
140+
flushMicrotasks();
141+
142+
// The checked property has been updated from the model and now the view needs
143+
// to reflect the state change.
144+
fixture.detectChanges();
145+
146+
expect(checkboxInstance.checked).toBe(false);
147+
expect(inputElement.indeterminate).toBe(false);
148+
expect(inputElement.checked).toBe(false);
149+
expect(testComponent.isIndeterminate).toBe(false);
143150
}));
144151

145152
it('should not set indeterminate to false when checked is set programmatically', async(() => {
@@ -190,7 +197,7 @@ describe('MdCheckbox', () => {
190197
expect(checkboxInstance.checked).toBe(false);
191198
});
192199

193-
it('should change from indeterminate to checked on click', async(() => {
200+
it('should change from indeterminate to checked on click', fakeAsync(() => {
194201
testComponent.isChecked = false;
195202
testComponent.isIndeterminate = true;
196203
fixture.detectChanges();
@@ -200,16 +207,17 @@ describe('MdCheckbox', () => {
200207

201208
checkboxInstance._onInputClick(<Event>{stopPropagation: () => {}});
202209

203-
fixture.whenStable().then(() => {
204-
expect(checkboxInstance.checked).toBe(true);
205-
expect(checkboxInstance.indeterminate).toBe(false);
210+
// Flush the microtasks because the indeterminate state will be updated in the next tick.
211+
flushMicrotasks();
206212

207-
checkboxInstance._onInputClick(<Event>{stopPropagation: () => {}});
208-
fixture.detectChanges();
213+
expect(checkboxInstance.checked).toBe(true);
214+
expect(checkboxInstance.indeterminate).toBe(false);
209215

210-
expect(checkboxInstance.checked).toBe(false);
211-
expect(checkboxInstance.indeterminate).toBe(false);
212-
});
216+
checkboxInstance._onInputClick(<Event>{stopPropagation: () => {}});
217+
fixture.detectChanges();
218+
219+
expect(checkboxInstance.checked).toBe(false);
220+
expect(checkboxInstance.indeterminate).toBe(false);
213221
}));
214222

215223
it('should add and remove disabled state', () => {
@@ -242,17 +250,18 @@ describe('MdCheckbox', () => {
242250
expect(checkboxInstance.checked).toBe(false);
243251
});
244252

245-
it('should overwrite indeterminate state when clicked', async(() => {
253+
it('should overwrite indeterminate state when clicked', fakeAsync(() => {
246254
testComponent.isIndeterminate = true;
247255
fixture.detectChanges();
248256

249257
inputElement.click();
250258
fixture.detectChanges();
251259

252-
fixture.whenStable().then(() => {
253-
expect(checkboxInstance.checked).toBe(true);
254-
expect(checkboxInstance.indeterminate).toBe(false);
255-
});
260+
// Flush the microtasks because the indeterminate state will be updated in the next tick.
261+
flushMicrotasks();
262+
263+
expect(checkboxInstance.checked).toBe(true);
264+
expect(checkboxInstance.indeterminate).toBe(false);
256265
}));
257266

258267
it('should preserve the user-provided id', () => {

src/lib/slide-toggle/slide-toggle.spec.ts

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import {Component} from '@angular/core';
22
import {By, HAMMER_GESTURE_CONFIG} from '@angular/platform-browser';
3-
import {async, ComponentFixture, TestBed, fakeAsync, tick} from '@angular/core/testing';
3+
import {
4+
async, ComponentFixture, TestBed, fakeAsync, tick,
5+
flushMicrotasks
6+
} from '@angular/core/testing';
47
import {NgModel, FormsModule, ReactiveFormsModule, FormControl} from '@angular/forms';
58
import {MdSlideToggle, MdSlideToggleChange, MdSlideToggleModule} from './index';
69
import {TestGestureConfig} from '../slider/test-gesture-config';
@@ -56,17 +59,17 @@ describe('MdSlideToggle', () => {
5659
labelElement = fixture.debugElement.query(By.css('label')).nativeElement;
5760
}));
5861

59-
// TODO(kara); update when core/testing adds fix
60-
it('should update the model correctly', async(() => {
62+
it('should update the model correctly', fakeAsync(() => {
6163
expect(slideToggleElement.classList).not.toContain('mat-checked');
6264

6365
testComponent.slideModel = true;
6466
fixture.detectChanges();
65-
fixture.whenStable().then(() => {
66-
fixture.detectChanges();
67-
expect(slideToggleElement.classList).toContain('mat-checked');
68-
});
6967

68+
// Flush the microtasks because the forms module updates the model state asynchronously.
69+
flushMicrotasks();
70+
71+
fixture.detectChanges();
72+
expect(slideToggleElement.classList).toContain('mat-checked');
7073
}));
7174

7275
it('should apply class based on color attribute', () => {
@@ -333,19 +336,23 @@ describe('MdSlideToggle', () => {
333336
expect(slideToggleElement.classList).not.toContain('mat-checked');
334337
});
335338

336-
// TODO(kara): update when core/testing adds fix
337-
it('should not set the control to touched when changing the model', async(() => {
339+
it('should not set the control to touched when changing the model', fakeAsync(() => {
338340
// The control should start off with being untouched.
339341
expect(slideToggleModel.touched).toBe(false);
340342

341343
testComponent.slideModel = true;
342344
fixture.detectChanges();
343-
fixture.whenStable().then(() => {
344-
fixture.detectChanges();
345-
expect(slideToggleModel.touched).toBe(false);
346-
expect(slideToggle.checked).toBe(true);
347-
expect(slideToggleElement.classList).toContain('mat-checked');
348-
});
345+
346+
// Flush the microtasks because the forms module updates the model state asynchronously.
347+
flushMicrotasks();
348+
349+
// The checked property has been updated from the model and now the view needs
350+
// to reflect the state change.
351+
fixture.detectChanges();
352+
353+
expect(slideToggleModel.touched).toBe(false);
354+
expect(slideToggle.checked).toBe(true);
355+
expect(slideToggleElement.classList).toContain('mat-checked');
349356
}));
350357

351358
it('should forward the required attribute', () => {

0 commit comments

Comments
 (0)