我正在尝试使用输入和外部模板测试角度2组件。
以下是组件:
@Component({
selector: 'text-counter',
templateUrl: 'text-counter.component.html',
styleUrls: ['text-counter.component.css']
})
export class TextCounterComponent implements OnChanges {
@Input() inputText: string;
@Input() min: number;
@Input() max: number;
@Input() tolerance: number = 20;
message: string;
messageClass: string;
constructor() {
}
ngOnChanges(changes: SimpleChanges) {
const input: string = changes['inputText'].currentValue;
function expandMessage(rawMessage, n) {
return rawMessage.replace('%', n);
}
const settings = {
initialPrompt: 'saisissez au moins % caractères',
nToGoPrompt: 'il manque % caractères',
nLeftPrompt: 'encore % caractères autorisés',
tooLongByPrompt: 'trop long de % caractères'
};
const length = input ? input.length : 0;
this.messageClass = 'lightblue';
if (length === 0) {
this.message = expandMessage(settings.initialPrompt, this.min);
}
else if (length > 0 && length < this.min) {
this.message = expandMessage(settings.nToGoPrompt, this.min - length);
}
else if (length >= this.min && length <= this.max) {
if (length > this.max - this.tolerance) {
this.messageClass = 'Gold';
}
this.message = expandMessage(settings.nLeftPrompt, this.max - length);
}
else {
this.messageClass = 'Red';
this.message = expandMessage(settings.tooLongByPrompt, length - this.max);
}
}
}
及其模板:
<span class="form-text" [ngClass]="messageClass">
{{message}}
</span>
message
变量永远不会在测试模板中更新,尽管ngOnChanges
实际上已被调用...
以下是测试:
@Component({
selector: `test-host-component`,
template: `<div>
<text-counter
[inputText]="valueFromHost"
[min]="2"
[max]="500">
</text-counter>
</div>`
})
export class TestHostComponent {
/* using viewChild we get access to the TestComponent which is a child of TestHostComponent */
@ViewChild(TextCounterComponent)
public textCounterComponent: any;
/* this is the variable which is passed as input to the TestComponent */
public valueFromHost: string;
}
describe('Component: TextCounter', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [TextCounterComponent, TestHostComponent]
})
.compileComponents();
}));
it('should indicate min message', () => {
const hostComponentFixture = TestBed.createComponent(TestHostComponent);
const textCounterComponentFixture = TestBed.createComponent(TextCounterComponent);
const de: DebugElement = textCounterComponentFixture.debugElement.query(By.css('span'));
const el: HTMLElement = de.nativeElement;
let testHostComponent = hostComponentFixture.componentInstance;
testHostComponent.valueFromHost = 'a';
spyOn(testHostComponent.textCounterComponent, 'ngOnChanges').and.callThrough();
hostComponentFixture.detectChanges();
textCounterComponentFixture.detectChanges();
expect(testHostComponent.textCounterComponent.ngOnChanges).toHaveBeenCalled();
expect(el.textContent).toContain('il manque');//This fails!!
});
});
这是失败的断言:
Chrome 54.0.2840 (Mac OS X 10.12.1) Component: TextCounter should indicate min message FAILED
Expected '
' to contain 'il manque'.
有人可以帮忙吗?
修改1 :我尝试通过在固定el
之后移动 HTMLElement
detectChanges()
的检索来更改我的代码,如下所示:
...
const de: DebugElement = textCounterComponentFixture.debugElement.query(By.css('span'));
const el: HTMLElement = de.nativeElement;
expect(el.textContent).toContain('il manque');
无济于事......
答案 0 :(得分:3)
当您调用TestBed.createComponent
方法时,先前的组件将从DOM中删除。
第1步
<强> TestBad.createComponent 强>
...
const rootElId = `root${_nextRootElementId++}`;
testComponentRenderer.insertRootElement(rootElId); <== see this line
https://github.com/angular/angular/blob/2.2.4/modules/%40angular/core/testing/test_bed.ts#L358
第2步
打开@ angular / platform-browser-dynamic / testing / dom_test_component_renderer.ts
insertRootElement() {
...
// TODO(juliemr): can/should this be optional?
const oldRoots = getDOM().querySelectorAll(this._doc, '[id^=root]');
for (let i = 0; i < oldRoots.length; i++) {
getDOM().remove(oldRoots[i]);
}
...
我会写如下:
it('should indicate min message', () => {
const hostComponentFixture = TestBed.createComponent(TestHostComponent);
//const textCounterComponentFixture = TestBed.createComponent(TextCounterComponent);
const de: DebugElement = hostComponentFixture.debugElement
.query(By.css('text-counter > span'));
const el: HTMLElement = de.nativeElement;
let testHostComponent = hostComponentFixture.componentInstance;
testHostComponent.valueFromHost = 'a';
hostComponentFixture.detectChanges();
expect(el.textContent).toContain('il manque');//This should work!!
});
<强> Plunker Example 强>