简体   繁体   中英

Unit testing angularjs directives's event broadcast

I never had to test my angularjs directives before, also the directives I wrote for my current company is uses events to communicated directives to directives and services.

And so I wrote a directive, eg a search directive.

<m-search />

This directive broadcasts "searchbox-valuechanged" event and the key, now I have to write tests for it.

'use strict';

describe('<m-search>', function() {

  beforeEach(module('hey.ui'));
  var rootScope;
  beforeEach(inject(function($injector) {
    rootScope = $injector.get('$rootScope');
    spyOn(rootScope, '$broadcast');
  }));

  it("should broadcast something", function() {
    expect(rootScope.$broadcast).toHaveBeenCalledWith('searchbox-valuechanged');
  });

});

Update On change on the input,

<input class="m-input m-input--no-border" type="search" placeholder="Search"
       ng-model="ctrl.searchValue"
       ng-model-options="{debounce: 100}"
       ng-change="ctrl.onChange({search: ctrl.searchValue})">

It calls a method in the directive's controller

vm.onChange = function (searchValue) {
  $rootScope.$broadcast('searchbox-valuechanged', {data: searchValue});
};

How do I test broadcasting?

Here's how I'd do it...

describe('m-search directive', function() {
    var ctrl, // your directive's controller
        $rootScope; // a reference to $rootScope

    beforeEach(function() {
        // bootstrap your module
        module('hey.ui');

        inject(function($compile, _$rootScope_) {
            $rootScope = _$rootScope_;
            // see https://docs.angularjs.org/api/ngMock/function/angular.mock.inject#resolving-references-underscore-wrapping-

            // create an instance of your directive
            var element = $compile('<m-search></m-search')($rootScope.$new());
            $rootScope.$digest();

            // get your directive's controller
            ctrl = element.controller('mSearch');
            // see https://docs.angularjs.org/api/ng/function/angular.element#methods

            // spy on $broadcast
            spyOn($rootScope, '$broadcast').and.callThrough();
        });
    });

    it('broadcasts searchbox-valuechanged on change', function() {
        var searchValue = {search: 'search string'};
        ctrl.onChange(searchValue);

        expect($rootScope.$broadcast).toHaveBeenCalledWith(
            'searchbox-valuechanged', {data: searchValue});
    });
});

You'll note this doesn't rely on your directive's template at all. I don't believe template functionality is in the realm of unit testing; that's something best left to e2e testing with protractor. Unit testing is about testing the API of your components to ensure they do what they're meant to do.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM