Angular中如何通过Jasmine测试获取<ng-template>内的元素
为什么你拿不到里的元素?
首先得澄清:这不是Shadow DOM的问题!querySelector自然找不到里面的按钮。
要测试里面的元素,你需要先手动把这个模板实例化并挂载到DOM里,具体步骤如下:
步骤1:给添加模板引用变量
先在你的组件模板里给目标模板加个引用,方便后续获取:
<ng-template #createTemplate> <button class="create"></button> </ng-template>
步骤2:在组件类中获取模板引用
在组件类里用@ViewChild拿到这个模板实例:
import { Component, ViewChild, TemplateRef } from '@angular/core'; @Component({ selector: 'app-some', templateUrl: './some.component.html' }) export class SomeComponent { @ViewChild('createTemplate') createTemplate!: TemplateRef<any>; }
步骤3:在Jasmine测试中实例化模板并查询元素
在测试代码里,你需要先创建组件,然后调用模板的createEmbeddedView方法把它嵌入到DOM中,之后再执行变更检测,最后就能查询到元素了:
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { SomeComponent } from './some.component'; describe('SomeComponent', () => { let fixture: ComponentFixture<SomeComponent>; let component: SomeComponent; let htmlElement: HTMLElement; beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [SomeComponent] }).compileComponents(); fixture = TestBed.createComponent(SomeComponent); component = fixture.componentInstance; htmlElement = fixture.nativeElement; }); it('should access button inside ng-template', () => { // 1. 实例化模板,把它挂载到组件的DOM中 const viewRef = component.createTemplate.createEmbeddedView(null); // 把模板的根节点添加到组件的nativeElement里 htmlElement.appendChild(viewRef.rootNodes[0]); // 2. 触发变更检测 fixture.detectChanges(); // 3. 现在就能查询到按钮了! const createBtn = htmlElement.querySelector('.create'); expect(createBtn).toBeTruthy(); }); });
额外情况:如果模板是通过结构指令触发的
如果你的*ngIf、*ngFor这类结构指令间接使用的(比如*ngIf其实是语法糖,背后会生成
it('should access button when ngIf is true', () => { // 假设按钮所在的模板是通过*ngIf="showCreateBtn"控制的 component.showCreateBtn = true; fixture.detectChanges(); const createBtn = htmlElement.querySelector('.create'); expect(createBtn).toBeTruthy(); });
内容的提问来源于stack exchange,提问作者Fabian
相关产品推荐
相关产品推荐

