1

I have a controller function which returns a string concatenated with the return value of a translate filter:

$scope.getDetails = function(history) {
  return angular.fromJson(history.value).name + $filter('translate')('CATALOGUE_HISTORY.ADD_ACTION');
};

I'm now writing a test to check the function returns the expected string, and have so far put together the following:

'use strict';
    describe('CatalogueHistoryController', function() {
      var $controller, $filter, $scope, controller, history;

      beforeEach(function() {
        module('app');
      });
      beforeEach(inject(function(_$controller_, _$filter_) {
        $controller = _$controller_;
        $filter = _$filter_;
      }));
      beforeEach(function() {
        $scope = {};
        $httpBackend.expectGET('assets/locale/en_gb.json').respond({})
        controller = $controller('CatalogueHistoryController', {
          $scope: $scope,
          $filter: $filter
        });
      });
      describe('$scope.getDetails', function() {
        beforeEach(function() {
          history = {
            value: "{\"id\":3,\"name\":\"Some Name\"}"
          };
        });
        it('should produce an add message', function() {
          expect($scope.getDetails(history)).toEqual('Some Name was added to the catalogue');
        });
      });
    });

When the test runs it fails with:

Expected 'Some NameCATALOGUE_HISTORY.ADD_ACTION' to equal 'Some Name was added to the catalogue'.

Do I need to mock out the translate filter in some way for the specific CATALOGUE_HISTORY.ADD_ACTION id?

EDIT

I am currently configuring angular translate like so:

angular.module('app').config(function($translateProvider) {
  $translateProvider.useStaticFilesLoader({
    prefix: 'assets/locale/',
    suffix: '.json'
  });
  $translateProvider.preferredLanguage('en_gb');
  $translateProvider.useSanitizeValueStrategy('sanitize');
});
mindparse
  • 6,115
  • 27
  • 90
  • 191
  • Where and how is angular translate configured? – JB Nizet Sep 04 '15 at 09:59
  • See my edit, I have actually added a $httpBackend.expectGET('assets/locale/en_gb.json') in the beforeEach but I am unsure how to set the respond property to the actual response to that json file. – mindparse Sep 04 '15 at 10:23
  • The easiest way is to use https://www.npmjs.com/package/karma-ng-json2js-preprocessor to define angular constants containing the json files, and to use a test module configuring angular-translate with these constants rather than a static file loader. No http request to mock anymore, and your real files are used – JB Nizet Sep 04 '15 at 10:29
  • Ok thanks for info, can you point me to any resources on how to set up a test module as you described? – mindparse Sep 04 '15 at 10:44
  • `$filter('translate')` uses `$translate.instant` internally. You should probably inject that into your controller, if you want to translate inside of your controller: – Thomas B Homburg Sep 04 '15 at 10:44

1 Answers1

2

I would mock the $filter and inject the mocked version of it.

Your goal in this specific test is to test your own function, not to test the filter. The filter test belongs to the filter implementation.

There are arguably many ways to mock a filter, here's one about the translate filter itself.

Once you make sure that whenever you call $filter('translate')('has been entered'); in your test it just returns the string you pass (i.e. 'has been entered' in this case) your test will be as simple as:

  describe('$scope.getDetails', function() {
    beforeEach(function() {
      history = {
        value: "{\"id\":3,\"name\":\"Some Name\"}"
      };
    });
    it('should produce an add message', function() {
      expect($scope.getDetails(history)).toEqual('Some Name has been entered');
    });
  });
Community
  • 1
  • 1
Aurelio
  • 24,702
  • 9
  • 60
  • 63