What is the idiomatic way of checking AngularJS directive?

What is the idiomatic way of doing integration memory testing in a directive?

For example, let's say I have a directive containing a button that, when pressed, changes color, will it be idiomatic for a DOM integration test?

color buttons directive-spec.js

var ColoredButtonDirective = require('../colored-button-directive');

describe('colored button', function() {

    var $compile, $rootScope;

    beforeEach(inject(function($templateCache, $rootScope, $injector) {
      // Should configuration of the module be located in the beforeEach?   
      angular.module('test', [])
            .directive('coloredButton', ColoredButtonDirective);
        $templateCache.put('./colored-button.html');            
        $compile = $injector.get('$compile'); // Can I have $compile injected instead?
    }));

    it('should turn red when clicked', function() {
        //arrange
        var dom, button;
        dom = $compile(angular.element('<colored-button></colored-button>'))($rootScope); // Must I inject a scope to the invocation of the link function?
        button = angular.element(dom.querySelector('button')); // Is there a better way of getting the button inside the rendered DOM?

        //act
        button.click();

        //assert
        expect(button.css('background-color')).toBe('red');
    });

});

color-button.html

<button ng-click='onClick'>My button</button>

<strong> color buttons-directive.js

return function ColoredButtonDirective() {
    return {
        scope: {
            onClick: function($event) {
                $event.currentTarget.css('background-color', 'red');
            }
        },
        restrict: 'E',
        template: require('./colored-button.html'),
        replace: true,
    };
};
+4
source share
1 answer

First, to answer your questions in the comments:

// Should configuration of the module be located in the beforeEach?   
angular.module('test', [])
  .directive('coloredButton', ColoredButtonDirective);

A more idiomatic way would be to do

beforeEach(module('test'));

https://code.angularjs.org/1.4.7/docs/guide/unit-testing. , ,

var app = angular.module('test', []);

.

$compile = $injector.get('$ compile');// $compile?

,

beforeEach(inject(function(_$rootScope_, _$compile_) {
  $rootScope = _$rootScope_;
  $compile = _$compile_;
}));

$compile

dom = $compile(angular.element('<colored-button></colored-button>'))($rootScope); // Must I inject a scope to the invocation of the link function?

, . , , , , DOM . ( , , ng-repeat ).

button = angular.element(dom.querySelector('button')); // Is there a better way of getting the button inside the rendered DOM?

, , , , , , :

  • dom - jQlite, querySelector
  • dom - jQlite , , .

, DOM, :

button = dom.find('button');

,

//act
button.click();

, jQlite 'click'. :

dom.triggerHandler('click');

,

scope: {
  onClick: function($event) {
    $event.currentTarget.css('background-color', 'red');
  }
}

, , scope. , , $event.target

link: function(scope, element, attrs) {
  scope.onClick = function($event) {
    angular.element($event.target).css('background-color', 'red');
  }
}

, $event,

<button ng-click='onClick'>My button</button>

<button ng-click='onClick($event)'>My button</button>

, ,

app.directive('coloredButton', function ColoredButtonDirective() {
  return {
    scope: {
    },
    restrict: 'E',
    template: '<button ng-click="onClick($event)">My button</button>',
    replace: true,
    link: function(scope, element, attrs) {
      scope.onClick = function($event) {
        angular.element($event.target).css('background-color', 'red');
      }
    }
  };
});

, :

describe('colored button', function() {
  var $compile, $rootScope;

  beforeEach(module('test'));

  beforeEach(inject(function(_$rootScope_, _$compile_) {
    $rootScope = _$rootScope_;
    $compile = _$compile_;
  }));

  it('should turn red when clicked', function() {
    var dom, button;
    dom = $compile(angular.element('<colored-button></colored-button>'))($rootScope);
    dom.triggerHandler('click');
    expect(dom.css('background-color')).toBe('red');
  });

});

http://plnkr.co/edit/L50B59V826Z6Wm8WtgJe?p=preview


.

, , .

app.directive('coloredButton', function ColoredButtonDirective() {
  return {
    scope: {
    },
    restrict: 'E',
    template: '<button ng-click="onClick()" ng-style="{\'background-color\': isRed ? \'red\' : \'\'}">My button</button>',
    link: function(scope, element, attrs) {
      scope.isRed = false;
      scope.onClick = function() {
        scope.isRed = true;
      }
    }
  };
});

, DOM, ,

  • ,
  • , -
  • , ,

. replace: true :

  • 2 3- ,

describe('colored button', function() {
  var $compile, $rootScope, dom, button, $scope;

  beforeEach(module('test'));

  beforeEach(inject(function(_$rootScope_, _$compile_) {
    $rootScope = _$rootScope_;
    $compile = _$compile_;
  }));

  beforeEach(function() {
    dom = $compile(angular.element('<colored-button></colored-button>'))($rootScope);
    button = dom.find('button');
    $scope = dom.isolateScope();
  });

  it('should call the onClick handler', function() {
    spyOn($scope, 'onClick');
    expect($scope.onClick).not.toHaveBeenCalled();
    button.triggerHandler('click');
    expect($scope.onClick).toHaveBeenCalled();
  });

  it('the onClick handler should set isRed to be true', function() {
    expect($scope.isRed).toBe(false);
    $scope.onClick();
    expect($scope.isRed).toBe(true);
  });

  it('setting isRed true should make the button red', function() {
    expect(button.css('background-color')).not.toBe('red');
    $scope.isRed = true;
    $scope.$apply();
    expect(button.css('background-color')).toBe('red');
  });
});

http://plnkr.co/edit/MmZGsYLopYP876Ft6ONG?p=preview

"unit-y", , , , , , . , 3 1, , , :

it('clicking should make the button red', function() {
  expect(button.css('background-color')).not.toBe('red');
  button.triggerHandler('click');
  expect(button.css('background-color')).toBe('red');
});

http://plnkr.co/edit/5WHzzzbpNFdqd94ITT8Q?p=preview

+1

Source: https://habr.com/ru/post/1615659/


All Articles