2

由 Yeoman 使用 angular-generator 生成的应用程序。

指示:

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);
      };
    }]
  };
});

测试:

describe('Directive: scrollTop', function () {

  // load the directive's module
  beforeEach(module('psApp'));

  var scope, element;

  beforeEach(inject(function ($rootScope, $compile) {
    scope = $rootScope.$new();
    element = $compile('<div scroll-top></div>')(scope);
    scope.$apply();
  }));

  it('should have "Back to top" as text', inject(function () {
    expect(element.html()).toBe('<a href="#" ng-click="click()" class="scroll-top"><span class="glyphicon glyphicon-arrow-up"></span> Back to top</a>');
    expect(element.text()).toBe(' Back to top');
    element.click();
  }));
});

错误:

PhantomJS 1.9.7 (Mac OS X) 指令:scrollTop 应该有“Back to top”作为文本类型错误:'undefined' 不是函数(评估'element.click()')

我无法理解问题出在哪里。:( 请发布功能代码。

4

3 回答 3

5

这不是 PhantomJS 的缺陷,而是 AngularJS 包含的 jqLit​​e 包的一个已知限制。它的元素类中没有“点击”功能: https ://docs.angularjs.org/api/ng/function/angular.element

有两种替代方法可用于测试目的。

  1. 在你的测试中包含 jQuery。如果包含 jQuery,jqLit​​e 包会自动替换为完整的 jQuery 包,该包确实具有完整的 click() 实现。我意识到这并不理想,因为您的应用程序可能不使用 jQuery。
  2. 使用 jqLit​​e 的 'triggerHandler()' 函数来调用点击处理程序。但是这种方法会使用虚拟事件调用您的处理程序;请参阅 triggerHandler 的文档。测试代码看起来像:

    element.triggerHandler('click');
    

    由于 triggerHandler 不传递“真实”事件对象,因此您可能需要相应地调整测试。

于 2014-09-17T20:05:04.273 回答
3

由于某种原因,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);
});
于 2014-08-29T14:04:22.583 回答
-1

这不是测试浏览器操作的地方(在这种情况下单击)。在 UNIT 测试中,您应该对其进行隔离测试,因此只需在范围内单击操作即可测试:

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

你想要测试的东西,点击浏览器是更多的集成测试,因为你正在测试浏览器中的点击和指令中的响应 - >这对于 Selenium 来说是更多的工作。

于 2015-03-10T09:23:03.837 回答