Unit testing Angular $filter with Jasmine

At RefME, we are firm believers in trying to unit test as much of our front-end code as possible. It is paramount to the stability of our platform moving forward. I recently came across a less documented process that is unit testing $filter of Angular.

To explain the process in a simple format, we will create a filter that capitalizes the content it is applied. Let's start off with the $filter itself:

angular.module('MyTestFilter', [])

.filter('capitalize', function() {
  return function(input, all) {
    return (!!input) ? input.replace(/([^\W_]+[^\s\-]*) */g, function (txt) {
      return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
    }) : '';
  };
});

The regex above is looking for words with spaces in between, we then use the replace function to run through every match and take the first character of each word and convert it to uppercase. Purely so we can get into the Jasmine side of testing the $filter, and then you can apply it to your more complex situation.

Right, let's get started on the test!

First, we need to do the basic setup for our jasmine test.

Note: I am going to presume you have already setup Jasmine to run through the terminal, if not, you should check out this tutorial.

describe('The capitalize filter', function () {
  'use strict'; 

  beforeEach(function () {
  });

  it('should capitalize the first letter of each word in a string', function () {
  });
});

To make the filter available to test we first have to make our module available in the beforeEach, and then we have to inject $filter.

describe('The capitalize filter', function () {
  'use strict'; 
  var $filter;

  beforeEach(function () {
    module('MyTestFilter');

    inject(function (_$filter_) {
      $filter = _$filter_;
    });
  });

  it('should capitalize the first letter of each word in a string', function () {
  });
});

We are almost there now, time to write the test itself, I like to use the Arrange, Act, and Assert methodology when writing my tests. Obviously you do not have to do the same, but I find it makes things very self-explanatory for other developers working on the same project to understand what is going on in your tests at first look. This is because it is clearly separating the setup from the verification of the unit test.

describe('The capitalize filter', function () {
  'use strict'; 
  var $filter;

  beforeEach(function () {
    module('MyTestFilter');

    inject(function (_$filter_) {
      $filter = _$filter_;
    });
  });

  it('should capitalize the first letter of each word in a string', function () {
    // Arrange
    var string = 'my now capitalized string',
        result;

    // Act    
    result = $filter('capitalize')(string);

    // Assert
    expect(string).toBe('My Now Capitalized String');
  });
});

The function filter should be what you wish to apply, in our case 'capitalize' followed by the string or array the filter is to be applied too. There are more parameters that can also be used with the $filter. I'll explain them all below.

    $filter('filter')(array, expression, comparator);
  • array: The source array, can be a string as in our case.
  • expression: Can be a string, object or function that gets the part of the array you wish to apply the filter too.
  • comparator: Is used to determine if the actual value and expected value should be considered a match. For more info on these take a look at the angular docs

So that's all there is to it. To see the working version of the test, please visit this JSFiddle I created.

Comments