Angular:如何测试单击组件 nativeElement 会打开一个对话框 [英] Angular: How to test that clicking on a component nativeElement opens a dialog
问题描述
我正在为呈现 mat-accordion
和 mat-expansion-panel
的组件编写测试.mat-expansion-panel 有一个 div(带有 .comment
类),它具有使用 [innerHtml]
的动态 html.有时,innerHtml 可能包含 <img/>
标签.当用户点击这样的 div
时,应该会弹出一个包含该图像的对话框(但尺寸更大).
I am writing a test for a component that renders mat-accordion
and mat-expansion-panel
. The mat-expansion-panel has a div (with class .comment
) that has dynamic html using [innerHtml]
. Sometimes the innerHtml could contain an <img />
tag. When the user clicks on such a div
, then a dialog should pop up containing that image (but in larger size).
在我的测试中,我想断言点击 img
应该打开这个对话框,但是,问题是当我检查 fixture.nativeElement
时,我确实看不到任何对话框元素.
In my test, I would like to assert that clicking on img
should open this dialog, however, the problem is that when I inspect fixture.nativeElement
, I indeed don't see any dialog element.
组件如下:
@Component({
selector: 'app-node-history',
templateUrl: './node-history.component.html',
styleUrls: ['./node-history.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class NodeHistoryComponent {
readonly data$: Observable<HistoryNode[]>;
constructor(private readonly resultService: ResultService, private readonly route: ActivatedRoute, public dialog: MatDialog) {
this.data$ = route.paramMap.pipe(
map(params => Number.parseInt(params.get('id')!, 10)),
filter(value => !!value),
switchMap(id => resultService.getResultHistoryForNode(id))
);
}
onCommentClick(event: MouseEvent) {
if ((event.target as HTMLElement)?.tagName === 'IMG') {
this.dialog.open(ImageDialogComponent, {
data: (event.target as HTMLElement).outerHTML,
maxHeight: '80vh'
});
}
}
}
规范文件是:
@Component({
template: '<router-outlet></router-outlet>'
})
class TestRootComponent {}
fdescribe('NodeHistoryComponent', () => {
function advance() {
tick();
rootFixture.detectChanges();
}
function navigateByNodeId(id: number) {
rootFixture.ngZone?.run(() => router.navigate(['history', 'node', id]));
}
let component: TestRootComponent;
let rootFixture: ComponentFixture<TestRootComponent>;
let router: Router;
let loader: HarnessLoader;
let httpTestingController: HttpTestingController;
afterEach(() => {
httpTestingController.verify();
});
beforeEach(async () => {
const fakeService = {
getResultHistoryForNode(id: number) {
console.log('Came here', id);
return of(mockResult);
}
} as Partial<ResultService>;
await TestBed.configureTestingModule({
declarations: [TestRootComponent, NodeHistoryComponent, ImageDialogComponent, DatePipe, SafePipe],
imports: [
MatDialogModule,
MatExpansionModule,
NoopAnimationsModule,
HttpClientTestingModule,
RouterTestingModule.withRoutes([
{
path: 'history/node/:id',
component: NodeHistoryComponent
}
])
],
providers: [
{
provide: ResultService,
useValue: fakeService
}
],
schemas: [NO_ERRORS_SCHEMA]
}).compileComponents();
rootFixture = TestBed.createComponent(TestRootComponent);
component = rootFixture.componentInstance;
router = TestBed.inject(Router);
rootFixture.detectChanges();
loader = TestbedHarnessEnvironment.loader(rootFixture);
httpTestingController = TestBed.inject(HttpTestingController);
});
it('should render img tags when comment has images', fakeAsync(async () => {
navigateByNodeId(123);
advance();
const panel = await loader.getAllHarnesses(MatExpansionPanelHarness);
expect(panel.length).toEqual(mockResult.length);
const text = await (await panel[1].host()).getCssValue;
const imageInComment = rootFixture.nativeElement.querySelector('.comment img') as HTMLImageElement;
expect(imageInComment).toBeDefined();
imageInComment.click();
advance();
/* The next assertion fails with the following error message:
Error: Failed to find element matching one of the following queries:
(MatDialogHarness with host element matching selector: ".mat-dialog-container")
*/
const dialog = await loader.getHarness(MatDialogHarness);
expect(dialog).toBeDefined();
}));
});
从规范文件中可能很清楚,由于组件依赖于 ActivatedRoute(这就是我需要 TestRootComponent
的原因),因此增加了复杂性.
As is probably clear from the spec file, there's an added complication because the component has a dependency on ActivatedRoute (which is why I need the TestRootComponent
).
非常感谢任何帮助:)
推荐答案
OverlayContainer 中有一个用于对话框的 documentRootLoader 线束加载器.
There's a documentRootLoader harness loader for dialogs in OverlayContainer.
documentRootLoader = TestbedHarnessEnvironment.documentRootLoader(fixture);
https:///stackblitz.com/edit/angular-harness-dialogs-3f7zju?file=src%2Fapp%2Fapp.component.spec.ts
这篇关于Angular:如何测试单击组件 nativeElement 会打开一个对话框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!