[英]Unit testing component with @Input / @Output and reactive form
This is my component: 这是我的组件:
import { Component, OnInit, Input, Output, EventEmitter, ChangeDetectionStrategy, OnDestroy } from '@angular/core';
import { FormBuilder, FormGroup , Validators } from '@angular/forms';
import { Subscription } from 'rxjs';
import { Values } from '../_models/values';
@Component({
selector: 'some',
templateUrl: './my.component.html',
styleUrls: ['./my.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class Mycomponent implements OnInit, OnDestroy {
@Input()
values: Array<string>;
@Output()
selectedValues = new EventEmitter<Values>();
private myForm: FormGroup;
@Input()
errorMsg: string;
private selectSubscription: Subscription;
constructor(private fb: FormBuilder) {}
ngOnInit() {
this.myForm = this.fb.group({
'selectAll': [false],
'values': [this.values, Validators.required]
});
this.selectSubscription = this.myForm.get('selectAll').valueChanges.subscribe(value => {
this.changeSelection(value);
});
}
submit(): void {
console.log('called');
console.log(this.myForm.value.values);
const theSelectedValues = {
vals: this.myForm.value.values
};
this.selectedValues.emit(theSelectedValues);
}
private changeSelection(selectAll: boolean): void {
if (selectAll) {
const valuesSelect = this.myForm.controls['values'];
valuesSelect.disable();
} else {
this.myForm.controls['values'].enable();
}
}
ngOnDestroy() {
this.selectSubscription.unsubscribe();
}
}
The template: 模板:
<form [formGroup]="myForm" (ngSubmit)="submit()">
<fieldset>
<mat-checkbox formControlName="all">Select all</mat-checkbox>
</fieldset>
<fieldset>
<select id="chooser" formControlName="values" multiple>
<option *ngFor="let val of values?.urls" [value]="val">{{val}}</option>
</select>
</fieldset>
<button mat-button [disabled]="myForm.invalid">Go!</button>
</form>
<div *ngIf="errorMsg">{{errorMsg}}</div>
The test 考试
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { Mycomponent } from './my.component';
import { By } from '@angular/platform-browser';
import { FormBuilder } from '@angular/forms';
import { NO_ERRORS_SCHEMA } from '@angular/core';
describe('Mycomponent', () => {
let component: Mycomponent;
let fixture: ComponentFixture<Mycomponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [],
schemas: [NO_ERRORS_SCHEMA],
declarations: [Mycomponent],
providers: [
FormBuilder ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(Mycomponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should emit selected values', () => {
spyOn(component.selectedValues, 'emit');
component.values = ['abc', 'de'];
fixture.detectChanges();
expect(fixture.debugElement.queryAll(By.css('option')).length).toBe(2); // is 0
const formDE = fixture.debugElement.query(By.css('form'));
formDE.triggerEventHandler('ngSubmit', {});
// urls: null
expect(component.selectedValues.emit).toHaveBeenCalledWith({ vals: ['abc', 'de'] });
});
});
The test fails because 测试失败,因为
a) 一种)
component.values = ['abc', 'de'];
Does not lead to the form having two option elements 不导致表单具有两个选项元素
and b) 和b)
expect(component.selectedValues.emit).toHaveBeenCalledWith({ vals: ['abc', 'de'] });
Is called, but with { vals: null }
被调用,但使用
{ vals: null }
The code works, the app itself works fine, just the test is failing. 代码工作正常,应用程序本身正常运行,只是测试失败。
How do I set up the form properly, the @Input
element? 如何正确设置表单
@Input
元素?
I have looked at some blog posts but have not been able to adapt them to my code. 我看过一些博客文章,但无法使其适应我的代码。
This is because you are using Onpush
strategy. 这是因为您使用的是
Onpush
策略。 When onPush is used change detection is propagating down from the parent component not the component itself. 当使用onPush时,更改检测从父组件而不是组件本身向下传播。
My suggestion is to wrap your test component inside a host component. 我的建议是将测试组件包装在主机组件中。 There is a pending issue regarding this on Angular's gitHub page you can look it up for further reading.
Angular的gitHub页面上存在与此相关的未决问题,您可以查找它以进一步阅读。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.