Angular: How to spy on $element.on

旧时模样 提交于 2019-12-02 10:38:02

问题


I have a directive which does something like this in its link function

angular.module('myApp')
    .directive('barFoo', function() {
        return {
            restrict: 'E',
            link: function (scope, element) {
                element.on('click', ....);
            }
        };
    });

Now I would like to verify in my unit test that it calls on correctly

element = angular.element('<bar-foo></bar-foo>');
$compile(element)(scope);
spyOn(element, 'on');
...
expect(element.on).toHaveBeenCalled();

It tells me the spy is not called. From what I've found on the web, angular/jquery creates a new wrapper around the DOM element every time. Meaning the the element inside my directive is not the same as the element in my spec file. Most likely (not verified) the element[0] probably are the same. I've also tried to spy on angular.element

var mockEl = { on: angular.noop };
spyOn(angular, 'element').andReturn(mockEl);
spyOn(mockEl, 'on');

but that seems to break more than it fixes (I also need functions like isloateScope for example).

Anyway, is there some easy way I can spy on the on function of the element used inside a directive?


回答1:


Link function can be tested separately

element = angular.element('<bar-foo');
spyOn(element, 'on');
BarFooDirective[0].link(scope, element);
expect(element.on).toHaveBeenCalled();

if it is simple enough (stays away from attrs, required controllers, dependencies), otherwise the spec will cause more problems than it can solve.

Otherwise, it can be tested like it is done by the framework:

element = angular.element('<bar-foo');
expect(angular.element._data(element[0]).events.click).toBeDefined();

For real-world directive which may have more than one click listener defined in either itself or child directives it is not enough to make sure that listeners exist. Generally you may want to encapsulate internal functions, but anonymous click handler can also be exposed to scope for the purpose of testing:

element = angular.element('<bar-foo');
expect(angular.element._data(element[0]).events.click).toContain(scope.onClick);



回答2:


Well, it's not necessary to test on method. You can test event bindings with the help of triggerHandler()

link: function (scope, element) {
    element.on('click', 'something to heppen');
}

Test:

element = angular.element('<bar-foo></bar-foo>');
$compile(element)(scope); 
$(element[0]).triggerHandler('click');
expect('something binded to click event to happen');



回答3:


If you've compiled your element in in a beforeEach like this:

myEl = '<div my-el>MY EL</div>';
scope = $rootScope.$new();
directiveElement = $compile(myEl)(scope);
scope.$digest();

Try replacing mousedown with the event you are testing like this:

expect(directiveElement.on.mousedown).toBeDefined;


来源:https://stackoverflow.com/questions/33738918/angular-how-to-spy-on-element-on

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!