import { Component, DebugElement, Injectable } from '@angular/core'; import { TestBed, ComponentFixture, fakeAsync, tick, async, inject } from '@angular/core/testing'; import { BrowserModule, By } from '@angular/platform-browser'; import { FormsModule } from '@angular/forms'; import { slice } from 'lodash'; import { expect, createGenericTestComponent } from '../testing'; import { TreeviewConfig } from './treeview-config'; import { TreeviewItemComponent } from './treeview-item.component'; import { TreeviewItem } from './treeview-item'; import { fakeItemTemplate } from './treeview-item-template.spec'; interface FakeData { item: TreeviewItem; checkedChange(checked: boolean): void; } const fakeData: FakeData = { item: undefined, checkedChange(checked: boolean) { } }; const testTemplate = fakeItemTemplate + ''; @Component({ selector: 'ngx-test', template: '', }) class TestComponent { item = fakeData.item; checkedChange = (checked: boolean) => fakeData.checkedChange(checked); } const createTestComponent = (html: string) => createGenericTestComponent(html, TestComponent) as ComponentFixture; describe('TreeviewItemComponent', () => { beforeEach(() => { TestBed.configureTestingModule({ imports: [ FormsModule, BrowserModule ], declarations: [ TestComponent, TreeviewItemComponent ], providers: [TreeviewConfig] }); }); it('should initialize with default config', () => { const defaultConfig = new TreeviewConfig(); const component = TestBed.createComponent(TreeviewItemComponent).componentInstance; expect(component.config).toEqual(defaultConfig); }); describe('item', () => { it('should not have element with class "treeview-item" if no item provided', () => { const fixture = createTestComponent(''); fixture.detectChanges(); const element = fixture.debugElement.query(By.css('.treeview-item')); expect(element).toBeNull(); }); it('should have element with class "treeview-item" if binding item', () => { fakeData.item = new TreeviewItem({ text: '1', value: 1 }); const fixture = createTestComponent(''); fixture.detectChanges(); const element = fixture.debugElement.query(By.css('.treeview-item')); expect(element).not.toBeNull(); }); }); describe('template', () => { let fixture: ComponentFixture; let collapsedElement: DebugElement; let parentCheckbox: DebugElement; let childrenCheckboxes: DebugElement[]; beforeEach(() => { fakeData.item = new TreeviewItem({ text: 'Parent 1', value: 1, checked: true, collapsed: false, disabled: false, children: [ { text: 'Child 1', value: 11 }, { text: 'Child 2', value: 12 } ] }); }); beforeEach(fakeAsync(() => { fixture = createTestComponent(testTemplate); fixture.detectChanges(); tick(); collapsedElement = fixture.debugElement.query(By.css('.fa')); const checkboxElements = fixture.debugElement.queryAll(By.css('.form-check-input')); parentCheckbox = checkboxElements[0]; childrenCheckboxes = slice(checkboxElements, 1); })); it('should work', () => { const textElement = fixture.debugElement.query(By.css('.form-check-label')); expect(textElement.nativeElement.innerText.trim()).toBe('Parent 1'); expect(parentCheckbox.nativeElement.checked).toBeTruthy(); expect(parentCheckbox.nativeElement.disabled).toBeFalsy(); expect(collapsedElement.nativeElement).toHaveCssClass('fa-caret-down'); }); it('should render "Parent 1", "Child 1" & "Child 2" with checked', () => { expect(parentCheckbox.nativeElement.checked).toEqual(true); expect(childrenCheckboxes.map(element => element.nativeElement.checked)).toEqual([true, true]); }); describe('toggle collapse/expand', () => { beforeEach(fakeAsync(() => { collapsedElement.triggerEventHandler('click', {}); fixture.detectChanges(); tick(); })); it('should invoke onCollapseExpand to change value of collapsed', () => { expect(collapsedElement.nativeElement).toHaveCssClass('fa-caret-right'); }); it('should not render children', () => { const checkboxElements = fixture.debugElement.queryAll(By.css('.form-check-input')); expect(checkboxElements.length).toBe(1); }); }); describe('uncheck "Parent 1"', () => { let spy: jasmine.Spy; beforeEach(fakeAsync(() => { spy = spyOn(fakeData, 'checkedChange'); parentCheckbox.nativeElement.click(); fixture.detectChanges(); tick(); })); it('should un-check "Child 1" & "Child 2"', () => { expect(childrenCheckboxes.map(element => element.nativeElement.checked)).toEqual([false, false]); }); it('should raise event checkedChange', () => { expect(spy.calls.count()).toBe(1); const args = spy.calls.mostRecent().args; expect(args[0]).toBeFalsy(); }); }); describe('un-check "Child 1"', () => { let spy: jasmine.Spy; beforeEach(fakeAsync(() => { spy = spyOn(fakeData, 'checkedChange'); childrenCheckboxes[0].nativeElement.click(); fixture.detectChanges(); tick(); })); it('should uncheck "Parent 1"', () => { expect(parentCheckbox.nativeElement.checked).toEqual(false); }); it('should raise event checkedChange', () => { expect(spy.calls.count()).toBe(1); const args = spy.calls.mostRecent().args; expect(args[0]).toBeFalsy(); }); describe('un-check "Child 2"', () => { beforeEach(fakeAsync(() => { spy.calls.reset(); childrenCheckboxes[1].nativeElement.click(); fixture.detectChanges(); tick(); })); it('should keep "Parent 1" unchecked', () => { expect(parentCheckbox.nativeElement.checked).toEqual(false); }); it('should raise event checkedChange', () => { expect(spy.calls.count()).toBe(1); const args = spy.calls.mostRecent().args; expect(args[0]).toBeFalsy(); }); }); describe('check "Child 1"', () => { beforeEach(fakeAsync(() => { spy.calls.reset(); childrenCheckboxes[0].nativeElement.click(); fixture.detectChanges(); tick(); })); it('should check "Parent 1"', () => { expect(parentCheckbox.nativeElement.checked).toEqual(true); }); it('should raise event checkedChange', () => { expect(spy.calls.count()).toBe(1); const args = spy.calls.mostRecent().args; expect(args[0]).toBeTruthy(); }); }); }); }); });