【问题标题】:How do I call triggerHandler with a specific fake 'event' parameter?如何使用特定的假“事件”参数调用 triggerHandler?
【发布时间】:2014-03-11 17:37:08
【问题描述】:

我正在尝试测试在链接上单击“preventDefault”是否被调用。但是,我很难用可以监视的对象替换真正的“事件”对象:

这是我触发点击事件的方式:

var e = jasmine.createSpyObj('e', [ 'preventDefault' ]);
$element.triggerHandler('click', [e]);

但是,当指令代码正在运行时,事件元素不会被假的替换:

$element.on('click', function(event) {
    console.log(event);
}

我尝试了将第二个参数添加到 triggerHandler 的不同方法 - 作为数组,作为对象,只是一些行等。都没有奏效.. triggerHandler 和附加参数的例子也不是很多,所以我觉得有点失落……

提前致谢!

【问题讨论】:

    标签: angularjs unit-testing


    【解决方案1】:

    当我们想要传递一个具有特定 which 属性值的测试事件时,我们也遇到了这个问题。

    正如 c0bra 所指出的,triggerHandler 函数会创建自己的虚拟事件对象,然后将其传递给事件处理程序。但是,您可以利用 triggerHandler 函数将使用传入的事件对象扩展虚拟事件这一事实,如果事件上有一个有价值的 type 属性: https://github.com/angular/angular.js/blob/v1.6.5/src/jqLite.js#L1043

    triggerHandler: function(element, event, extraParameters) {
        ...
        // If a custom event was provided then extend our dummy event with it
        if (event.type) {
            dummyEvent = extend(dummyEvent, event);
        }
        ...
    }
    

    在检查 Angular 代码后,我们发现当您从测试中调用 element.triggerHandler 时,它会首先调用一个匿名函数,然后调用 Angular 的 triggerHandler 函数。当调用 Angular 的 triggerHandler 函数时,它将元素作为第一个参数传递,然后是您在测试中传递给 triggerHandler 的第一个参数作为第二个参数,然后是您传递给 triggerHandler 的第二个参数第三个等https://github.com/angular/angular.js/blob/v1.6.5/src/jqLite.js#L1068

    这意味着您可以在测试中将一个对象作为第一个参数传递给triggerHandler,并且该对象的属性将附加到虚拟事件对象(如果虚拟对象上已有属性,则将被覆盖)同名),从而允许您传递特定值并添加间谍以进行测试。

    请注意,需要将事件类型作为对象的 type 属性传递给 triggerHandler,以满足上述 if 条件。例如,这就是我们在测试中使用triggerHandler 的方式:

    element.triggerHandler({
        type: 'keydown',
        which: 13
    });
    

    【讨论】:

    • 谢谢你,我正在尝试element.triggerHandler('keydown', { which: 27 }),但正如你提到的那样更改为element.triggerHandler({ type: 'keydown', which: 27 })解决了这个问题。
    • 快去丽莎!我也在使用 elm.triggerHandler ('keydown', {which:13});你的方式很完美。要补充的一件事。 . . event.which 返回一个整数,因此我必须删除 which 值上的单引号才能使其与我的实现一起使用:elm.triggerHandler({type: 'keydown', which: 13 });
    • element.triggerHandler({ type: 'keydown', keyCode: 27 }) 为我工作。 element.triggerHandler('keydown', {keyCode: 27 }) 没有。 IMO 这应该是公认的答案。
    • Lisa,当您链接到存储库中的源时,不要链接到分支(在这种情况下为 master),因为这是一个 moving target 但是到稳定的特定提交或标签。我在答案中修复了指向源的链接,将它们指向当前最新版本 1.6.5。
    【解决方案2】:

    文档说triggerHandler() 将一个虚拟对象传递给处理程序:http://docs.angularjs.org/api/ng/function/angular.element

    如果您查看源代码,您可以看到triggerHandler() 创建了自己的事件对象,然后将您的第二个参数作为事件数据传递,而不是实际的事件对象:

    https://github.com/angular/angular.js/blob/master/src/jqLite.js#L882

    相关代码:

    var event = [{
      preventDefault: noop,
      stopPropagation: noop
    }];
    
    forEach(eventFns, function(fn) {
      fn.apply(element, event.concat(eventData));
    });
    

    我使用 jQuery 的内部事件模拟器来创建我自己的事件。这可能对你有用:http://wingkaiwan.com/2012/09/23/triggering-mouse-events-with-jquery-simulate-when-testing-in-javascript/

    【讨论】:

      猜你喜欢
      • 2013-10-04
      • 2019-01-08
      • 2022-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-18
      相关资源
      最近更新 更多