javascript - How to ng-click an A directive in a PhantomJS test - Stack Overflow

App generated by Yeoman with angular-generator.Directive:angular.module('psApp').directive(&#

App generated by Yeoman with angular-generator.

Directive:

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

Test:

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

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

  var scope, element;

  beforeEach(inject(function ($rootScope, $pile) {
    scope = $rootScope.$new();
    element = $pile('<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();
  }));
});

Error:

PhantomJS 1.9.7 (Mac OS X) Directive: scrollTop should have "Back to top" as text TypeError: 'undefined' is not a function (evaluating 'element.click()')

I cannot understand where the problem is. :( Please post functional code.

App generated by Yeoman with angular-generator.

Directive:

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

Test:

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

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

  var scope, element;

  beforeEach(inject(function ($rootScope, $pile) {
    scope = $rootScope.$new();
    element = $pile('<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();
  }));
});

Error:

PhantomJS 1.9.7 (Mac OS X) Directive: scrollTop should have "Back to top" as text TypeError: 'undefined' is not a function (evaluating 'element.click()')

I cannot understand where the problem is. :( Please post functional code.

Share Improve this question edited Sep 17, 2014 at 23:35 Artjom B. 62k26 gold badges135 silver badges230 bronze badges asked Aug 28, 2014 at 17:36 Thales PThales P 3711 gold badge6 silver badges17 bronze badges 1
  • possible duplicate of PhantomJS; click an element since the accepted answer is very similar to the most upvoted one. – Artjom B. Commented Sep 17, 2014 at 23:39
Add a ment  | 

3 Answers 3

Reset to default 5

This is not a deficiency of PhantomJS, but rather a known limitation of the jqLite package that is included with AngularJS. It does not have a 'click' function in its element class: https://docs.angularjs/api/ng/function/angular.element

There are two alternate approaches for testing purposes.

  1. Include jQuery in your tests. If jQuery is included, the jqLite package is automatically replaced with the full jQuery package, which does have the full click() implementation. I realize that this is not ideal, since your application presumably does not use jQuery.
  2. Use the 'triggerHandler()' function of jqLite to call the click handler. But this approach would call your handler with a dummy event; see the documentation for triggerHandler. Test code would look something like:

    element.triggerHandler('click');
    

    Since triggerHandler does not pass a 'real' event object, you might need to adjust your tests accordingly.

For some reason PhantomJS does not have a click() function in it. Here is the workaround:

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

And here is how to use it:

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

This isn't place for testing browser action (in this case click). In UNIT test you should test it isolated so test just click action from the scope:

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

The thing you want to test, click on the browser is more integration test since you are testing click in the browser and response in directive -> this is more job for Selenium for example.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744929009a4601618.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信