I trying to test a simple component:
HTML:
<ng-container *ngIf="lessThanTen(value) else moreThanTen">
<div
class="circle"
[ngClass]="{'active': isActive}"
>
{{value}}
</div>
</ng-container>
<ng-template #moreThanTen>
<div
class="rounded-rectangle"
[ngClass]="{'active': isActive}"
>
{{value}}
</div>
</ng-template>
TS:
export class MatchesCounterComponent {
@Input() public value: number;
@Input() public isActive: boolean;
public lessThanTen(value: number): boolean {
return value < 10;
}
}
And test:
describe('MatchesCounterComponent', () => {
let component: MatchesCounterComponent;
let fixture: ComponentFixture<MatchesCounterComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [MatchesCounterComponent],
}).compileComponents();
fixture = TestBed.createComponent(MatchesCounterComponent);
component = fixture.componentInstance;
fixture.detectChanges(); // IF REMOVE IT ALL WORKS CORRECT
});
it('should render circle if value is less than 10', () => {
component.value = 5;
fixture.detectChanges(); // DOESN'T WORK
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('.rounded-rectangle')).toBeNull();
expect(compiled.querySelector('.circle')).not.toBeNull();
});
});
Problem:
The test fails because the change detector does not fire a second time
Question: Why fixture.detectChanges() doesn't work second time in the "it" block? (value is undefined, but I directly changed it: component.value = 5).
If I remove fixture.detectChanges() from beforeEach block - all works correct.
If I set value via fixture.componentRef.setInput() - all works correct.
But I really interesting how CD works in this code.
Does your component use
ChangeDetectionStrategy.OnPush? If so, wrap it in a test host, as there is an issue with change detection for OnPush components in tests. The test host can be used as a workaround.