【发布时间】:2021-06-26 13:18:20
【问题描述】:
我正在为呈现mat-accordion 和mat-expansion-panel 的组件编写测试。 mat-expansion-panel 有一个 div(类 .comment),它具有使用 [innerHtml] 的动态 html。有时innerHtml 可能包含<img /> 标签。当用户点击这样的div 时,应该会弹出一个对话框,其中包含该图像(但尺寸更大)。
在我的测试中,我想断言点击img 应该会打开这个对话框,但是,问题是当我检查fixture.nativeElement 时,我确实没有看到任何对话框元素。
组件如下:
@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'
});
}
}
}
spec 文件是:
@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 的原因)。
非常感谢任何帮助:)
【问题讨论】:
标签: angular angular-material jasmine karma-jasmine angular9