Search code examples
angularjsangularjs-components

Testing Angular 1.5 components : how to test $onChanges


I wanted to test my component's $onChanges after creating controller with $componentController service. However I didn't know how to trigger/test $onChanges. I tried to change bindings object that was passed to $componentController but changes were not picket up.

However I was able to do the same with the use of good old $compile & $rootScope:

describe("test component", function() {

    angular.module('test', []).component('component', {
        template: '<span>{{$ctrl.text}}</span>',
        bindings: {
            'text': '@'
        },
        controller: function() {

            this.$onChanges = function(changesObj) {
                console.log("onChanges called", changesObj);
            }
        }
    })

    var $compile, $rootScope;

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

    it('should call onChanges', function() {

        var scope = $rootScope.$new()
        scope.text = 'original text';
        var el = $compile('<component text="{{text}}" />')(scope);
        $rootScope.$apply();
        console.log(el.find('span').text())

        scope.text = 'text has changed';
        $rootScope.$apply();
        console.log(el.find('span').text())
    })
})

My question is: when testing $onChanges with $componentController, do I have to manually call $onChanges and build changesObj manually?


Solution

  • Yes, I think so. It helps to focus on the intention of your test.

    If you try some high-level manipulation that will eventually trigger the onChanges hook, you are actually exercising the internal behavior of Angular and your code at the same time. This is probably not your intention here.

    Acknowledging that you are using Angular and expecting something specific from this hook, calling it explicitly makes sense.