Discover how to write tests for an Angular pipe ✨ ✨ ✨


Wish you knew how to test your Angular pipes?

pipes

PSST. Want to jump straight to the code? Then click here.

How do you properly test an Angular pipe?

How do you write tests for an Angular pipe? And make sure that it always behaves as intended?

Well...

The good news is that the Angular pipe is probably the easiest piece of our application that we could test.

Why?

First, because we don't have to mock any dependencies.

And second, the logic of a good Angular pipe is very straight-forward. Any Angular pipe worth its salt is simple and logical.

The bad news is... well... there is no bad news.

So, how do we get started?

We'll begin by testing the UpperCase pipe that is already part of the Angular framework.

I know. It doesn't need to be tested. 😊

But for the first example, I want to take a pipe that you're probably familiar with, that works well, and teach you how to test it.

Testing the UpperCase pipe

So, buster, here's the code to test the upper case pipe.

import { UpperCasePipe } from '@angular/common/';

describe('UpperCasePipe', () => {
  it('create an instance', () => {
    const pipe = new UpperCasePipe();
    expect(pipe).toBeTruthy();
  });
  it('pipe should be PIPE', () => {
    const pipe = new UpperCasePipe();
    let value = "pipe";
    let expected = "PIPE";

    expect(pipe.transform(value)).toEqual(expected);
  })
});

So how does this work?

We grab a new instance of the UpperCase pipe, call its transform function and check the results.

Simple?

Yup. 😎

How about we try another pipe? The CurrencyPipe.

Testing the Currency pipe

Angular has a CurrencyPipe that takes an amount and formats it depending on the currency type.

This example is different in that we have to initialize the pipe with a locale so that it knows how to properly transform the input.

import { CurrencyPipe } from '@angular/common/';

describe('CurrencyPipe', () => {
  it('create an instance', () => {
    const pipe = new CurrencyPipe("en-US");
    expect(pipe).toBeTruthy();
  });
  it('10.26 should be $10.26', () => {
    const pipe = new CurrencyPipe("en-US");
    let value = "10.26";
    let expected = "$10.26";

    expect(pipe.transform(value)).toEqual(expected);
  })
  it('1 should be $1.00', () => {
    const pipe = new CurrencyPipe("en-US");
    let value = "1";
    let expected = "$1.00";

    expect(pipe.transform(value)).toEqual(expected);
  })
});

But what about our own custom pipes?

How do we test those?

Building our own pipe

For this demo, we'll create a pimple-popping-simple greeting pipe.

It'll have the simple responsibility of taking a string and prepending Hello to it.

We'll begin by using the Angular CLI to generate a new pipe.

ng generate pipe hello

Then we'll edit it to look like this.

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'hello'
})
export class HelloPipe implements PipeTransform {

  transform(value: unknown, ...args: unknown[]): unknown {
    return `Hello ${value}`;
  }

}

So how do we test it?

Just like we tested the others.

Unit testing our new Angular pipe

import { HelloPipe } from './hello.pipe';

describe('HelloPipe', () => {
  it('create an instance', () => {
    const pipe = new HelloPipe();
    expect(pipe).toBeTruthy();
  });

  it ("expect John to equal Hello John", () => {
    const pipe = new HelloPipe();
    expect(pipe.transform("John")).toEqual("Hello John");
  })
});

Just like before, we begin by creating a new instance of our Angular pipe.

Then, we used it to transform an input and check the output.

Simple?

Sure. But this isn't all I wanted to show you.

Integration testing our Angular pipe

You're probably smart enough to realize this but in case you haven't caught on yet...

What we've just done is written a unit test for our Angular pipe.

But what if we want to write an integration test?

And test it inside of a component to make sure that it's rendering properly?

How do we write an integration test for our Angular pipe?

Inside of the component that uses our Angular pipe, we'll declare a test like this.

import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
import { HelloPipe } from './hello.pipe';

describe('AppComponent', () => {
  it('should say Hello Alice', () => {
    const fixture = TestBed.createComponent(AppComponent);
    const hostElement: HTMLElement = fixture.nativeElement;

    var paragraph = hostElement.querySelector("p");
    fixture.detectChanges();

    expect(paragraph.innerText).toBe("Hello Alice");
  });
});

So what did we just do?

We created our Angular component and grabbed a reference to the <p> element inside the component that uses our pipe.

Then, we ran the detection changer.

And finally, we made sure that the displayed value is the value that we expected the pipe to return.

Conclusion

And... BOOM!

We've just learned how to test Angular pipes. And make sure they never behave like monkeys let loose in a jungle.

Testing Angular pipes is one of the easiest pieces of an Angular application to test. Plus, it has one of the best ROI's that I know of.

Questions? Comments? Don't hesitate to reach out.

signature

Angular Consultant