Search code examples
angularjasmine

Jasmine - How to check angular pipe was called in the template


I expect my angular component should called TitleCasePipe from CommonModule.

Below my test files:

test.component.ts

import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import { CommonModule } from '@angular/common';

@Component({
  template: `<span>{{ text | titlecase }}</span>`,
  standalone: true,
  changeDetection: ChangeDetectionStrategy.OnPush,
  imports: [CommonModule]
})
export class TestComponent {
  @Input() text: string;
}

test.component.spec.ts

import { ChangeDetectionStrategy } from '@angular/core';
import { CommonModule, TitleCasePipe } from '@angular/common';
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { TestComponent } from './test.component';

describe('TestComponent', () => {
  let component: TestComponent;
  let fixture: ComponentFixture<TestComponent>;
  let titleCasePipeSpy: any = jasmine.createSpyObj('TitleCasePipe', ['transform']);

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [TestComponent, CommonModule],
      providers: [{ provide: TitleCasePipe, useValue: titleCasePipeSpy }],
    }).overrideComponent(TestComponent, {
      set: { changeDetection: ChangeDetectionStrategy.Default }
    }).compileComponents();

    fixture = TestBed.createComponent(TestComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should render text using titlecase', () => {
    component.test= 'test';
    fixture.detectChanges();

    expect(titleCasePipeSpy.transform).toHaveBeenCalledTimes(1);
  });
});

Result of my test: "Expected spy TitleCasePipe.transform to have been called once. It was called 0 times". What I missed here?


Solution

  • Give an input that will surely be transformed by titleCase pipe, so you can check the output in html instead of checking the function which gets executed outside the tested component! The logic happens in angular internally, so you cannot check if the transform method has been called!

    import { ChangeDetectionStrategy } from '@angular/core';
    import { CommonModule, TitleCasePipe } from '@angular/common';
    import { ComponentFixture, TestBed } from '@angular/core/testing';
    
    import { TestComponent } from './test.component';
    import { By } from '@angular/platform-browser';
    
    describe('TestComponent', () => {
      let component: TestComponent;
      let fixture: ComponentFixture<TestComponent>;
      let titleCasePipeSpy: any = jasmine.createSpyObj('TitleCasePipe', [
        'transform',
      ]);
    
      beforeEach(() => {
        TestBed.configureTestingModule({
          imports: [TestComponent, CommonModule],
          providers: [{ provide: TitleCasePipe, useValue: titleCasePipeSpy }],
        })
          .overrideComponent(TestComponent, {
            set: { changeDetection: ChangeDetectionStrategy.Default },
          })
          .compileComponents();
    
        fixture = TestBed.createComponent(TestComponent);
        component = fixture.componentInstance;
        fixture.detectChanges();
      });
    
      it('should render text using titlecase', () => {
        component.text = 'hello world';
        fixture.detectChanges();
    
        expect(
          fixture.debugElement.query(By.css('span')).nativeElement.textContent
        ).toContain('Hello World');
      });
    });
    

    stackblitz -> cd test -> npm i -> ng test to check the output!