我们有一个用于包装输入字段的组件。它工作得很好,但Jasmine测试没有。我已经缩小了导致测试失败的原因,但不确定为什么或如何纠正。
这个组件有一堆功能(翻译,可访问性,添加所需的指示符等),我已经从这个版本/解释中删除了,因为它们对手头的问题并不重要。因此,当字段出错时,组件现在基本上会变成红色。
以下是精简版组件:
import { Component, Input, ContentChild, ElementRef } from '@angular/core';
import { AbstractControlDirective, AbstractControl } from '@angular/forms';
@Component({
selector: 'my-control-group',
templateUrl: './my-control-group.component.html',
styleUrls: ['./my-control-group.component.css']
})
export class MyControlGroupComponent {
@ContentChild('inputElement')
private inputElement: ElementRef;
@Input()
private control: AbstractControlDirective | AbstractControl;
constructor() { }
/* This method returns true of the field is in error */
private isInputFieldInError(): boolean {
if (this.control && this.control.errors) {
return true;
} else {
return false;
}
}
}
其模板
<div class="form-group" [ngClass]="{'has-error': isInputFieldInError()}">
<label class="control-label">Test Field</label>
<div class="input-container">
<ng-content></ng-content>
</div>
</div>
一个工作用法示例如下:
<form #myForm="ngForm" novalidate>
<my-control-group [control]="sampleName">
<input #inputElement name="sampleName" class="form-control" [(ngModel)]="sample.name" required #sampleName="ngModel" autocomplete="off">
</my-control-group>
</form>
测试规范:
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { Component, Input, ContentChild, ElementRef, ViewChild } from '@angular/core';
import { AbstractControlDirective, AbstractControl } from '@angular/forms';
import { FormsModule } from '@angular/forms';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { MyControlGroupComponent } from './my-control-group.component';
@Component({
selector: 'my-required-field',
template: `
<form #myForm="ngForm" novalidate>
<my-control-group [control]="sampleName" label="Required field">
<input #inputElement name="sampleName" class="form-control" [(ngModel)]="sample.name" required #sampleName="ngModel" autocomplete="off">
</my-control-group>
</form>
`
})
class ContentProjectionComponent {
private sample = { name : ''};
}
describe('MyControlGroupComponent', () => {
let component: ContentProjectionComponent;
let fixture: ComponentFixture<ContentProjectionComponent>;
let de: DebugElement;
let el: HTMLElement;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ MyControlGroupComponent, ContentProjectionComponent],
imports: [FormsModule]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ContentProjectionComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
let formGroupDE: DebugElement;
let formGroupHTML: HTMLElement;
formGroupDE = fixture.debugElement.query(By.css('div'));
formGroupHTML = formGroupDE.nativeElement;
expect(formGroupHTML.className).toContain("has-error");
});
});
所以,问题是当我调试我的测试时,字段永远不会认为它是错误的。换句话说,即使我已经根据需要标记了它所包含的字段并且该字段为空,this.control.errors数组也始终为null。
它修复了什么?如果我从我正在测试的模板中删除我的表单标签:
template: `
<my-control-group [control]="sampleName" label="Required field">
<input #inputElement name="sampleName" class="form-control" [(ngModel)]="sample.name" required #sampleName="ngModel" autocomplete="off">
</my-control-group>
`
注意:您可能想知道为什么我还需要表单标记 - 这是我从本示例中删除的其他功能所必需的。
调试测试时,我查看this.control没有表单标签,我可以在数组rawValidators列表中看到所需的验证器,并填充了错误数组。使用表单标记,该列表中没有验证器,并且errors数组始终为null。
奇怪的是,这个功能在现场工作中起作用(就像我剥离的其他部分一样)。