[英]Angular Karma Jasmine Testing form validation error
我想測試以確保我在構建時給表單控件的驗證得到應用。 這可能是因為我在檢查錯誤之前設置了表單控件值? 該表單是在一個專門用於整體表單的服務中構建的。 這是一個 6 頁的登記表。 我想確保在我的 karma-jasmine 測試中應用了我用來構建表單的驗證器。 申請人在 onInit 中定義為一個向后端進行 http 調用的服務和另一個構建表單的服務。 我創建了一個通用注冊表模擬來表示從規范中的后端調用返回的數據。 理想情況下,我需要開始工作的是期望所需的驗證器和驗證器模式實際上是在構建時傳遞到表單中的內容:
(請參閱本文底部的錯誤照片)
expect(errors.required).toBeTruthy();
expect(errors.pattern).toBeTruthy();
此表單控件在構建時傳遞了 Validators.required。 但是,在測試驗證器錯誤顯示為未定義...
表單生成器:
phone_number: [null, Validators.required],
表單驗證規范:
it('phone number field validity - required', () => {
const phoneNumber = component.applicant.controls.phone_number;
expect(phoneNumber.valid).toBeFalsy();
phoneNumber.setValue(mockGenericMaEnrollmentRefresh.applicant.phone_number);
const errors = phoneNumber.errors || {};
// expect(errors.required).toBeTruthy();
expect(errors.pattern).toBe(undefined);
expect(phoneNumber.valid).toBeTruthy();
});
組件 HTML:
<mat-form-field>
<mat-label>Phone *</mat-label>
<input [textMask]="{mask: phoneMask}" formControlName="phone_number" id="phone_number" matInput
type="text">
<mat-error *ngIf="applicant.controls.phone_number.errors?.required">Phone Number is
required.
</mat-error>
</mat-form-field>
組件 TS:
import {Component, OnInit} from '@angular/core';
import {GoToStepConfig, MaNavigationService} from '../../services/ma-navigation/ma-navigation.service';
import {MaEnrollmentFormService} from '../../services/ma-enrollment-form/ma-enrollment-form.service';
import {FormControl, FormGroup} from '@angular/forms';
@Component({
selector: 'app-ma-personal-info',
templateUrl: './ma-personal-info.component.html',
styleUrls: ['./ma-personal-info.component.css']
})
export class MaPersonalInfoComponent implements OnInit {
phoneMask: any[] = [/\d/, /\d/, /\d/, '-', /\d/, /\d/, /\d/, '-', /\d/, /\d/, /\d/, /\d/];
mailingAddressSameAsResidential = new FormControl(null);
constructor(private maNavigationService: MaNavigationService,
private formService: MaEnrollmentFormService) {
}
get enrollmentForm(): FormGroup {
return this.formService.enrollmentForm;
}
get applicant(): FormGroup {
return this.formService.applicant as FormGroup;
}
get permanentAddress(): FormGroup {
return this.formService.permanentAddress as FormGroup;
}
get mailingAddress(): FormGroup {
return this.formService.mailingAddress as FormGroup;
}
get medicaid(): FormGroup {
return this.formService.medicaid as FormGroup;
}
get providerForm(): FormGroup {
return this.formService.providerForm as FormGroup;
}
ngOnInit() {
}
isApplicantBasicInfoValid(): boolean {
return this.applicant.controls.first_name.valid &&
this.applicant.controls.last_name.valid &&
this.applicant.controls.date_of_birth.valid &&
this.applicant.controls.phone_number.valid &&
this.applicant.controls.gender.valid;
}
isAddressValid(): boolean {
return this.permanentAddress.valid && this.mailingAddress.valid;
}
isMedicareInformationValid(): boolean {
return this.applicant.controls.medicare_claim_number.valid &&
this.applicant.controls.hospital_insurance_parta.valid &&
this.applicant.controls.medical_insurance_partb.valid &&
this.enrollmentForm.controls.proposed_effective_date.valid;
}
isMedicaidInformationValid(): boolean {
return this.providerForm.valid && this.medicaid.valid;
}
areAllControlsValid(): boolean {
return this.applicant.valid && this.medicaid.valid && this.providerForm.valid &&
this.enrollmentForm.controls.proposed_effective_date.valid;
}
back() {
this.maNavigationService.returnToQuotePage();
}
next() {
this.applicant.markAllAsTouched();
this.medicaid.markAllAsTouched();
this.permanentAddress.markAllAsTouched();
this.mailingAddress.markAllAsTouched();
this.providerForm.markAllAsTouched();
if (!this.areAllControlsValid()) {
return;
}
const goToStepConfig: GoToStepConfig = {
route: '/ma/enroll/2'
};
this.maNavigationService.goToStep(goToStepConfig);
}
}
///////////// PAGE 1 GETTERS FORM SERVICE ///////////////
get applicant(): FormGroup {
return this.enrollmentForm.get('applicant') as FormGroup;
}
get permanentAddress(): FormGroup {
return this.applicant.get('permanent_address') as FormGroup;
}
get mailingAddress(): FormGroup {
return this.applicant.get('mailing_address') as FormGroup;
}
get medicaid(): FormGroup {
return this.enrollmentForm.get('medicaid') as FormGroup;
}
get providerForm(): FormGroup {
return this.enrollmentForm.get('plan.primary_care_physician.provider') as FormGroup;
}
這個問題看起來像是沒有發生一些變化檢測。 當您直接更新內部值時,表單可能會有點奇怪。 只要表單檢測到發生了更改,驗證器邏輯就會重新運行,這通常發生在直接使用該字段時(想想模糊/臟)。 但是,您設置值的方式可能會繞過這一點。
確保驗證邏輯運行並獲得適當的錯誤響應/表單邏輯的一種方法是告訴表單控件它已過期。
component.yourForm.controls['yourFormField'].markAsTouched();
fixture.detectChanges();
這將運行驗證器,您將看到預期的行為。
請注意,您可能還想嘗試使用本機元素來更新表單,而不是轉到組件本身。 這確保測試檢查有助於模擬用戶體驗的模板。 如果您選擇執行該路線,則可以使用此代碼。
yourFormInput = dom.query(By.css('[formcontrolname=yourFormField]')).nativeElement;
yourFormInput.value = deviceName;
yourFormInput.dispatchEvent(new Event('input'));
fixture.detectChanges();
對我markAsTouched()
是調用markAsTouched()
函數並手動設置該控件的錯誤。
component.yourForm.controls['yourFormField'].markAsTouched();
component.yourForm.controls['yourFormField'].setErrors({ required: true });
fixture.detectChanges();
希望答案對其他人有幫助。
從 Angular 材料的第 9 版開始,隨測試 API 一起提供了 ComponentHarnesses。 對於測試墊輸入錯誤,您可以嘗試MatInputHarness
。
it( 'should display validation errors when the input is focus and the value is invalid', async () => {
const matFormFieldHarness = await loader.getHarness( MatFormFieldHarness );
const inputHarness = await matFormFieldHarness .getHarness( MatInputHarness );
await inputHarness.focus(); // focus in input
await inputHarness.setValue( invalid_value ); // set value to input
await inputHarness.blur(); // focus out input
const errors = await matFormFieldHarness.getTextErrors(); // get an array of
validation errors
expect( errors ).toContain( error_message );
} );
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.