From 0c9bb0dd2a88942cbff0647e820546069ee8fc41 Mon Sep 17 00:00:00 2001 From: Oleksandr Telnov Date: Fri, 24 Jun 2016 17:48:16 +0300 Subject: [PATCH] tests(button directive) (#645) --- .../buttons/button-checkbox.directive.ts | 2 + components/buttons/button-radio.directive.ts | 3 + components/buttons/button.directive.spec.ts | 231 ++++++++++++++++++ 3 files changed, 236 insertions(+) create mode 100644 components/buttons/button.directive.spec.ts diff --git a/components/buttons/button-checkbox.directive.ts b/components/buttons/button-checkbox.directive.ts index 8d5daa932f..578eac8fbc 100644 --- a/components/buttons/button-checkbox.directive.ts +++ b/components/buttons/button-checkbox.directive.ts @@ -3,6 +3,8 @@ import { } from '@angular/core'; import {ControlValueAccessor, NgModel} from '@angular/common'; +// TODO: config: activeClass - Class to apply to the checked buttons. + @Directive({selector: '[btnCheckbox][ngModel]'}) export class ButtonCheckboxDirective implements ControlValueAccessor, OnInit { public cd:NgModel; diff --git a/components/buttons/button-radio.directive.ts b/components/buttons/button-radio.directive.ts index 82bb9936cc..fe75395838 100644 --- a/components/buttons/button-radio.directive.ts +++ b/components/buttons/button-radio.directive.ts @@ -3,6 +3,9 @@ import { } from '@angular/core'; import {ControlValueAccessor, NgModel} from '@angular/common'; +// TODO: if uncheckable, null should be set to ngModel +// if disabled, button should not be checkable + @Directive({selector: '[btnRadio][ngModel]'}) export class ButtonRadioDirective implements ControlValueAccessor, OnInit { public cd:NgModel; diff --git a/components/buttons/button.directive.spec.ts b/components/buttons/button.directive.spec.ts new file mode 100644 index 0000000000..00f409a4b2 --- /dev/null +++ b/components/buttons/button.directive.spec.ts @@ -0,0 +1,231 @@ +import {Component} from '@angular/core'; +import {it, beforeEach, beforeEachProviders, injectAsync, expect} from '@angular/core/testing'; +import {TestComponentBuilder, ComponentFixture} from '@angular/compiler/testing'; +import {ButtonCheckboxDirective} from './button-checkbox.directive'; +import {ButtonRadioDirective} from './button-radio.directive'; + +const html = ` +
+ + + + + + +
+ + + +
+ +
+ + + + +
+ +
+ + + +
+
+`; + +describe('Directive: Buttons', () => { + let fixture:ComponentFixture; + let context:any; + let element:any; + + beforeEachProviders(() => [ + TestComponentBuilder + ]); + + beforeEach(injectAsync([TestComponentBuilder], (tcb:TestComponentBuilder) => { + return tcb + .overrideTemplate(TestButtonsComponent, html) + .createAsync(TestButtonsComponent) + .then((f:ComponentFixture) => { + fixture = f; + context = fixture.componentInstance; + element = fixture.nativeElement; + fixture.detectChanges(); + }); + })); + + describe('checkbox', () => { + it('should work correctly with default model values', () => { + expect(element.querySelector('#default')).not.toHaveCssClass('active'); + context.singleModel = true; + fixture.detectChanges(); + expect(element.querySelector('#default')).toHaveCssClass('active'); + }); + + it('should bind custom model values', () => { + expect(element.querySelector('#custom')).not.toHaveCssClass('active'); + context.singleModel = '1'; + fixture.detectChanges(); + expect(element.querySelector('#custom')).toHaveCssClass('active'); + }); + + it('should toggle default model values on click', () => { + context.singleModel = false; + fixture.detectChanges(); + let btn = element.querySelector('#default'); + + btn.click(); + fixture.detectChanges(); + expect(context.singleModel).toEqual(true); + expect(btn).toHaveCssClass('active'); + + btn.click(); + fixture.detectChanges(); + expect(context.singleModel).toEqual(false); + expect(btn).not.toHaveCssClass('active'); + }); + + it('should toggle custom model values on click', () => { + let btn = element.querySelector('#custom'); + + btn.click(); + fixture.detectChanges(); + expect(context.singleModel).toEqual('1'); + expect(btn).toHaveCssClass('active'); + + btn.click(); + fixture.detectChanges(); + expect(context.singleModel).toEqual('0'); + expect(btn).not.toHaveCssClass('active'); + }); + + it('should not toggle when disabled', () => { + context.singleModel = false; + fixture.detectChanges(); + let btn = element.querySelector('#disabled'); + + btn.click(); + fixture.detectChanges(); + expect(context.singleModel).toEqual(false); + expect(btn).not.toHaveCssClass('active'); + + btn.click(); + fixture.detectChanges(); + expect(context.singleModel).toEqual(false); + expect(btn).not.toHaveCssClass('active'); + }); + + it('should work for btn-group', () => { + let btn = element.querySelector('.btn-group.checkbox'); + expect(btn.children[0]).not.toHaveCssClass('active'); + expect(btn.children[1]).toHaveCssClass('active'); + expect(btn.children[2]).not.toHaveCssClass('active'); + }); + }); + + describe('radio', () => { + it('should set active class based on model', () => { + let btn = element.querySelector('.btn-group.radio'); + expect(btn.children[0]).not.toHaveCssClass('active'); + expect(btn.children[1]).toHaveCssClass('active'); + expect(btn.children[2]).not.toHaveCssClass('active'); + + context.radioModel = 'Left'; + fixture.detectChanges(); + expect(btn.children[0]).toHaveCssClass('active'); + expect(btn.children[1]).not.toHaveCssClass('active'); + expect(btn.children[2]).not.toHaveCssClass('active'); + }); + + it('should set active class via click', () => { + let btn = element.querySelector('.btn-group.radio'); + delete context.radioModel; + expect(context.radioModel).toBeUndefined(); + + btn.children[2].click(); + fixture.detectChanges(); + expect(context.radioModel).toEqual('Right'); + expect(btn.children[0]).not.toHaveCssClass('active'); + expect(btn.children[1]).not.toHaveCssClass('active'); + expect(btn.children[2]).toHaveCssClass('active'); + + btn.children[1].click(); + fixture.detectChanges(); + expect(context.radioModel).toEqual('Middle'); + expect(btn.children[0]).not.toHaveCssClass('active'); + expect(btn.children[1]).toHaveCssClass('active'); + expect(btn.children[2]).not.toHaveCssClass('active'); + }); + + it('should do nothing when clicking an active radio', () => { + let btn = element.querySelector('.btn-group.radio'); + expect(context.radioModel).toEqual('Middle'); + expect(btn.children[0]).not.toHaveCssClass('active'); + expect(btn.children[1]).toHaveCssClass('active'); + expect(btn.children[2]).not.toHaveCssClass('active'); + + btn.children[1].click(); + fixture.detectChanges(); + expect(context.radioModel).toEqual('Middle'); + expect(btn.children[0]).not.toHaveCssClass('active'); + expect(btn.children[1]).toHaveCssClass('active'); + expect(btn.children[2]).not.toHaveCssClass('active'); + }); + + xit('should not toggle when disabled', () => { + let btn = element.querySelector('.btn-group.radio'); + expect(context.radioModel).toEqual('Middle'); + expect(btn.children[1]).toHaveCssClass('active'); + expect(btn.children[3]).not.toHaveCssClass('active'); + + context.radioModel = '1'; + fixture.detectChanges(); + expect(btn.children[1]).toHaveCssClass('active'); + expect(btn.children[3]).not.toHaveCssClass('active'); + + btn.children[3].click(); + fixture.detectChanges(); + expect(btn.children[1]).toHaveCssClass('active'); + expect(btn.children[3]).not.toHaveCssClass('active'); + }); + + xit('should unset active class via click', () => { + let btn = element.querySelector('.btn-group.radioUncheckable'); + expect(context.radioUncheckableModel).toBeUndefined(); + + btn.children[0].click(); + fixture.detectChanges(); + expect(context.radioUncheckableModel).toEqual('Left'); + expect(btn.children[0]).toHaveCssClass('active'); + expect(btn.children[1]).not.toHaveCssClass('active'); + expect(btn.children[2]).not.toHaveCssClass('active'); + + btn.children[0].click(); + fixture.detectChanges(); + expect(context.radioUncheckableModel).toBeNull(); + expect(btn.children[0]).not.toHaveCssClass('active'); + expect(btn.children[1]).not.toHaveCssClass('active'); + expect(btn.children[2]).not.toHaveCssClass('active'); + }); + }); +}); + +@Component({ + selector: 'buttons-test', + directives: [ButtonCheckboxDirective, ButtonRadioDirective], + template: '' +}) + +class TestButtonsComponent { + public singleModel:string = '0'; + public checkModel:any = {left: false, middle: true, right: false}; + public radioModel:string = 'Middle'; +}