使用 Jasmine 和 Angular 测试 FileReader
Testing FileReader with Jasmine and Angular
我有一个基于此处示例的非常简单的指令:
https://veamospues.wordpress.com/2014/01/27/reading-files-with-angularjs/
但我正在努力使用 Jasmine 正确测试指令,因为我似乎无法按预期触发事件。
我的指令:
var fileReaderModule = angular.module('fileReaderModule', []);
fileReaderModule.controller('fileReaderCtrl', [ '$scope', function($scope) {
$scope.setContent = function($fileContent) {
$scope.content = $fileContent;
console.log($fileContent);
};
$scope.getContent = function() {
console.info("content:", $scope.content);
return $scope.content;
};
} ]);
fileReaderModule.directive('onReadFile', function($parse) {
return {
restrict : 'A',
scope : false,
link : function(scope, element, attrs) {
var fn = $parse(attrs.onReadFile);
element.on('change', function(onChangeEvent) {
var reader = new FileReader();
reader.addEventListener("load", function(onLoadEvent) {
scope.$apply(function() {
fn(scope, {
$fileContent : onLoadEvent.target.result
});
});
}, false);
reader.readAsText((onChangeEvent.srcElement || onChangeEvent.target).files[0]);
});
}
};
});
我的测试规格:
describe("Test suite for the fileReaderModule angular module", function() {
var scope, rootScope, compile, fileReaderController, element, eventListener, windowMock;
beforeEach(function() {
module('fileReaderModule');
inject(function($rootScope, $compile, $controller, $window) {
rootScope = $rootScope;
scope = $rootScope.$new();
compile = $compile;
windowMock = $window;
$fileReaderController = $controller('fileReaderCtrl', {
'$scope' : scope
});
});
});
describe("Tests focused on the fileReaderCtrl controller", function() {
it("should set the file contents correctly", function() {
scope.setContent('1');
expect(scope.content).toEqual('1');
})
it("should get the file contents correctly", function() {
scope.content = 'test';
expect(scope.getContent()).toEqual('test');
})
it("should set and then get the file contents correctly", function() {
scope.setContent('test');
expect(scope.getContent()).toEqual('test');
})
});
describe("Tests focused on the onReadFile directive", function() {
beforeEach(function() {
eventListener = jasmine.createSpy();
spyOn(windowMock, "FileReader").andReturn({
addEventListener: eventListener,
readAsText : function(file) {
// do nothing.
}
});
});
it("should set the file contents correctly", function() {
var elm = compile('<div on-read-file="name"></div>')(scope);
scope.$digest();
scope.$broadcast('change', ['file.txt']);
scope.$broadcast('load', ['file.txt']);
expect(windowMock.FileReader).toHaveBeenCalled();
})
});
});
有关完整示例,请查看此 jsfiddle:
您正在调用 scope.$broadcast('change')
,但此 angular 事件没有侦听器。相反,您可以在新元素上调度自定义事件:
var elm = compile('<div on-read-file="name"></div>')(scope);
var div = elm[0];
div.files = ['file.txt'];
div.dispatchEvent(new CustomEvent('change'));
expect(windowMock.FileReader).toHaveBeenCalled();
检查this fiddle。
如果您想测试读取文件作为文本,您可以在模拟的 readAsText
函数中调用 onload 函数:
spyOn(window, 'FileReader').and.returnValue({
readAsText: function(file) {
this.onload({
target: {
result: 'text content'
}
});
}
});
我有一个基于此处示例的非常简单的指令:
https://veamospues.wordpress.com/2014/01/27/reading-files-with-angularjs/
但我正在努力使用 Jasmine 正确测试指令,因为我似乎无法按预期触发事件。
我的指令:
var fileReaderModule = angular.module('fileReaderModule', []);
fileReaderModule.controller('fileReaderCtrl', [ '$scope', function($scope) {
$scope.setContent = function($fileContent) {
$scope.content = $fileContent;
console.log($fileContent);
};
$scope.getContent = function() {
console.info("content:", $scope.content);
return $scope.content;
};
} ]);
fileReaderModule.directive('onReadFile', function($parse) {
return {
restrict : 'A',
scope : false,
link : function(scope, element, attrs) {
var fn = $parse(attrs.onReadFile);
element.on('change', function(onChangeEvent) {
var reader = new FileReader();
reader.addEventListener("load", function(onLoadEvent) {
scope.$apply(function() {
fn(scope, {
$fileContent : onLoadEvent.target.result
});
});
}, false);
reader.readAsText((onChangeEvent.srcElement || onChangeEvent.target).files[0]);
});
}
};
});
我的测试规格:
describe("Test suite for the fileReaderModule angular module", function() {
var scope, rootScope, compile, fileReaderController, element, eventListener, windowMock;
beforeEach(function() {
module('fileReaderModule');
inject(function($rootScope, $compile, $controller, $window) {
rootScope = $rootScope;
scope = $rootScope.$new();
compile = $compile;
windowMock = $window;
$fileReaderController = $controller('fileReaderCtrl', {
'$scope' : scope
});
});
});
describe("Tests focused on the fileReaderCtrl controller", function() {
it("should set the file contents correctly", function() {
scope.setContent('1');
expect(scope.content).toEqual('1');
})
it("should get the file contents correctly", function() {
scope.content = 'test';
expect(scope.getContent()).toEqual('test');
})
it("should set and then get the file contents correctly", function() {
scope.setContent('test');
expect(scope.getContent()).toEqual('test');
})
});
describe("Tests focused on the onReadFile directive", function() {
beforeEach(function() {
eventListener = jasmine.createSpy();
spyOn(windowMock, "FileReader").andReturn({
addEventListener: eventListener,
readAsText : function(file) {
// do nothing.
}
});
});
it("should set the file contents correctly", function() {
var elm = compile('<div on-read-file="name"></div>')(scope);
scope.$digest();
scope.$broadcast('change', ['file.txt']);
scope.$broadcast('load', ['file.txt']);
expect(windowMock.FileReader).toHaveBeenCalled();
})
});
});
有关完整示例,请查看此 jsfiddle:
您正在调用 scope.$broadcast('change')
,但此 angular 事件没有侦听器。相反,您可以在新元素上调度自定义事件:
var elm = compile('<div on-read-file="name"></div>')(scope);
var div = elm[0];
div.files = ['file.txt'];
div.dispatchEvent(new CustomEvent('change'));
expect(windowMock.FileReader).toHaveBeenCalled();
检查this fiddle。
如果您想测试读取文件作为文本,您可以在模拟的 readAsText
函数中调用 onload 函数:
spyOn(window, 'FileReader').and.returnValue({
readAsText: function(file) {
this.onload({
target: {
result: 'text content'
}
});
}
});