Returning HTML from a filter

When your filter returns HTML, you need to do stuff for Angular to be OK with it.

Step 1: Tell Angular it’s HTML it can trust:

//some filter code...

return $sce.trustAsHtml('html in here');

The $sce service can be injected into your filter like any other Angular service.

Step 2: Test it

describe('some filter tests', function () {
   beforeEach(module('my module'));

var f;

beforeEach(inject(function ($filter) {
      f = $filter('myFilter');
}));

describe('Given some thing...', function () {

  it('should should return me some html', function () {
    var filterResult = f('some input value').$$unwrapTrustedValue();
    expect(filterResult).toBe('<strong>HELLO</strong>&nbsp;<small>little people</small>');
  });
 });
});

Mocking dependencies for Angular tests

Two approaches are available

  1. Configure the $provide service in your test to supply the mocked dependency when the injector is materialising your SUT:
'use strict';

describe('Company Input Metrics controller', function () {
  var scope, controllerFactory, mockRepo = {}, q, cimsData, repoDefer, provide;

  function createController() {
    return controllerFactory('CIMCtrl', {
      $scope: scope,
    });
  }

  beforeEach(module('adminApp', function($provide) {
    // here the provide service is being scoped for later use
    provide = $provide;
  }));

  beforeEach(inject(function ($controller, $rootScope, $q) {
    scope = $rootScope.$new();
    q = $q;
    controllerFactory = $controller;
  }));
  
  beforeEach(function () {
    cimsData = [{
      nominalGDPPotential: 1,
      equityRiskBeta: 1,
      riskFree: 1,
      equityRiskPremium: 1,
      costOfCapital: 1
    }];

    repoDefer = q.defer();
    repoDefer.resolve(cimsData);
    mockRepo.getCims = sinon.stub().returns(repoDefer.promise);
    
    // here the provide service is being configured to supply the mockRepo when the 'CIMRepository' needs to be injected
    provide.value('CIMRepository', mockRepo);
  });

  describe('Given the user wants to configure company metrics', function () {

    describe('When the user views the metrics to edit them', function () {

      it('Then the metrics are displayed', function () {
        createController();
        scope.$digest();

        expect(mockRepo.getCims.called).toBeTruthy();
        expect(scope.cims).toBe(cimsData);
      });

    });
  });
});
	

 

2. Manually set the dependency to the mock in your test:

'use strict';

describe('Company Input Metrics controller', function () {
  var scope, controllerFactory, mockRepo = {}, q, cimsData, repoDefer;

  function createController() {
    return controllerFactory('CIMCtrl', {
      $scope: scope,
      // here the CIMRepository is manually being set to the the mockRepo for the controller
      CIMRepository: mockRepo
    });
  }

  beforeEach(module('adminApp'));

  beforeEach(inject(function ($controller, $rootScope, $q) {
    scope = $rootScope.$new();
    q = $q;
    controllerFactory = $controller;
  }));
  
  beforeEach(function () {
    cimsData = [{
      nominalGDPPotential: 1,
      equityRiskBeta: 1,
      riskFree: 1,
      equityRiskPremium: 1,
      costOfCapital: 1
    }];

    repoDefer = q.defer();
    repoDefer.resolve(cimsData);
    mockRepo.getCims = sinon.stub().returns(repoDefer.promise);
  });

  describe('Given the user wants to configure company metrics', function () {

    describe('When the user views the metrics to edit them', function () {

      it('Then the metrics are displayed', function () {
        createController();
        scope.$digest();

        expect(mockRepo.getCims.called).toBeTruthy();
        expect(scope.cims).toBe(cimsData);
      });

    });
  });
});

Go either way I suppose. I prefer manually setting the dependencies whenever possible. It’s more terse and at the end of the day, just plain JS which suits me fine.

Other things worth noting are the patterns used in the test for dealing with promises. The magic is here:

    repoDefer = q.defer();

    // this will resolve .then(fn(cimsData))...
    repoDefer.resolve(cimsData);

    mockRepo.getCims = sinon.stub().returns(repoDefer.promise);