1

I am expending a lot of time trying to understand how the $httpBackend and the angular-translate could work together in order to test if the translation functionality still works.

I am in this point, and I really don't know how to solve this problem.

'use strict';

describe('Directive: translate', function () {

    beforeEach(function () {
        angular.module('myApp', ['pascalprecht.translate']);
    });

    var element,
        $compile,
        $rootScope,
        $http,
        $httpBackend;

    beforeEach(inject(function (_$rootScope_, _$compile_, _$httpBackend_, _$http_) {
        $compile = _$compile_;
        $rootScope = _$rootScope_;
        $http = _$http_;
        $httpBackend = _$httpBackend_;
    }));

    afterEach(function() {
        $httpBackend.verifyNoOutstandingExpectation();
        $httpBackend.verifyNoOutstandingRequest();
    });

    it('should translate to English', function () {
        element = $compile('<p translate>discover_more</p>')($rootScope);
        $rootScope.$digest();

        $httpBackend.expect('GET', 'langs/en.json').respond(200); // Should I return some data at this point?
        $http.get('langs/en.json').then(function () {}); // Should I do something here?
        $httpBackend.flush();

        expect(element.html()).toBe('Discover more');
    });

});

My test of course fails. The thing is that I don't know how to 1) really get the JSON with the data and 2) say the directive "here is your data, do your work".

Edit:

Ok, some light over the issue. I just was looking at the testing of this angular module (https://github.com/angular-translate/angular-translate/tree/master/test/unit/directive) and I could make it work:

'use strict';

describe('Directive: translate', function () {

    beforeEach(function () {
        angular.module('gajoApp', ['pascalprecht.translate']);
    });

    var element,
        $compile,
        $rootScope;

    beforeEach(module('pascalprecht.translate', function ($translateProvider) {
        $translateProvider
            .translations('en', {
                'discover_more': 'Discover more'
            })
            .preferredLanguage('en');
    }));

    beforeEach(inject(function (_$rootScope_, _$compile_) {
        $compile = _$compile_;
        $rootScope = _$rootScope_;
    }));

    it('should translate to English', function () {
        element = $compile('<p translate>discover_more</p>')($rootScope);
        $rootScope.$digest();

        expect(element.html()).toBe('Discover more');
    });
});

What I would like, however, is combine this solution with the proper AJAX calls that return the JSON, to test that this is been done too.

DanielM
  • 1,106
  • 3
  • 17
  • 27

2 Answers2

0

You should return from your expected GET request whatever the angular-translate need to actually replace the discover_more in your element.

beforeEach(function () {
    $httpBackend.when(
        'GET',
         'langs/en.json'
    ).respond({'discover_more': 'Discover more'});
}); 

Note, that I dont know the excact object that angular-translate expects, so it could differ from my suggestion. Anyway return it when the GET request is perceived.

In addition you're not supposed to make the GET request yourself within your test. If everything is set uo correctly, it should work if you add the expected return to your expected GET request.

Daniel
  • 6,916
  • 2
  • 36
  • 47
  • I already thought that no explicitly $http request must be present, but in fact when I do not do it, I get the error "No pending request to flush !". I have already tried your solution without success :/ The angular-translate seems to need something else before to run properly... But I don't know what that could be. Thanks for your attempt, anyway, Daniel. – DanielM Sep 02 '14 at 20:37
  • Trying to give more information... In fact, some configuration is needed via the $translatorProvider (set the prefix and the preferred language). Is it necessary to config this things for the tests, or the app config is got somehow? And in case it is, how could I call the .config() from inside the tests? Another thing is that if I try to inject $translate (could be an alternative to the first config) in the beforEach() just as I do it in the controllers where I use it, I get the error "Unknown provider: $translateProvider". – DanielM Sep 02 '14 at 21:04
0

Unfortunately it is due to restrictions on angular-translate, but you can use your real JSON locale file by either:

1) Using a plugin to load JSON files combined with $httpBackend to load your locale file when angular-translate requests it.

beforeEach(inject(function (_$httpBackend_) {
    $httpBackend = _$httpBackend_;

    $httpBackend.whenGET('locale-pt.json').respond(readJSON('langs/en.json'));
    $httpBackend.flush();
})));

2) Overriding your app's translations with the $translateProvider.translations() method with a JSON read by a plugin to load JSON files

beforeEach(module(function ($translateProvider) {
    $translateProvider.translations('en', readJSON('langs/en.json'));
}));

Note this should be below your beforeEach(module('myApp')); or you will get an $injector error.

Bruno Peres
  • 2,980
  • 1
  • 21
  • 19