使用 karma 在 Angular 中获取 e.currentTarget 的测试事件
test event that grabs e.currentTarget in Angular using karma
我已经尝试完成这项工作好几个小时了。我想测试基于 target = e.currentTarget
和 input.val()
进行 api 调用的 $scope.function
,但我现在处于死点。
问题是,如何模拟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 来模拟 e.current 目标,但总是得到 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 是否已启动,然后分别测试其他功能...
我不确定你的 "if e.currentTarget = xxx" 方法是否正确,但我为它写了一个简单的工作测试:
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');
});
});
一键编译简单控制器html,点击即可。为了触发点击,我尝试使用您的代码中类似于 el.find('.searcher-button').click();
的内容,但它导致 click
未定义错误。使用 jQuery 对此有所帮助。
请注意,您需要在断言中使用 elm.scope()
而不是 $scope
。 elm.scope()
returns 在 ngController
指令元素与 $scope
链接期间创建的子作用域。您可以在 $compile docs.
中了解更多信息
我已经尝试完成这项工作好几个小时了。我想测试基于 target = e.currentTarget
和 input.val()
进行 api 调用的 $scope.function
,但我现在处于死点。
问题是,如何模拟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 来模拟 e.current 目标,但总是得到 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 是否已启动,然后分别测试其他功能...
我不确定你的 "if e.currentTarget = xxx" 方法是否正确,但我为它写了一个简单的工作测试:
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');
});
});
一键编译简单控制器html,点击即可。为了触发点击,我尝试使用您的代码中类似于 el.find('.searcher-button').click();
的内容,但它导致 click
未定义错误。使用 jQuery 对此有所帮助。
请注意,您需要在断言中使用 elm.scope()
而不是 $scope
。 elm.scope()
returns 在 ngController
指令元素与 $scope
链接期间创建的子作用域。您可以在 $compile docs.