Как да щракнете с ng-щрак върху A директива в PhantomJS тест

Приложение, генерирано от Yeoman с ъглов генератор.

Директива:

angular.module('psApp').directive('scrollTop', function () {
  return {
    restrict: 'A',
    scope: true,
    template: '<a href="/bg#" 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="/bg#" 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 трябва да има „Назад към началото“ като текст. TypeError: „undefined“ не е функция (оценявайки „element.click()“)

Не мога да разбера къде е проблема. :( Моля, публикувайте функционален код.


person Thales P    schedule 28.08.2014    source източник
comment
възможен дубликат на PhantomJS; щракнете върху елемент, тъй като приетият отговор е много подобен на най-гласувания.   -  person Artjom B.    schedule 18.09.2014


Отговори (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);
});
person MBielski    schedule 29.08.2014
comment
добре, правя го, но как ще разбера дали е превъртяно? Опитах с $window.scrollY преди и след click(); но е равно на 0. Какво не е наред? наздраве! - person Thales P; 31.08.2014
comment
Това е съвсем различен въпрос и на него нямам отговор. съжалявам - person MBielski; 01.09.2014
comment
Отговорът вероятно е взет от тук: stackoverflow.com/questions/15739263/phantomjs -кликнете върху елемент - person Artjom B.; 18.09.2014
comment
Това е възможно, но няма начин да знам, тъй като получих това решение от колега няколко месеца преди тази публикация. - person MBielski; 18.09.2014

Това не е недостатък на PhantomJS, а по-скоро известно ограничение на пакета jqLite, който е включен в AngularJS. Той няма функция „щракване“ в своя клас елементи: https://docs.angularjs.org/api/ng/function/angular.element

Има два алтернативни подхода за целите на тестването.

  1. Включете jQuery във вашите тестове. Ако jQuery е включен, пакетът jqLite автоматично се заменя с пълния пакет jQuery, който има пълната реализация click(). Осъзнавам, че това не е идеално, тъй като приложението ви вероятно не използва jQuery.
  2. Използвайте функцията 'triggerHandler()' на jqLite, за да извикате манипулатора на щракване. Но този подход ще извика вашия манипулатор с фиктивно събитие; вижте документацията за triggerHandler. Тестовият код ще изглежда така:

    element.triggerHandler('click');
    

    Тъй като triggerHandler не предава „истински“ обект на събитие, може да се наложи да коригирате съответно вашите тестове.

person Mike Daly    schedule 17.09.2014
comment
Това е много добър отговор. Той анализира проблема и показва две възможни решения. - person Artjom B.; 18.09.2014
comment
Много интересно. Ще трябва да го пробвам. - person MBielski; 18.09.2014

Това не е място за тестване на действие на браузъра (в този случай щракване). В теста UNIT трябва да го тествате изолирано, така че тествайте просто кликване от обхвата:

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

Нещото, което искате да тествате, щракнете върху браузъра, е повече интеграционен тест, тъй като тествате щракване в браузъра и отговор в директива -> това е повече работа за Selenium например.

person Slaven Tomac    schedule 10.03.2015