单元测试指令,测试不返回值
unit testing directive, tests not returning value
您好,我想测试一个指令,但我实在是太累了。
这是我目前的测试:
describe('pbImagePicker', function () {
beforeEach(module('pb.campaigns.directives'));
beforeEach(module('ui.router'));
beforeEach(module('ui.bootstrap'));
var $compile;
var element;
var $rootScope;
beforeEach(inject(function (_$compile_, _$rootScope_, _$document_) {
$compile = _$compile_;
$rootScope = _$rootScope_;
$document = _$document_;
scope = $rootScope.$new();
}));
describe('template', function () {
it('should render HTML based on scope correctly', function () {
scope.campaign = {
fileId: '43253',
accountId: '3874',
imageSource: 'http://www.gravatar.com/avatar/12345?s=40&d=identicon',
width: '250',
height: '250'
};
var element = $compile('<img data-ng-src="{{ imageSource }}" width="{{width}}" height="{{height}}" alt="Image Picker" class="img-rounded" />')(scope);
scope.$digest();
expect(element.html()).toEqual('<img data-ng-src="http://www.gravatar.com/avatar/12345?s=40&d=identicon" width="250" height="250" alt="Image Picker" class="img-rounded" />');
//expect(element.attr('src')).toBe('http://www.gravatar.com/avatar/12345?s=40&d=identicon');
});
});
describe('element.click()', function () {
var campaign = {
fileId: '43253',
accountId: '3874',
imageSource: 'http://www.gravatar.com/avatar/12345?s=40&d=identicon',
width: '250',
height: '250'
};
var image = {
storageUrl: 'http://www.pressboard.com/avatar/7453',
fileId: 6432342
};
var accountId = 543222;
var pickImage = function (accountId) {
var defer = $q.defer();
defer.resolve(image);
return defer.promise;
};
//beforeEach(function () {
// element = angular.element('<img data-ng-src="{{ imageSource }}" width="{{width}}" height="{{height}}" alt="Image Picker" class="img-rounded" />');
// compiled = $compile(element)(scope);
// compiled.triggerHandler('click');
//});
it('should resolve a promise when clicked', function () {
scope.campaign = campaign;
scope.accountId = accountId;
scope.pickImage = pickImage;
element = angular.element('<img data-ng-src="{{ imageSource }}" width="{{width}}" height="{{height}}" alt="Image Picker" class="img-rounded" />');
compiled = $compile(element)(scope);
compiled.triggerHandler('click');
spyOn(scope, 'pickImage');
scope.$digest();
expect(scope.pickImage).toHaveBeenCalledWith(scope.accountId);
});
it('should assign data from resolved promise when clicked', function () {
scope.campaign = campaign;
scope.accountId = accountId;
scope.pickImage = pickImage;
element = angular.element('<img data-ng-src="{{ imageSource }}" width="{{width}}" height="{{height}}" alt="Image Picker" class="img-rounded" />');
compiled = $compile(element)(scope);
compiled.triggerHandler('click');
scope.$digest();
expect(scope.imageSource).toEqual('http://www.pressboard.com/avatar/7453');
expect(scope.fileId).toEqual(6432342);
});
});
});
这是我正在测试的指令:
angular.module('pb.campaigns.directives')
.directive('pbImagePicker', ['$window', '$document', function ($window, $document) {
return {
restrict: "E",
template: '<img data-ng-src="{{ imageSource }}" width="{{width}}" height="{{height}}" alt="Image Picker" class="img-rounded" />',
scope: {
fileId: '=pbFileId',
accountId: '=pbAccountId',
defaultSrc: '@pbDefaultSrc',
width: '@pbWidth',
height: '@pbHeight'
},
controller: 'pbImagePickerController',
link: function (scope, element, attrs) {
scope.$watch('defaultSrc', function (value) {
if (value !== undefined) {
scope.imageSource = value;
}
});
element.click(function () {
scope.pickImage(scope.accountId).then(function (image) {
scope.imageSource = image.storageUrl;
scope.fileId = image.fileId;
}, function () {
console.log('Modal dismissed at: ' + new Date());
});
});
}
};
}]);
我得到的错误是:
Test 'pbImagePicker template:should render HTML based on scope correctly' failed
Expected '' to equal '<img data-ng-src="http://www.gravatar.com/avatar/12345?s=40&d=identicon" width="250" height="250" alt="Image Picker" class="img-rounded" />'.
Test 'pbImagePicker element.click():should resolve a promise when clicked' failed
Expected spy pickImage to have been called with [ 543222 ] but it was never called.
Test 'pbImagePicker element.click():should assign data from resolved promise when clicked' failed
Expected undefined to equal 'http://www.pressboard.com/avatar/7453'.
我真的很困惑如何继续,或者我是否在正确的轨道上。 angular 用于测试指令的文档有点缺乏。如果其他人在入门时遇到问题,http://blog.ninja-squad.com/2015/01/27/5-tricks-about-directives-and-tests/ 对入门有很大帮助。
感谢任何提示!
您有几个错误...我将使用您的第一个单元测试进行解释:describe('template')
当你编译你的元素时,你将属性 "width" 设置为 {{width}} 而不是 {{campaign.width}} (基于你的范围定义)等等......
如果你想测试你的指令,你应该测试属性和 class 而不是 element.html() 因为模板是一个 <img/>
标签
更新
对指令的定义做了一些修改:
//--- CODE --------------------------
angular.module('pb.campaigns.directives', [])
.directive('pbImagePicker', ['$q', function ($q) {
return {
restrict: "E",
replace : 'true',
scope: {
fileId: '=pbFileId',
accountId: '=pbAccountId',
defaultSrc: '@pbDefaultSrc',
width: '@pbWidth',
height: '@pbHeight'
},
template: '<img ' +
'data-ng-src="{{imageSource }}" '+
'alt="Image Picker" ' +
'width="{{width}}" ng-click="clickFn(imageSource, fileId)" '+
'height="{{height}}"/>',
//controller: 'pbImagePickerController',
link: function (scope, element, attrs) {
scope.$watch('defaultSrc', function (value) {
if (value !== undefined) {
scope.imageSource = value;
}
});
element.addClass('img-rounded');
function pickImage() {
var image = {
storageUrl: 'http://www.pressboard.com/avatar/7453',
fileId: 6432342
};
var deferred = $q.defer();
deferred.resolve(image);
return deferred.promise;
}
scope.clickFn = function () {
pickImage()
.then(function (image) {
// we encounter a non-assign error on scope.fileId
// due to isolated scope assignment
// Expression '{0}' used with directive '{1}' is non-assignable!
//https://docs.angularjs.org/error/$compile/nonassign
scope.imageSource = image.storageUrl;
//scope.fileId = image.fileId;
}, function () {
console.log('Modal dismissed at: ' + new Date());
});
};
}
};
}]);
规范测试 模板和点击事件的完整测试
//------- SPECS - TESTING -------------
describe('pb.campaigns.directives', function () {
var $compile,
elem,
element,
$rootScope,
$scope;
beforeEach(function () {
module('pb.campaigns.directives');
inject(function ($q, _$rootScope_, _$compile_, _$controller_, _$document_) {
scope = _$rootScope_.$new();
scope.campaign = {
fileId: '43253',
accountId: '3874',
imageSource: 'http://www.gravatar.com/avatar/12345?s=40&d=identicon',
width: '250',
height: '250'
};
element = angular.element(
'<pb-image-picker '+
'file-id="campaign.fileId" ' +
'account-id="campaign.accountId" ' +
'pb-default-src="{{campaign.imageSource}}" ' +
'pb-width="{{campaign.width}}" ' +
'pb-height="{{campaign.height}}">' +
'<pb-image-picker/>'
);
_$compile_(element)(scope);
scope.$digest();
});
});
describe('template', function () {
it('should render HTML based on scope correctly', function () {
scope.imageSource = scope.campaign.imageSource;
expect(scope.imageSource).toMatch(scope.defaultSrc);
expect(element.attr('data-ng-src')).toEqual(scope.imageSource);
expect(element.hasClass('img-rounded')).toBe(true);
expect(element.attr('alt')).toMatch('Image Picker');
expect(element.attr('width')).toEqual('250');
expect(element.attr('height')).toEqual('250');
});
});
describe('element click', function () {
beforeEach (inject(function($q) {
$scope = element.isolateScope();
$scope.$apply();
spyOn($scope, 'clickFn').andCallThrough();
element.triggerHandler('click');
}));
afterEach(function(){
$scope.$apply();
});
it('should resolve a promise when clicked', function () {
expect($scope.clickFn).toBeDefined();
expect($scope.clickFn).toHaveBeenCalled();
});
it('should assign data from resolved promise when clicked', function () {
expect($scope.imageSource)
.toEqual('http://www.pressboard.com/avatar/7453');
// expect($scope.fileId).toEqual(6432342);
});
});
});
注意:正如 tasseKat 指出的那样,第一个 post 不是测试指令的正确方法(对此感到抱歉)。相反,它是试图向您展示在 it()
函数中写入的内容。希望这个版本是一个更好的例子。
我有一个 jsfiddle 来演示(供你玩)
您好,我想测试一个指令,但我实在是太累了。 这是我目前的测试:
describe('pbImagePicker', function () {
beforeEach(module('pb.campaigns.directives'));
beforeEach(module('ui.router'));
beforeEach(module('ui.bootstrap'));
var $compile;
var element;
var $rootScope;
beforeEach(inject(function (_$compile_, _$rootScope_, _$document_) {
$compile = _$compile_;
$rootScope = _$rootScope_;
$document = _$document_;
scope = $rootScope.$new();
}));
describe('template', function () {
it('should render HTML based on scope correctly', function () {
scope.campaign = {
fileId: '43253',
accountId: '3874',
imageSource: 'http://www.gravatar.com/avatar/12345?s=40&d=identicon',
width: '250',
height: '250'
};
var element = $compile('<img data-ng-src="{{ imageSource }}" width="{{width}}" height="{{height}}" alt="Image Picker" class="img-rounded" />')(scope);
scope.$digest();
expect(element.html()).toEqual('<img data-ng-src="http://www.gravatar.com/avatar/12345?s=40&d=identicon" width="250" height="250" alt="Image Picker" class="img-rounded" />');
//expect(element.attr('src')).toBe('http://www.gravatar.com/avatar/12345?s=40&d=identicon');
});
});
describe('element.click()', function () {
var campaign = {
fileId: '43253',
accountId: '3874',
imageSource: 'http://www.gravatar.com/avatar/12345?s=40&d=identicon',
width: '250',
height: '250'
};
var image = {
storageUrl: 'http://www.pressboard.com/avatar/7453',
fileId: 6432342
};
var accountId = 543222;
var pickImage = function (accountId) {
var defer = $q.defer();
defer.resolve(image);
return defer.promise;
};
//beforeEach(function () {
// element = angular.element('<img data-ng-src="{{ imageSource }}" width="{{width}}" height="{{height}}" alt="Image Picker" class="img-rounded" />');
// compiled = $compile(element)(scope);
// compiled.triggerHandler('click');
//});
it('should resolve a promise when clicked', function () {
scope.campaign = campaign;
scope.accountId = accountId;
scope.pickImage = pickImage;
element = angular.element('<img data-ng-src="{{ imageSource }}" width="{{width}}" height="{{height}}" alt="Image Picker" class="img-rounded" />');
compiled = $compile(element)(scope);
compiled.triggerHandler('click');
spyOn(scope, 'pickImage');
scope.$digest();
expect(scope.pickImage).toHaveBeenCalledWith(scope.accountId);
});
it('should assign data from resolved promise when clicked', function () {
scope.campaign = campaign;
scope.accountId = accountId;
scope.pickImage = pickImage;
element = angular.element('<img data-ng-src="{{ imageSource }}" width="{{width}}" height="{{height}}" alt="Image Picker" class="img-rounded" />');
compiled = $compile(element)(scope);
compiled.triggerHandler('click');
scope.$digest();
expect(scope.imageSource).toEqual('http://www.pressboard.com/avatar/7453');
expect(scope.fileId).toEqual(6432342);
});
});
});
这是我正在测试的指令:
angular.module('pb.campaigns.directives')
.directive('pbImagePicker', ['$window', '$document', function ($window, $document) {
return {
restrict: "E",
template: '<img data-ng-src="{{ imageSource }}" width="{{width}}" height="{{height}}" alt="Image Picker" class="img-rounded" />',
scope: {
fileId: '=pbFileId',
accountId: '=pbAccountId',
defaultSrc: '@pbDefaultSrc',
width: '@pbWidth',
height: '@pbHeight'
},
controller: 'pbImagePickerController',
link: function (scope, element, attrs) {
scope.$watch('defaultSrc', function (value) {
if (value !== undefined) {
scope.imageSource = value;
}
});
element.click(function () {
scope.pickImage(scope.accountId).then(function (image) {
scope.imageSource = image.storageUrl;
scope.fileId = image.fileId;
}, function () {
console.log('Modal dismissed at: ' + new Date());
});
});
}
};
}]);
我得到的错误是:
Test 'pbImagePicker template:should render HTML based on scope correctly' failed
Expected '' to equal '<img data-ng-src="http://www.gravatar.com/avatar/12345?s=40&d=identicon" width="250" height="250" alt="Image Picker" class="img-rounded" />'.
Test 'pbImagePicker element.click():should resolve a promise when clicked' failed
Expected spy pickImage to have been called with [ 543222 ] but it was never called.
Test 'pbImagePicker element.click():should assign data from resolved promise when clicked' failed
Expected undefined to equal 'http://www.pressboard.com/avatar/7453'.
我真的很困惑如何继续,或者我是否在正确的轨道上。 angular 用于测试指令的文档有点缺乏。如果其他人在入门时遇到问题,http://blog.ninja-squad.com/2015/01/27/5-tricks-about-directives-and-tests/ 对入门有很大帮助。
感谢任何提示!
您有几个错误...我将使用您的第一个单元测试进行解释:describe('template')
当你编译你的元素时,你将属性 "width" 设置为 {{width}} 而不是 {{campaign.width}} (基于你的范围定义)等等......
如果你想测试你的指令,你应该测试属性和 class 而不是 element.html() 因为模板是一个 <img/>
标签
更新 对指令的定义做了一些修改:
//--- CODE --------------------------
angular.module('pb.campaigns.directives', [])
.directive('pbImagePicker', ['$q', function ($q) {
return {
restrict: "E",
replace : 'true',
scope: {
fileId: '=pbFileId',
accountId: '=pbAccountId',
defaultSrc: '@pbDefaultSrc',
width: '@pbWidth',
height: '@pbHeight'
},
template: '<img ' +
'data-ng-src="{{imageSource }}" '+
'alt="Image Picker" ' +
'width="{{width}}" ng-click="clickFn(imageSource, fileId)" '+
'height="{{height}}"/>',
//controller: 'pbImagePickerController',
link: function (scope, element, attrs) {
scope.$watch('defaultSrc', function (value) {
if (value !== undefined) {
scope.imageSource = value;
}
});
element.addClass('img-rounded');
function pickImage() {
var image = {
storageUrl: 'http://www.pressboard.com/avatar/7453',
fileId: 6432342
};
var deferred = $q.defer();
deferred.resolve(image);
return deferred.promise;
}
scope.clickFn = function () {
pickImage()
.then(function (image) {
// we encounter a non-assign error on scope.fileId
// due to isolated scope assignment
// Expression '{0}' used with directive '{1}' is non-assignable!
//https://docs.angularjs.org/error/$compile/nonassign
scope.imageSource = image.storageUrl;
//scope.fileId = image.fileId;
}, function () {
console.log('Modal dismissed at: ' + new Date());
});
};
}
};
}]);
规范测试 模板和点击事件的完整测试
//------- SPECS - TESTING -------------
describe('pb.campaigns.directives', function () {
var $compile,
elem,
element,
$rootScope,
$scope;
beforeEach(function () {
module('pb.campaigns.directives');
inject(function ($q, _$rootScope_, _$compile_, _$controller_, _$document_) {
scope = _$rootScope_.$new();
scope.campaign = {
fileId: '43253',
accountId: '3874',
imageSource: 'http://www.gravatar.com/avatar/12345?s=40&d=identicon',
width: '250',
height: '250'
};
element = angular.element(
'<pb-image-picker '+
'file-id="campaign.fileId" ' +
'account-id="campaign.accountId" ' +
'pb-default-src="{{campaign.imageSource}}" ' +
'pb-width="{{campaign.width}}" ' +
'pb-height="{{campaign.height}}">' +
'<pb-image-picker/>'
);
_$compile_(element)(scope);
scope.$digest();
});
});
describe('template', function () {
it('should render HTML based on scope correctly', function () {
scope.imageSource = scope.campaign.imageSource;
expect(scope.imageSource).toMatch(scope.defaultSrc);
expect(element.attr('data-ng-src')).toEqual(scope.imageSource);
expect(element.hasClass('img-rounded')).toBe(true);
expect(element.attr('alt')).toMatch('Image Picker');
expect(element.attr('width')).toEqual('250');
expect(element.attr('height')).toEqual('250');
});
});
describe('element click', function () {
beforeEach (inject(function($q) {
$scope = element.isolateScope();
$scope.$apply();
spyOn($scope, 'clickFn').andCallThrough();
element.triggerHandler('click');
}));
afterEach(function(){
$scope.$apply();
});
it('should resolve a promise when clicked', function () {
expect($scope.clickFn).toBeDefined();
expect($scope.clickFn).toHaveBeenCalled();
});
it('should assign data from resolved promise when clicked', function () {
expect($scope.imageSource)
.toEqual('http://www.pressboard.com/avatar/7453');
// expect($scope.fileId).toEqual(6432342);
});
});
});
注意:正如 tasseKat 指出的那样,第一个 post 不是测试指令的正确方法(对此感到抱歉)。相反,它是试图向您展示在 it()
函数中写入的内容。希望这个版本是一个更好的例子。
我有一个 jsfiddle 来演示(供你玩)