У меня такой контроллер ...
angular.module('jobBoard').controller('JobListController', ['$scope','$window', function($scope, $window){
$scope.keywordPlaceholder = 'What kind of job?';
$scope.locationPlaceholder = 'Where? (city, state or zip)';
$scope.onResize = function(){
if ($window.innerWidth <= 480){
$scope.keywordPlaceholder = 'What?';
$scope.locationPlaceholder = 'Where?';
}
}
angular.element($window).bind('resize', function(){
$scope.onResize();
$scope.$apply();
})
$scope.onResize();
$scope.loadJobs();
}]);
А это жасминовый тест ...
describe('JobListController', function(){
var scope, controller;
describe('binding resize to window', function(){
var mockWindow = {
resize: function(){}
}
beforeEach(inject(function($rootScope, $controller){
scope = $rootScope.$new();
$controller('JobListController', { $scope:scope, $window: mockWindow});
}))
it('binds to the resize function', function(){
spyOn(scope, 'onResize');
spyOn(scope, '$apply');
mockWindow.resize();
expect(scope.onResize).toHaveBeenCalled();
expect(scope.$apply).toHaveBeenCalled();
})
})
})
Но это не соответствует ожиданиям scope.onResize. Я как сумасшедший гуглил, как правильно это сделать, но не могу найти правильный ответ. Есть идеи? Спасибо.
2 ответа
Если честно, я никогда этого не пробовал, поэтому не могу сказать, сработает ли это. Однако - вы путаете вызов функции с запуском события. Ваш оператор bind
привязан к событию, а не к вызову функции.
Из документов MDN о событиях JavaScript вы должны можно сделать что-то вроде этого, чтобы создать событие с именем «изменение размера» и запустить его:
describe('binding resize to window', function(){
// Get a DOM element (there's probably a better way to do this...)
var mockWindow = angular.element('<div>')[0];
// create the event
var resizeEvent = new Event('resize');
beforeEach(inject(function($rootScope, $controller){
scope = $rootScope.$new();
$controller('JobListController', { $scope:scope, $window: mockWindow});
}))
it('binds to the resize function', function(){
spyOn(scope, 'onResize');
spyOn(scope, '$apply');
// call the event.
mockWindow.dispatchEvent(event);
expect(scope.onResize).toHaveBeenCalled();
expect(scope.$apply).toHaveBeenCalled();
})
})
Если вы хотите проверить, что вы прикрепляете к событию, служба Angular $window
отлично подходит для этой цели:
describe('JobListController', function(){
var scope, controller;
describe('binding resize to window', function(){
beforeEach(inject(function($rootScope, $controller){
scope = $rootScope.$new();
spyOn($window, 'addEventListener').and.callThrough();
$controller('JobListController', { $scope:scope });
}))
it('binds to the resize function', function() {
expect($window.addEventListener).toHaveBeenCalledWith('resize', scope.onResize);
})
})
})
В вашем контроллере выполните привязку, используя вместо этого addEventListener
:
$window.addEventListener('resize', scope.onResize);
Это также позволяет проверить, когда вы отключаете событие:
it('stop listening to window resize', function () {
compileDirective();
spyOn($window, 'removeEventListener');
scope.$destroy();
expect($window.removeEventListener).toHaveBeenCalledWith('resize', scope.onResize);
});
После этого вы можете самостоятельно протестировать свою логику scope.onResize
.
Плюсы:
- Легко сделать.
- Разрешить проверить развязку события
- Хорошо работает в любом браузере (даже PhantomJS)
Минусы:
- Он не проверяет взаимодействие между частями (событие, слушатель, обработчик). Для этого я полагаюсь на тесты более высокого уровня (например, E2E).
Похожие вопросы
Новые вопросы
angularjs
Используйте для вопросов об AngularJS (1.x), JavaScript-фреймворке с открытым исходным кодом. НЕ используйте этот тег для Angular 2 или более поздних версий; вместо этого используйте тег [angular].