diff --git a/package.json b/package.json index c6611ae2..8b976776 100644 --- a/package.json +++ b/package.json @@ -31,8 +31,8 @@ }, "dependencies": {}, "devDependencies": { - "@blackbaud/skyux": "2.28.1", - "@blackbaud/skyux-builder": "1.28.0", + "@blackbaud/skyux": "2.29.0", + "@blackbaud/skyux-builder": "1.29.0", "@skyux-sdk/builder-plugin-skyux": "1.0.0-rc.5" } } diff --git a/src/app/public/modules/checkbox/checkbox.component.spec.ts b/src/app/public/modules/checkbox/checkbox.component.spec.ts index 33483f72..e42bf72e 100644 --- a/src/app/public/modules/checkbox/checkbox.component.spec.ts +++ b/src/app/public/modules/checkbox/checkbox.component.spec.ts @@ -13,7 +13,10 @@ import { } from '@angular/platform-browser'; import { FormsModule, - NgModel + NgModel, + FormControl, + FormGroup, + ReactiveFormsModule } from '@angular/forms'; import { @@ -72,6 +75,26 @@ class CheckboxWithFormDirectivesComponent { public isGood: boolean = false; } +/** Simple component for testing an MdCheckbox with ngModel. */ +@Component({ + template: ` +
+
+ + + Be good + + +
+
+ ` +}) +class CheckboxWithReactiveFormComponent { + public checkbox1: FormControl = new FormControl(false); + + public checkboxForm = new FormGroup({'checkbox1': this.checkbox1}); +} + /** Simple test component with multiple checkboxes. */ @Component(({ template: ` @@ -140,12 +163,14 @@ describe('Checkbox component', () => { CheckboxWithFormDirectivesComponent, CheckboxWithNameAttributeComponent, CheckboxWithTabIndexComponent, + CheckboxWithReactiveFormComponent, MultipleCheckboxesComponent, SingleCheckboxComponent ], imports: [ BrowserModule, FormsModule, + ReactiveFormsModule, SkyCheckboxModule ] }); @@ -499,6 +524,96 @@ describe('Checkbox component', () => { })); }); + describe('with reactive form', () => { + let checkboxElement: DebugElement; + let testComponent: CheckboxWithReactiveFormComponent; + let inputElement: HTMLInputElement; + let checkboxNativeElement: HTMLElement; + let formControl: FormControl; + let labelElement: HTMLLabelElement; + + beforeEach(async(() => { + fixture = TestBed.createComponent(CheckboxWithReactiveFormComponent); + fixture.detectChanges(); + + fixture.whenStable().then(() => { + checkboxElement = fixture.debugElement.query(By.directive(SkyCheckboxComponent)); + checkboxNativeElement = checkboxElement.nativeElement; + + testComponent = fixture.debugElement.componentInstance; + inputElement = checkboxNativeElement.querySelector('input'); + formControl = testComponent.checkbox1; + labelElement = + checkboxElement + .nativeElement.querySelector('label.sky-checkbox-wrapper'); + }); + })); + + it('should be in pristine, untouched, and valid states initially', async(() => { + fixture.detectChanges(); + expect(formControl.valid).toBe(true); + expect(formControl.pristine).toBe(true); + expect(formControl.touched).toBe(false); + + labelElement.click(); + + fixture.detectChanges(); + + fixture.whenStable().then(() => { + fixture.detectChanges(); + + expect(formControl.valid).toBe(true); + expect(formControl.pristine).toBe(false); + expect(formControl.touched).toBe(false); + expect(formControl.value).toBe(true); + + inputElement.dispatchEvent(createEvent('blur')); + expect(formControl.touched).toBe(true); + }); + })); + + it('should change check state through form control programmatically', async(() => { + fixture.whenStable().then(() => { + fixture.detectChanges(); + expect(inputElement.checked).toBe(false); + expect(formControl.value).toBe(false); + fixture.detectChanges(); + formControl.setValue(true); + + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + expect(inputElement.checked).toBe(true); + }); + }); + })); + + it('should change disable state through form control programmatically', async(() => { + fixture.whenStable().then(() => { + fixture.detectChanges(); + expect(inputElement.disabled).toBe(false); + expect(formControl.value).toBe(false); + fixture.detectChanges(); + formControl.disable(); + + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + expect(inputElement.disabled).toBe(true); + expect(inputElement.checked).toBe(false); + + formControl.enable(); + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + expect(inputElement.disabled).toBe(false); + expect(inputElement.checked).toBe(false); + }); + }); + }); + })); + }); + describe('with name attribute', () => { beforeEach(async(() => { fixture = TestBed.createComponent(CheckboxWithNameAttributeComponent); diff --git a/src/app/public/modules/checkbox/checkbox.component.ts b/src/app/public/modules/checkbox/checkbox.component.ts index 0d15a13f..f3c27a1b 100644 --- a/src/app/public/modules/checkbox/checkbox.component.ts +++ b/src/app/public/modules/checkbox/checkbox.component.ts @@ -124,6 +124,13 @@ export class SkyCheckboxComponent implements ControlValueAccessor { this.onTouched = fn; } + /** + * Implemented as part of ControlValueAccessor. + */ + public setDisabledState(isDisabled: boolean) { + this.disabled = isDisabled; + } + /** * Event handler for checkbox input element. * Toggles checked state if element is not disabled.