正确的测试指令的方法

时间:2014-06-26 07:01:56

标签: angularjs unit-testing mocha karma-runner browserify

我们说我已经建立了非常简单的指令:

moment = require 'moment'   # as you can see I'm using browserify

###  whenever mouse hovered, it shows relative time ###
app.directive 'simpleDirective',->
   restrict: 'E'
   scope: date:'='
   template: "<div class='nice-date' date='date' ng-mouseenter='hover = true' 
                        ng-mouseleave='hover = false'>{{niceDate}}</div>"
   controller: ($scope)->
       $scope.$watch 'hover',->
          $scope.niceDate = if $scope.hover 
             moment($scope.date).fromNow()
          else ''

现在,我可以使用这样的测试轻松测试指令是否正确编译:

describe 'simpleDirective test', ->
    $compile = $rootScope = undefined
    beforeEach module('myApp')

    beforeEach inject (_$compile_, _$rootScope_) ->
      $compile = _$compile_
      $rootScope = _$rootScope_

    it 'Replaces the element with the appropriate content', ->
        var element = $compile("<simple-directive date='mydate' />")($rootScope)
        $rootScope.$digest()
        expect(element.html()).toContain("class='nice-date'")

现在,我该如何测试mouseenter的行为?我的意思是首先我不知道如何达到控制器的胆量。而且我也不知道如何从测试中访问moment.js(我使用kocha与mocha)。

我应该将moment.js内容转换为ng-service依赖吗?然后它意味着使用的每一件事我都必须作为角度服务导入?或者我可能只是在测试中使用browserify?然后每个spec文件都必须独立浏览,因为测试没有单一的入口点。

1 个答案:

答案 0 :(得分:2)

首先,您必须在配置文件中添加moment.js作为业力依赖(通常命名为karma.conf.js ...至少对于Node项目而言)。这样您就可以从测试中访问它。其次,这就是我写测试的方式:

describe('simlpleDirective', function() {
  var $scope, $compile;
  beforeEach(module('myApp'));

  beforeEach(inject($rootScope, _$compile_) {
    // Always create a new scope to prevent permanently dirtying the root scope for other tests
    $scope = $rootScope.$new();
    $compile = _$compile_
  });

  it('Replaces element with content or something like that', function() {
    // Abstract the date so that you can test it later
    var date = new Date(),
      element;

    $scope.mydate = date;

    $scope.$apply(function() {
      element = $compile("<simple-directive date='mydate'></simple-directive>")($scope);
    });

    // You have full access to the compiled element here
    expect(element.find('.nice-date').text()).toBe('');

    // You also have access to $scope variables here
    expect($scope.niceDate).toBe('');

    // You should probably wrap the hover stuff in another test, but I'm being lazy here
    formattedDate = moment(date).fromNow();
    // Manually trigger the hover event
    element.find('.nice-date').triggerHandler('mouseenter');

    // Now check one or both again
    // $scope.$apply or $scope.$digest might be necessary here
    expect(element.find('.nice-date').text()).toBe(formattedDate);
    expect($scope.niceDate).toBe(formattedDate);
  });
});

希望这会有所帮助。 注意此代码尚未经过测试,因此可能需要进行一些调整以满足您的需求。

注意2 我刚刚注意到我也在Jasmine中编写了这个测试。如果它不容易理解,请告诉我。