2017-09-15 43 views
1

我有一个组件包含一个带有3个输入文本的表单。两个输入是纯文本框,一个是ngbTypeahead指向ng-bootstrap的文本框。 我的表单是使用FormBuilder(反应形式)构建的。单元测试一个包含ngbTypeahead的组件

this.form = fb.group({ 
    department: [''], 
    name: ['', Validators.required], 
    location: ['', Validators.required] 
}); 

我的模板是这样的:

<input type="text" class="form-control" formControlName="name"/> 
... 
<input type="text" class="form-control" formControlName="location"/> 
... 
<input 
    type="text" 
    class="form-control" 
    formControlName="department" 
    [ngbTypeahead]="autocompleteDepartments" 
    [resultFormatter]="formatDepartment" 
    [inputFormatter]="formatDepartment"/> 

组件包含功能ngbTypeahead

autocompleteDepartments(text$: Observable<string>): Observable<Department> { 
    .... 
} 
formatDepartment(department: Department) { 
    return department.name; 
} 

所以this.form.department.value不是一个字符串,但像这样的对象:

interface Department { 
    id: number; 
    name: string; 
    foo: boolean; 
    bar: number; 
    ... 
} 

一切正常。

现在我想单元测试我的组件,为此我需要为三个输入中的每一个设置一个值。 对于两个纯投入,没有问题:

const nameHtmlEl = <HTMLInputElement>fixture.debugElement.query(By.css('[formControlName="name"]')).nativeElement; 
nameHtmlEl.value = "Toto"; 
nameHtmlEl.dispatchEvent(new Event('input')); 

但与ngbTypeahead指令输入,我不知道如何设置的值(即必须是处对象,而不是一个字符串): 我试过了,但它不起作用:

const departmentHtmlEl = /*<HTMLInputElement>*/ fixture.debugElement.query(By.css('[formControlName="department"]')).nativeElement; 
departmentHtmlEl.value = <Department>{id: 10, name: "Foo", ...}; 
departmentHtmlEl.dispatchEvent(new Event('input')); 

回答

0

我相信你试图模拟Typeahead的一个过滤项目的选择。

我会去了解这个的办法是仍设置您正在搜索密钥字符串:

departmentHtmlEl.value = 'Foo'; 

假设你的名字搜索。

然后,我会模拟选择。这个你可以通过

getWindowLinks(fixture.debugElement)[0].triggerEventHandler('click', {}); 

其中getWindowLinks做的是:

function getWindowLinks(element: DebugElement): DebugElement[] { 
    return Array.from(element.queryAll(By.css('button.dropdown-item'))); 
} 

此外,你将不得不使用fakeAsync,使这项工作。样品测试看起来像这样:

it('sample test', fakeAsync(() => { 
    const departmentHtmlEl = /*<HTMLInputElement>*/ fixture.debugElement.query(By.css('[formControlName="department"]')).nativeElement; 
    departmentHtmlEl.value = 'Foo'; 
    fixture.detectChanges(); 

    tick(300); 
    // this should be more than the number on debounceTime you are using for the search 

    getWindowLinks(fixture.debugElement)[0].triggerEventHandler('click', {}); 
    fixture.detectChanges(); 

    tick(300); 

    // your expectation code here. 
    })); 

希望这会有所帮助。