[Angular Unit Testing] Testing component with content projection

Component to be tested:

复制代码
<ng-template #defaultPlaceholder>
    Loading...
</ng-template>

<div class="loading-container" *ngIf="loading$ | async">
    <ng-container
        *ngTemplateOutlet="outlet ? outlet : defaultPlaceholder"
    ></ng-container>
</div>
复制代码
复制代码
import {
    Component,
    OnInit,
    Input,
    TemplateRef,
    AfterViewInit
} from '@angular/core'
import {LoadingService} from './loading.service'
import {Observable} from 'rxjs'

@Component({
    selector: 'loading',
    templateUrl: './loading.component.html',
    styleUrls: ['./loading.component.scss']
})
export class LoadingComponent implements OnInit, AfterViewInit {
    loading$: Observable<boolean>

    @Input() outlet: TemplateRef<any>

    ngAfterViewInit() {}

    constructor(private loadingService: LoadingService) {}

    ngOnInit(): void {
        this.loading$ = this.loadingService.loading$
    }

    get loadingContext() {
        return {
            type: 'placeholder'
        }
    }
}
复制代码

 

Test code:

复制代码
import {async, ComponentFixture, TestBed} from '@angular/core/testing'

import {LoadingComponent} from './loading.component'
import {LoadingService} from './loading.service'

import {ViewChild, Component, DebugElement} from '@angular/core'
import {of} from 'rxjs'
import {By} from '@angular/platform-browser'

@Component({
    template: `
        <ng-template #loadingTmp><p>loading...</p></ng-template>
        <loading [outlet]="loadingTmp"></loading>
    `
})
class WrapperComponent {
    @ViewChild(LoadingComponent) loadingComponentRef: LoadingComponent
}

let loadingServiceSpy = {
    loading$: of(true),
    get config() {
        return {showContent: false}
    }
}

describe('LoadingComponent', () => {
    let component: LoadingComponent
    let wrapperComponent: WrapperComponent
    let fixture: ComponentFixture<WrapperComponent>
    let el: DebugElement

    beforeEach(async(() => {
        TestBed.configureTestingModule({
            declarations: [WrapperComponent, LoadingComponent],
            providers: [{provide: LoadingService, useValue: loadingServiceSpy}]
        }).compileComponents()
    }))

    beforeEach(() => {
        fixture = TestBed.createComponent(WrapperComponent)
        wrapperComponent = fixture.debugElement.componentInstance
        fixture.detectChanges()
        component = wrapperComponent.loadingComponentRef
        el = fixture.debugElement
        fixture.detectChanges()
    })

    it('should create', () => {
        expect(wrapperComponent).toBeDefined()
        expect(component).toBeDefined()
    })

    it('should use has p tag with text loading...', () => {
        const p = el.queryAll(By.css('p'))
        expect(p.length).toBe(1)
        expect(p[0].nativeElement.textContent).toBe('loading...')
    })
})
复制代码

 

Idea is to create a WrapperComponent to include our component. Then we are able to project content which need to be passed into the testing component.

posted @   Zhentiw  阅读(3380)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
历史上的今天:
2019-03-25 [Git] Change the commit message of my last commit
2019-03-25 [Git] Squash all of my commits into a single one and merge into master
2019-03-25 [Git] Move some commits to a separate branch that I have accidentally committed to master
2019-03-25 [Functional Programming] Introduction to State, thinking in State
2019-03-25 [Algorithm] How many times is a sorted array rotated?
2016-03-25 [Angular 2] Simple intro Http
2016-03-25 [Typescript] Typescript Enums vs Booleans when Handling State
点击右上角即可分享
微信分享提示