使用karma

时间:2017-04-29 05:44:09

标签: angularjs angular gruntjs karma-runner karma-jasmine

我一直在努力让这项工作持续很长时间。我想测试一个$ scope.function,它根据target = e.currentTarget和input.val()进行api调用,但我现在正处于死点。基本上问题是,¿我如何模拟e.currentTarget以使测试通过?如果这不是正确的方法,¿你推荐我什么?我希望有一种方法,真的。我使用的很多函数都有“if e.currentTarget = xxx”行为。

这是我的控制器,工作正常

angular.module('myapp')
    .controller('myctrl', function($scope, $http) {
      var offset = 0;
      //search function
      var generalSearch = function(target) {
        $('.somediv').hide();
        if (target.hasClass('someclass') && $scope.paginationNext == true) {
          dostuff
        }
        if (target.hasClass('someclass') && $scope.paginationPrev == true) {
          dostuff
        }
        var getArtist = function (type='somevalue') {
          var query = $('#somediv').val();e
          var url = "someurl?query=" + query + '&offset='+ offset +'&limit=20&type='+ type;
          if (query !== '' && query !== null) {
            $http.get(url, {cache:true})
              .then(function(res) {
                $scope.somevar = res.data;
                if ($scope.result.length > 0) {
                  $('#somediv').hide();
                  $('.somediv').show(); //shows results
                }else {
                  $('#somediv').show();
                  $('.somep').text('').append("<i class='fa fa-frown-o' aria-hidden='true'></i> We couldn't find any artist nor album with that name");
                  setTimeout(
                    function() {
                      $('.somep').text('Your result will appear here');
                    }, 5000);
                }
                if (res.data.next !== null || res.data.albums.next !== null) {
                  $scope.paginationNext = true;
                }else {
                  $scope.paginationNext = false;
                }
                if (res.data.previous !== null || res.data.albums.previous !== null) {
                  $scope.paginationPrev = true;
                }else {
                  $scope.paginationPrev = false;
                }
            }, function(error) {
              //if the user search more than once, and there's no results, this will show the magnify again
              $('#somediv').show(); 
            });
          }else {
            $('.somep').text('').append("ERROR: We can't find what you want if you don't tell us what it is");
            setTimeout(
              function() {
                $('.somep').text('Your result will appear here');
              }, 5000);
          }     
        }
        getArtist();
      }
      $scope.startSearch = function Search(e) {    
        var target = $(e.currentTarget);
        generalSearch(target);
      }

这是我的测试,我认为我可以使用带模板和触发器的httpBackend来模拟电流目标,但始终得到TypeError: Cannot read property 'currentTarget' of undefined

describe('movie app tests', function () {
  var $controller;
  var $httpBackend;
  var $scope;
	var el, $compile, simpleHtml;
	
  beforeEach(module('spotify'));
  beforeEach(inject(function($rootScope, _$controller_, _$httpBackend_, $templateCache, _$compile_) {
    $controller = _$controller_;
    $scope = $rootScope.$new();
    $httpBackend = _$httpBackend_;
    $templateCache.put('./views/search/search.html', [
      '<section class="searcher-container visiond-20" id="searcher">',
      '	<form class="visiond-18 visiond-lg-8">',
      '		<fieldset class="searcher-wrapper">',
      '			<input type="text" id="artist" value="lamb of god">',
      '			<button ng-click="startSearch($event)" type="submit" class="searcher-button visiond-13 visiond-lg-5" id="searchButton">search</button> ',
      '		</fieldset>',
      '	</form>',
      '</section>'
    ].join(''));
    $compile = _$compile_;
  }));
  describe('http tests (original example)', function() {
    it('should load user defined movies on search', function () {
      $controller('ctrlSearch', { $scope: $scope });
	    simpleHtml = '<div ng-search id="searcher-container"></div>';
	    el = $compile(angular.element(simpleHtml))($scope);
	    $scope.$digest();
      var input = el.find('#artist');
      $scope.$apply(function() {
        angular.element(input).val('lamb of god');
      });
      el.find('.searcher-button').click();
      //$scope.startSearch();
      //$httpBackend.flush();
      //expect($scope.movies).toEqual(testData.query.starwars);
    });
  });
});

当你使用2到3个元素作为条件时,我想我可以按照另一种方法,测试是否启动startSearch然后分别测试其他函数,但我对角度测试很新,但实际上并不是知道如何继续,所以非常感谢一些帮助,谢谢我的进步!

1 个答案:

答案 0 :(得分:1)

我不确定你的&#34;如果e.currentTarget = xxx&#34;方法是正确的,但我为它写了一个简单的工作测试:

angular.module('spotify', [])
  .controller('SearchController', function($scope) {

    $scope.startSearch = function(e) {
     $scope.currentTarget = e.currentTarget;
    }
  });

describe('SearchController', function() {

  var $scope, $compile;

  beforeEach(module('spotify'));

  beforeEach(inject(function($rootScope, _$compile_) {
    $compile = _$compile_;
    $scope = $rootScope.$new();
  }));

  it('should start search', function() {   
    var html = [
      '<div ng-controller="SearchController">',
      ' <button ng-click="startSearch($event)" class="test-class">search</button>',
      '</div>'].join('');
    var elm = $compile(angular.element(html))($scope);
    var button = elm.find("button");
    $(button).click();

    expect(elm.scope().currentTarget).toBeDefined();
    expect(elm.scope().currentTarget.className).toBe('test-class');
  });
});

Run JSFiddle

它用一个按钮编译简单的控制器html,然后单击它。为了触发点击,我尝试在代码中使用与el.find('.searcher-button').click();类似的内容,但导致click未定义错误。使用jQuery有助于此。

请注意,您需要在断言中使用elm.scope()而不是$scopeelm.scope()返回在ngController指令元素与$scope链接期间创建的子范围。您可以在$compile docs中了解有关它的更多信息。