I've created a component to render validation errors associated with form elements. The HTML produced by this component is very simple: @if (shouldShowErrors()) { <ul class="tbw-fed-error-list"> @for (error of listOfErrors(); track error) { <li class="tbw-warning-text tbw-fed-error">{{error}}</li> } </ul> } I've started writing a unit test for this component. That testing works properly when it comes to getting expected results from the listOfErrors() function seen above. I'd rather, however, make sure the HTML that should be generated by using listOfErrors() is correct. That HTML isn't being rendered during my unit test for reasons unknown. It's been a long time since I last had to write an Angular unit test, but I definitely remember testing the HTML my components were supposed to produce, and not having to make any special effort to do so. What I need to do now, many versions of Angular later, is a mystery to me that Googling hasn't answered so far. Here's my unit test code: import { FormErrorDisplayComponent } from './form-error-display.component'; import { Component, ViewChild } from '@angular/core'; import { FormControl, ReactiveFormsModule, Validators } from '@angular/forms'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; @Component({ template: ` <input type="text" [formControl]="control"/> <tbw-form-error-display #errorDisplay [control]="control"></tbw-form-error-display> `, standalone: false }) class FormControlComponent { control = new FormControl(''); @ViewChild('errorDisplay', { static: true }) errorDisplay: FormErrorDisplayComponent; } describe('FormErrorDisplayComponent', () => { let fixture: ComponentFixture<FormControlComponent>; let formControl: FormControlComponent; let errorDisplay: FormErrorDisplayComponent; let input: HTMLInputElement; function fakeTyping(s: string): void { input.value = s; input.dispatchEvent(new Event('input')); } beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [FormControlComponent], imports: [ReactiveFormsModule, FormErrorDisplayComponent] }).compileComponents(); fixture = TestBed.createComponent(FormControlComponent); input = fixture.debugElement.query(By.css('input')).nativeElement as HTMLInputElement; formControl = fixture.componentInstance; errorDisplay = formControl.errorDisplay; }); describe('shouldShowErrors', () => { it('should not try to show error if control is undefined', () => { errorDisplay.control = undefined; fixture.detectChanges(); expect(errorDisplay.shouldShowErrors()).toBeFalse(); }); it('should show no error if control is valid', () => { expect(errorDisplay.shouldShowErrors()).toBeFalse(); formControl.control.addValidators([Validators.required, Validators.minLength(4)]); fixture.detectChanges(); fakeTyping('book'); expect(errorDisplay.shouldShowErrors()).toBeFalse(); }); it('should show error if control is invalid', async () => { formControl.control.addValidators([Validators.required, Validators.minLength(4)]); fixture.detectChanges(); fakeTyping(''); expect(errorDisplay.shouldShowErrors()).toBeTrue(); // I don't want to merely check what listOfErrors() returns, I want to check the // rendered HTML that displays the error messages. expect(errorDisplay.listOfErrors()).toEqual(['This field is required']); // What's returned below is null, however. // There's nothing within my <tbw-form-error-display></tbw-form-error-display> // tags other than a <!--container--> comment. await fixture.whenStable(); console.log(fixture.debugElement.query(By.css('ul'))?.nativeElement); fakeTyping('abc'); expect(errorDisplay.shouldShowErrors()).toBeTrue(); expect(errorDisplay.listOfErrors()).toEqual(['The min. allowed number of characters is 4']); }); }); }); Anything more I should do beyond fixture.detectChanges() and fixture.whenStable() to get my tested component to render its HTML content? Continue reading...