我正在测试下面使用隔离范围的指令。我知道triggerHandler正在工作但由于某种原因我不断收到错误
预期未定义为等于'http://www.gravatar.com/avatar/12345?s=40&d=identicon'。
指令:
angular.module('pb.webSites.directives')
.directive('pbOrganizationImagePicker', [ function () {
return {
restrict: "E",
template: '<img data-ng-src="{{ imageSource }}" width="{{width}}" height="{{height}}" alt="Image Picker" class="img-rounded" />',
scope: {
fileId: '=pbFileId',
defaultSrc: '@pbDefaultSrc',
width: '@pbWidth',
height: '@pbHeight'
},
controller: 'pbOrganizationImagePickerController',
link: function (scope, element, attrs) {
scope.$watch('defaultSrc', function (value) {
if (value !== undefined) {
scope.imageSource = value;
}
});
element.on('click', function () {
scope.pickImage().then(function (image) {
scope.imageSource = image.storageUrl;
scope.fileId = image.fileId;
}, function () {
console.log('Modal dismissed at: ' + new Date());
});
});
}
};
}]);
试验:
describe('pbOrganizationImagePicker', function () {
beforeEach(module('pb.webSites.controllers'));
beforeEach(module('pb.webSites.directives'));
beforeEach(module('ui.router'));
beforeEach(module('ui.bootstrap'));
var compile;
var scope;
var mockModal = {};
var image;
beforeEach(inject(function ($compile, $rootScope) {
compile = $compile
scope = $rootScope.$new();
}));
beforeEach(inject(function ($q, $injector) {
$httpBackend = $injector.get('$httpBackend');
$httpBackend.whenGET('/app/webSites/directives/OrganizationImagePicker.html').respond(200, '');
scopeObject = {
profileImageUrl: 'http://www.gravatar.com/avatar/12345?s=40&d=identicon',
profileImageId: 54634
};
scope.webSite = {
profileImageId: 6436
};
scope.pickImage = function () {
var defer = $q.defer();
defer.resolve(scopeObject);
return defer.promise;
};
}));
describe('element.click()', function () {
beforeEach(function () {
var html = angular.element('<pb-organization-image-picker data-pb-default-src="{{ webSite.profileImageUrl || \'/content/img/placeholder-lg.jpg\' }}" data-pb-file-id="webSite.profileImageId" data-pb-width="200"></pb-organization-image-picker>');
element = compile(html)(scope);
element.triggerHandler('click');
});
it('should assign value to scope variables', function () {
scope.pickImage();
scope.$digest();
expect(scope.imageSource).toEqual(scopeObject.profileImageUrl);
expect(scope.fileId).toEqual(scopeObject.profileImageId);
});
});
});
我也尝试将测试更改为以下内容,因为我在上面的测试中非常确定我正在尝试测试。但是在这里我得到的pickImage()从未被调用过。即使您没有看到问题,您认为哪种方法更适合测试?
describe('element.click()', function () {
it('should assign value to scope variables', function () {
element = compile(html)(scope);
spyOn(scope, 'pickImage');
element.triggerHandler('click');
scope.$apply();
//scope.pickImage();
expect(scope.pickImage).toHaveBeenCalled();
scope.$digest();
expect(scope.imageSource).toEqual(scopeObject.profileImageUrl);
expect(scope.fileId).toEqual(scopeObject.profileImageId);
});
});
答案 0 :(得分:0)
element.on('click', function () {
scope.$apply(function() {
scope.pickImage().then(function (image) {
scope.imageSource = image.storageUrl;
scope.fileId = image.fileId;
}, function () {
console.log('Modal dismissed at: ' + new Date());
});
});
});
将您的点击处理程序中的代码包装在$ apply。
中我怀疑真正的问题是你的指令使用了一个隔离范围,所以它实际上没有“pickImage()”方法,当你分配imageSource和fileId时,你将它们放在指令范围内,而不是您的测试尝试验证的范围(父范围)。
您的测试将pickImage()和webSite分配给测试元素的范围。由于您使用隔离范围,因此您的指令将无法访问这些方法和属性。您应该将它们移动到服务中并将它们注入到指令中。
这不是“正确”,但为了测试理论,您可以将指令更改为:
element.on('click', function () {
scope.$apply(function(){
scope.$parent.pickImage().then(function (image) {
scope.$parent.imageSource = image.storageUrl;
scope.$parent.fileId = image.fileId;
}, function () {
console.log('Modal dismissed at: ' + new Date());
});
});
});
这不是你想要的生产代码,但我只想说明不同的范围是如何相互关联的。