Javascript 如何在PhantomJS测试中单击A指令

Javascript 如何在PhantomJS测试中单击A指令,javascript,angularjs,phantomjs,yeoman,yeoman-generator-angular,Javascript,Angularjs,Phantomjs,Yeoman,Yeoman Generator Angular,应用程序由Yeoman使用角度生成器生成 指令: angular.module('psApp').directive('scrollTop', function () { return { restrict: 'A', scope: true, template: '<a href="#" ng-click="click()" class="scroll-top"><span class="glyphicon glyphicon-arrow-up"&

应用程序由Yeoman使用角度生成器生成

指令:

angular.module('psApp').directive('scrollTop', function () {
  return {
    restrict: 'A',
    scope: true,
    template: '<a href="#" ng-click="click()" class="scroll-top"><span class="glyphicon glyphicon-arrow-up"></span> Back to top</a>',
    controller: ['$scope', '$element', '$document', function ($scope, $element, $document) {
      $scope.click = function () {
        $document.scrollTop(0, 500);
      };
    }]
  };
});
angular.module('psApp')。指令('scrollTop',函数(){
返回{
限制:“A”,
范围:正确,
模板:“”,
控制器:['$scope','$element','$document',函数($scope,$element,$document){
$scope.click=函数(){
$document.scrollpop(0500);
};
}]
};
});
测试:

description('指令:scrollTop',函数(){
//加载指令的模块
在每个(模块(‘psApp’)之前;
var范围、要素;
beforeach(注入(函数($rootScope,$compile){
scope=$rootScope.$new();
元素=$compile(“”)(范围);
作用域:$apply();
}));
它('应该有“返回顶部”作为文本',注入(函数(){
expect(element.html()).toBe(“”);
expect(element.text()).toBe('backtotop');
元素。单击();
}));
});
错误:

PhantomJS 1.9.7(Mac OS X)指令:scrollTop应将“返回顶部”作为文本 TypeError:“undefined”不是函数(正在计算“element.click()”)


我不明白问题出在哪里(请发布函数代码。

由于某些原因,PhantomJS中没有click()函数。以下是解决方法:

//Need to create a cross browser click() function no .click() in PhantomJS
function click(el){
    var ev = document.createEvent('MouseEvent');
    ev.initMouseEvent(
        'click',
        true /* bubble */, true /* cancelable */,
        window, null,
        0, 0, 0, 0, /* coordinates */
        false, false, false, false, /* modifier keys */
        0 /*left*/, null
    );
    el.dispatchEvent(ev);
}
下面是如何使用它:

it('Should set the month when the month is changed', function(){
    var obj = element[0].getElementsByClassName('month_opt')[1];
    click(obj);
    expect(scope.dt.getMonth()).toEqual(1);
});

这不是PhantomJS的缺陷,而是AngularJS附带的jqLite包的已知限制。它的元素类中没有“click”函数:

出于测试目的,有两种替代方法

  • 在测试中包含jQuery。如果包含jQuery,jqLite包将自动替换为完整的jQuery包,该包具有完整的click()实现。我意识到这并不理想,因为您的应用程序可能不使用jQuery
  • 使用jqLite的“triggerHandler()”函数调用click处理程序。但是这种方法会使用一个虚拟事件调用处理程序;请参阅triggerHandler的文档。测试代码如下所示:

    element.triggerHandler('click');
    
    由于triggerHandler不传递“真实”事件对象,因此可能需要相应地调整测试


  • 这不是测试浏览器操作的地方(在本例中,请单击)。在单元测试中,您应该对其进行测试,以便只需从范围中单击操作即可进行测试:

    $scope.$$childHead.click(); // in test $$childHead is scope of your directive in application
    ...your assertions here
    

    您要测试的是,单击浏览器是更多的集成测试,因为您正在测试单击浏览器并在指令中响应->例如,这是Selenium的更多工作。

    好的,我会这样做,但如何知道它是否被滚动?我在单击之前和之后使用$window.scrollY进行了尝试();但它等于0。怎么了?干杯!这是一个完全不同的问题,我没有答案。抱歉。答案可能来自这里:这是可能的,但我无法知道,因为我在发布前几个月从同事那里得到了此解决方案。可能重复,因为已接受的答案与最新的答案非常相似投了一票。这是一个非常好的答案。它分析了问题并展示了两种可能的解决方案。非常有趣。我必须尝试一下。
    $scope.$$childHead.click(); // in test $$childHead is scope of your directive in application
    ...your assertions here