在 Angular 单元测试中使用 Modernizr
Using Modernizr in Angular unit test
我在 Grails gsp 中定义了一个 Angular 应用程序。 Modernizr 库包含在 gsp 级别。
我需要在指令单元测试中使用该库。由于我没有将 Modernizr 定义为模块,因为它在 Angular 应用程序外部和内部使用,我如何将它注入我的 Angular 单元测试?
这是我的指令:
'use strict';
angular.module('simplify.directives').directive('img', ['$timeout', function ($timeout) {
return {
restrict: 'A',
link: function (elem, attrs) {
if ( typeof Modernizr !== 'undefined' && !Modernizr.svg ) {
$timeout(function(){
elem.attr('src', attrs.src.replace('.svg', '.png'));
});
}
}
};
}]);
这是我的单元测试代码:
'use strict';
describe('Testing SVG to PNG directive', function() {
var scope,
elem;
beforeEach(module('app'));
beforeEach(module(function($provide) {
$provide.service('appConstants', function(){});
}));
beforeEach(inject(function($compile, $rootScope) {
elem = angular.element('<img ng-src="test-img.svg" />');
scope = $rootScope;
$compile(elem)(scope);
scope.$digest();
}));
it('Should swap svg for png image if svg is not supported', function() {
//force Modernizr.svg to be undefined here for purposes of the test
expect(elem.attr('src')).toBe('test-img.png');
});
});
执行此操作的最佳做法是什么?
您可以通过更新指令以注入 $window
并从 $window
获取 Modernizr
实例来做到这一点。
即:-
.directive('img', ['$timeout','$window', function ($timeout, $window) {
return {
restrict: 'E',
link: function (scope, elem, attrs) {
if ( typeof $window.Modernizr !== 'undefined' && !$window.Modernizr.svg ) {
$timeout(function(){
elem.attr('src', attrs.src.replace('.svg', '.png'));
});
}
}
};
}]);
在您的测试中,只需创建一个模拟 Modernizr,并且由于您使用的是 $timeout
,因此您需要通过执行 $timeout.flush()
来刷新 timeout
,以便执行超时回调。
describe('Testing SVG to PNG directive', function() {
var scope,
elem,
ModernizerMock = {svg:false};// <-- use this for mocking various conditions
beforeEach(module('app'));
beforeEach(module(function($provide) {
$provide.service('appConstants', function(){});
}));
beforeEach(inject(function($compile, $rootScope, $timeout, $window) {
elem = angular.element('<img ng-src="test-img.svg" />');
scope = $rootScope;
$window.Modernizr = ModernizerMock; //Set the mock
$compile(elem)(scope);
scope.$digest();
$timeout.flush(); //<-- Flush the timeout
}));
it('Should swap svg for png image if svg is not supported', function() {
//force Modernizr.svg to be undefined here for purposes of the test
expect(elem.attr('src')).toBe('test-img.png');
});
});
如果你的指令是这样的:
.directive('img', ['$window', function ($window) {
return {
restrict: 'E',
compile: function (elem, attrs) {
if ( typeof $window.Modernizr !== 'undefined' && !$window.Modernizr.svg ) {
attrs.$set('ngSrc', attrs.ngSrc.replace('.svg', '.png'));
}
}
};
}]);
在没有超时逻辑的情况下进行测试会更轻松。 Plnkr
我在 Grails gsp 中定义了一个 Angular 应用程序。 Modernizr 库包含在 gsp 级别。
我需要在指令单元测试中使用该库。由于我没有将 Modernizr 定义为模块,因为它在 Angular 应用程序外部和内部使用,我如何将它注入我的 Angular 单元测试?
这是我的指令:
'use strict';
angular.module('simplify.directives').directive('img', ['$timeout', function ($timeout) {
return {
restrict: 'A',
link: function (elem, attrs) {
if ( typeof Modernizr !== 'undefined' && !Modernizr.svg ) {
$timeout(function(){
elem.attr('src', attrs.src.replace('.svg', '.png'));
});
}
}
};
}]);
这是我的单元测试代码:
'use strict';
describe('Testing SVG to PNG directive', function() {
var scope,
elem;
beforeEach(module('app'));
beforeEach(module(function($provide) {
$provide.service('appConstants', function(){});
}));
beforeEach(inject(function($compile, $rootScope) {
elem = angular.element('<img ng-src="test-img.svg" />');
scope = $rootScope;
$compile(elem)(scope);
scope.$digest();
}));
it('Should swap svg for png image if svg is not supported', function() {
//force Modernizr.svg to be undefined here for purposes of the test
expect(elem.attr('src')).toBe('test-img.png');
});
});
执行此操作的最佳做法是什么?
您可以通过更新指令以注入 $window
并从 $window
获取 Modernizr
实例来做到这一点。
即:-
.directive('img', ['$timeout','$window', function ($timeout, $window) {
return {
restrict: 'E',
link: function (scope, elem, attrs) {
if ( typeof $window.Modernizr !== 'undefined' && !$window.Modernizr.svg ) {
$timeout(function(){
elem.attr('src', attrs.src.replace('.svg', '.png'));
});
}
}
};
}]);
在您的测试中,只需创建一个模拟 Modernizr,并且由于您使用的是 $timeout
,因此您需要通过执行 $timeout.flush()
来刷新 timeout
,以便执行超时回调。
describe('Testing SVG to PNG directive', function() {
var scope,
elem,
ModernizerMock = {svg:false};// <-- use this for mocking various conditions
beforeEach(module('app'));
beforeEach(module(function($provide) {
$provide.service('appConstants', function(){});
}));
beforeEach(inject(function($compile, $rootScope, $timeout, $window) {
elem = angular.element('<img ng-src="test-img.svg" />');
scope = $rootScope;
$window.Modernizr = ModernizerMock; //Set the mock
$compile(elem)(scope);
scope.$digest();
$timeout.flush(); //<-- Flush the timeout
}));
it('Should swap svg for png image if svg is not supported', function() {
//force Modernizr.svg to be undefined here for purposes of the test
expect(elem.attr('src')).toBe('test-img.png');
});
});
如果你的指令是这样的:
.directive('img', ['$window', function ($window) {
return {
restrict: 'E',
compile: function (elem, attrs) {
if ( typeof $window.Modernizr !== 'undefined' && !$window.Modernizr.svg ) {
attrs.$set('ngSrc', attrs.ngSrc.replace('.svg', '.png'));
}
}
};
}]);
在没有超时逻辑的情况下进行测试会更轻松。 Plnkr