Angularjs 测试指令的正确方法

Angularjs 测试指令的正确方法,angularjs,unit-testing,mocha.js,karma-runner,browserify,Angularjs,Unit Testing,Mocha.js,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

假设我构建了非常简单的指令:

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 ''
moment=require'moment'#如您所见,我正在使用browserify
###每当鼠标悬停时,它都会显示相对时间###
app.directive'simpleDirective',->
限制:“E”
范围:日期:'='
模板:“{niceDate}}”
控制器:($scope)->
$scope.$watch'hover',->
$scope.niceDate=如果$scope.hover
时刻($scope.date).fromNow()
否则“
现在,我可以使用如下测试轻松测试指令是否正确编译:

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'")
描述“简单直接测试”,->
$compile=$rootScope=未定义
在每个模块之前('myApp')
每次注入之前($compile,$rootScope)->
$compile=\$compile_
$rootScope=\$rootScope_
它“用适当的内容替换元素”,->
var元素=$compile(“”)($rootScope)
$rootScope.$digest()
expect(element.html()).toContain(“class='nice-date'))
现在,如何测试
mouseenter
的行为?我的意思是,首先,我不知道如何进入控制器的内部。而且,我也不知道如何从测试中访问
moment.js
(我正在用卡玛和摩卡)


我应该把
moment.js
东西变成ng服务依赖吗?那就意味着每一件我用过的东西都要作为角度服务导入?或者我只是在测试中使用browserify?然后,每个spec文件都必须单独浏览,因为测试没有单一的入口点

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

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);
  });
});
description('simlpleDirective',function(){
var$scope$compile;
在每个模块之前(模块(‘myApp’);
beforeach(注入($rootScope,$compile){
//始终创建一个新的作用域,以防止将根作用域永久性地弄脏用于其他测试
$scope=$rootScope.$new();
$compile=\$compile_
});
它('将元素替换为内容或类似内容',函数(){
//提取日期,以便稍后进行测试
变量日期=新日期(),
元素;
$scope.mydate=日期;
$scope.$apply(函数(){
元素=$compile(“”)($scope);
});
//您可以在此完全访问已编译的元素
expect(element.find('.nice date').text()).toBe('');
//您还可以在此处访问$scope变量
预期($scope.niceDate.)为(“”);
//你可能应该在另一个测试中包装悬停的东西,但我在这里很懒
formattedDate=时刻(日期).fromNow();
//手动触发悬停事件
元素.find('.nice date').triggerHandler('mouseenter');
//现在再次检查其中一个或两个
//此处可能需要$scope.$apply或$scope.$digest
expect(element.find('.nice date').text()).toBe(formattedDate);
expect($scope.niceDate).toBe(formattedDate);
});
});
希望这能有所帮助注意此代码尚未测试,因此可能需要一些调整以满足您的需要


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

太棒了,迈克!谢谢。我试试看。茉莉花不是问题。我只是需要从一个大的角度来看待它。