55 inject ,
66 async ,
77 fakeAsync ,
8- flushMicrotasks ,
9- tick
8+ flushMicrotasks
109} from '@angular/core/testing' ;
1110import {
1211 FORM_DIRECTIVES ,
@@ -19,7 +18,6 @@ import {TestComponentBuilder, ComponentFixture} from '@angular/compiler/testing'
1918import { Component , DebugElement } from '@angular/core' ;
2019import { By } from '@angular/platform-browser' ;
2120import { MdCheckbox , MdCheckboxChange } from './checkbox' ;
22- import { PromiseCompleter } from '@angular2-material/core/async/promise-completer' ;
2321
2422
2523
@@ -215,21 +213,48 @@ describe('MdCheckbox', () => {
215213 expect ( testComponent . onCheckboxClick ) . toHaveBeenCalledTimes ( 1 ) ;
216214 } ) ;
217215
218- it ( 'should emit a change event when the `checked` value changes' , ( ) => {
219- // TODO(jelbourn): this *should* work with async(), but fixture.whenStable currently doesn't
220- // know to look at pending macro tasks.
221- // See https://github.com/angular/angular/issues/8389
222- // As a short-term solution, use a promise (which jasmine knows how to understand).
223- let promiseCompleter = new PromiseCompleter ( ) ;
224- checkboxInstance . change . subscribe ( ( ) => {
225- promiseCompleter . resolve ( ) ;
216+ it ( 'should trigger the change event properly' , async ( ( ) => {
217+ spyOn ( testComponent , 'onCheckboxChange' ) ;
218+
219+ expect ( inputElement . checked ) . toBe ( false ) ;
220+ expect ( checkboxNativeElement . classList ) . not . toContain ( 'md-checkbox-checked' ) ;
221+
222+ labelElement . click ( ) ;
223+ fixture . detectChanges ( ) ;
224+
225+ expect ( inputElement . checked ) . toBe ( true ) ;
226+ expect ( checkboxNativeElement . classList ) . toContain ( 'md-checkbox-checked' ) ;
227+
228+ // Wait for the fixture to become stable, because the EventEmitter for the change event,
229+ // will only fire after the zone async change detection has finished.
230+ fixture . whenStable ( ) . then ( ( ) => {
231+ // The change event shouldn't fire, because the value change was not caused
232+ // by any interaction.
233+ expect ( testComponent . onCheckboxChange ) . toHaveBeenCalledTimes ( 1 ) ;
226234 } ) ;
235+ } ) ) ;
236+
237+ it ( 'should not trigger the change event by changing the native value' , async ( ( ) => {
238+ spyOn ( testComponent , 'onCheckboxChange' ) ;
239+
240+ expect ( inputElement . checked ) . toBe ( false ) ;
241+ expect ( checkboxNativeElement . classList ) . not . toContain ( 'md-checkbox-checked' ) ;
227242
228243 testComponent . isChecked = true ;
229244 fixture . detectChanges ( ) ;
230245
231- return promiseCompleter . promise ;
232- } ) ;
246+ expect ( inputElement . checked ) . toBe ( true ) ;
247+ expect ( checkboxNativeElement . classList ) . toContain ( 'md-checkbox-checked' ) ;
248+
249+ // Wait for the fixture to become stable, because the EventEmitter for the change event,
250+ // will only fire after the zone async change detection has finished.
251+ fixture . whenStable ( ) . then ( ( ) => {
252+ // The change event shouldn't fire, because the value change was not caused
253+ // by any interaction.
254+ expect ( testComponent . onCheckboxChange ) . not . toHaveBeenCalled ( ) ;
255+ } ) ;
256+
257+ } ) ) ;
233258
234259 describe ( 'state transition css classes' , ( ) => {
235260 it ( 'should transition unchecked -> checked -> unchecked' , ( ) => {
@@ -308,17 +333,21 @@ describe('MdCheckbox', () => {
308333 } ) ;
309334 } ) ) ;
310335
311- it ( 'should call the change event on first change after initialization' , fakeAsync ( ( ) => {
312- fixture . detectChanges ( ) ;
313- expect ( testComponent . lastEvent ) . toBeUndefined ( ) ;
336+ it ( 'should emit the event to the change observable' , ( ) => {
337+ let changeSpy = jasmine . createSpy ( 'onChangeObservable' ) ;
338+
339+ checkboxInstance . change . subscribe ( changeSpy ) ;
314340
315- checkboxInstance . checked = true ;
316341 fixture . detectChanges ( ) ;
342+ expect ( changeSpy ) . not . toHaveBeenCalled ( ) ;
317343
318- tick ( ) ;
344+ // When changing the native `checked` property the checkbox will not fire a change event,
345+ // because the element is not focused and it's not the native behavior of the input element.
346+ labelElement . click ( ) ;
347+ fixture . detectChanges ( ) ;
319348
320- expect ( testComponent . lastEvent . checked ) . toBe ( true ) ;
321- } ) ) ;
349+ expect ( changeSpy ) . toHaveBeenCalledTimes ( 1 ) ;
350+ } ) ;
322351
323352 it ( 'should not emit a DOM event to the change output' , async ( ( ) => {
324353 fixture . detectChanges ( ) ;
@@ -496,7 +525,8 @@ describe('MdCheckbox', () => {
496525 [indeterminate]="isIndeterminate"
497526 [disabled]="isDisabled"
498527 (change)="changeCount = changeCount + 1"
499- (click)="onCheckboxClick($event)">
528+ (click)="onCheckboxClick($event)"
529+ (change)="onCheckboxChange($event)">
500530 Simple checkbox
501531 </md-checkbox>
502532 </div>`
@@ -511,6 +541,7 @@ class SingleCheckbox {
511541 lastKeydownEvent : Event = null ;
512542
513543 onCheckboxClick ( event : Event ) { }
544+ onCheckboxChange ( event : MdCheckboxChange ) { }
514545}
515546
516547/** Simple component for testing an MdCheckbox with ngModel. */
0 commit comments