如何测试组件模板包含mat-error
How to test that component template contains mat-error
我想为检查是否显示 mat-error 的组件创建测试。
我创建了一个测试,但它失败了,因为 DOM 在测试期间根本没有 mat-error。虽然它在项目服务时工作正常。
模板片段
<mat-error>
Error message
</mat-error>
测试设置
describe('MyComponent', () => {
let component: MyComponent;
let fixture: ComponentFixture<MyComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
MatFormFieldModule,
ReactiveFormsModule,
MatInputModule,
MatFormFieldModule,
BrowserAnimationsModule
],
declarations: [MyComponent]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(MyComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
fit('should display error', () => {
const matErrorEl: HTMLElement =
fixture.debugElement.query(By.directive(MatError)).nativeElement;
expect(matErrorEl).toBeTruthy();
});
});
tldr;在显示任何错误之前,您必须触摸 FormControl
。
您必须先触摸组件。
使用反应形式(其中 nameFormControl
是类型 FormControl
):
component.nameFormControl.markAsTouched();
您的 mat-error
元素现在将显示在视图中。
对于真实场景,您将在 mat-error
元素上有一个 ngIf
,并且还需要设置该错误。
示例模板:
<mat-error *ngIf="nameFormControl.hasError('required')">
Error message
</mat-error>
添加错误:
component.nameFormControl.setErrors({ required: true} as ValidationErrors);
这个问题的类似问题:
How to catch the <mat-error> error message text content using Protractor
关于Angular 表单验证的官方文档:
https://angular.io/guide/form-validation#why-check-dirty-and-touched
我采用了另一种方式,我使用了一个名为 spectator 的库来帮助我处理使用 angular-material spectator
的场景
文件测试
import { createComponentFactory, Spectator } from '@ngneat/spectator';
describe('InputEmailComponent', () => {
let spectator: Spectator<InputEmailComponent>;
const createComponent = createComponentFactory({
component: InputEmailComponent,
});
beforeEach(() => (spectator = createComponent()));
it(`should get the component mat-error with a email empty`, () => {
// Pass a value null for a email validator required
spectator.component.email.setValue(null);
expect(spectator.query('mat-error')).toHaveText('Insira um e-mail válido');
});
});
文件组件
import { Component, Input, OnInit } from "@angular/core";
import {
ControlContainer,
FormControl,
FormGroupDirective,
Validators,
} from "@angular/forms";
@Component({
selector: "input-email",
templateUrl: "./input-email.component.html",
viewProviders: [
{
provide: ControlContainer,
useExisting: FormGroupDirective,
},
],
})
export class InputEmailComponent implements OnInit {
@Input() style: string = "";
email: FormControl;
constructor() {
this.email = new FormControl("", [Validators.required, Validators.email]);
}
ngOnInit(): void {}
getErrorMessage(): string | null {
if (this.email.hasError("required") || this.email.hasError("email")) {
return "Insira um e-mail válido";
}
return null;
}
}
文件模板html
<mat-form-field [style]="style" appearance="fill">
<mat-label>e-mail</mat-label>
<input
type="email"
formControlName="email"
matInput
placeholder="digite seu e-mail"
/>
<mat-error *ngIf="!email.valid">{{ getErrorMessage() }}</mat-error>
</mat-form-field>
前几天我在使用 angular testing-library 和 Jest 时遇到了同样的问题。 @RonanCodes 的回答实际上让我走上了正确的轨道。不过,我还必须在 markAsTouched()
之后添加 detectChanges()
语句。
不可否认,我的设置有点不同,因为日期选择器是一个单独的共享组件,您可以在其中注入错误映射以根据添加到表单控件的验证器函数进行处理。
无论如何,如果添加 markAsTouched
无法解决您的问题,请尝试添加 detectChanges
。
it('should show error', async () => {
const reqMsg = 'This field is required';
const errors = new Map([['required', reqMsg]]);
const control = new FormControl(null, [Validators.required]);
const rc = await renderComponent('ariaLabel', 'label', control, errors);
control.setErrors({ required: true });
control.markAsTouched();
rc.detectChanges();
expect(screen.getByTestId('date-picker-error')).toHaveTextContent(reqMsg);
});
我想为检查是否显示 mat-error 的组件创建测试。
我创建了一个测试,但它失败了,因为 DOM 在测试期间根本没有 mat-error。虽然它在项目服务时工作正常。
模板片段
<mat-error>
Error message
</mat-error>
测试设置
describe('MyComponent', () => {
let component: MyComponent;
let fixture: ComponentFixture<MyComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
MatFormFieldModule,
ReactiveFormsModule,
MatInputModule,
MatFormFieldModule,
BrowserAnimationsModule
],
declarations: [MyComponent]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(MyComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
fit('should display error', () => {
const matErrorEl: HTMLElement =
fixture.debugElement.query(By.directive(MatError)).nativeElement;
expect(matErrorEl).toBeTruthy();
});
});
tldr;在显示任何错误之前,您必须触摸 FormControl
。
您必须先触摸组件。
使用反应形式(其中 nameFormControl
是类型 FormControl
):
component.nameFormControl.markAsTouched();
您的 mat-error
元素现在将显示在视图中。
对于真实场景,您将在 mat-error
元素上有一个 ngIf
,并且还需要设置该错误。
示例模板:
<mat-error *ngIf="nameFormControl.hasError('required')">
Error message
</mat-error>
添加错误:
component.nameFormControl.setErrors({ required: true} as ValidationErrors);
这个问题的类似问题:
How to catch the <mat-error> error message text content using Protractor
关于Angular 表单验证的官方文档:
https://angular.io/guide/form-validation#why-check-dirty-and-touched
我采用了另一种方式,我使用了一个名为 spectator 的库来帮助我处理使用 angular-material spectator
的场景文件测试
import { createComponentFactory, Spectator } from '@ngneat/spectator';
describe('InputEmailComponent', () => {
let spectator: Spectator<InputEmailComponent>;
const createComponent = createComponentFactory({
component: InputEmailComponent,
});
beforeEach(() => (spectator = createComponent()));
it(`should get the component mat-error with a email empty`, () => {
// Pass a value null for a email validator required
spectator.component.email.setValue(null);
expect(spectator.query('mat-error')).toHaveText('Insira um e-mail válido');
});
});
文件组件
import { Component, Input, OnInit } from "@angular/core";
import {
ControlContainer,
FormControl,
FormGroupDirective,
Validators,
} from "@angular/forms";
@Component({
selector: "input-email",
templateUrl: "./input-email.component.html",
viewProviders: [
{
provide: ControlContainer,
useExisting: FormGroupDirective,
},
],
})
export class InputEmailComponent implements OnInit {
@Input() style: string = "";
email: FormControl;
constructor() {
this.email = new FormControl("", [Validators.required, Validators.email]);
}
ngOnInit(): void {}
getErrorMessage(): string | null {
if (this.email.hasError("required") || this.email.hasError("email")) {
return "Insira um e-mail válido";
}
return null;
}
}
文件模板html
<mat-form-field [style]="style" appearance="fill">
<mat-label>e-mail</mat-label>
<input
type="email"
formControlName="email"
matInput
placeholder="digite seu e-mail"
/>
<mat-error *ngIf="!email.valid">{{ getErrorMessage() }}</mat-error>
</mat-form-field>
前几天我在使用 angular testing-library 和 Jest 时遇到了同样的问题。 @RonanCodes 的回答实际上让我走上了正确的轨道。不过,我还必须在 markAsTouched()
之后添加 detectChanges()
语句。
不可否认,我的设置有点不同,因为日期选择器是一个单独的共享组件,您可以在其中注入错误映射以根据添加到表单控件的验证器函数进行处理。
无论如何,如果添加 markAsTouched
无法解决您的问题,请尝试添加 detectChanges
。
it('should show error', async () => {
const reqMsg = 'This field is required';
const errors = new Map([['required', reqMsg]]);
const control = new FormControl(null, [Validators.required]);
const rc = await renderComponent('ariaLabel', 'label', control, errors);
control.setErrors({ required: true });
control.markAsTouched();
rc.detectChanges();
expect(screen.getByTestId('date-picker-error')).toHaveTextContent(reqMsg);
});