单元测试的模拟文件输入
Mock file input for unit test
我得到了如下代码行:
jQuery('.js-img-input').on('change', handleNewFiles);
var handleNewFiles = function(event) {
var fileList = event.target.files;
loadFileList(fileList);
};
var loadFileList = function(fileList) {
jQuery(fileList).each(function(key, file) {
readFileAsync(file);
});
}
var readFileAsync = function(file) {
var fileReader = new FileReader();
fileReader.addEventListener("load", function(event) {
file.result = event.target.result;
saveFile(file);
});
fileReader.readAsDataURL(file);
};
所有方法在jQuery函数中都是私有的,我不想仅仅为了测试目的而将"handleNewFiles"公开
我很想用这样的东西来测试这些线路:
it('should create a fileReader', function(){
spyOn(window, 'FileReader').and.returnValue({
addEventListener: function(){},
readAsDataURL: function(){}
});
jQuery('.js-img-input').trigger('change');
expect(window.FileReader).toHaveBeenCalled();
});
但是我是如何将一些伪数据放入event.target.files的?
好吧,我找到了一个解决方案。您不能用文件创建伪造的本机事件,出于安全原因,这是一件好事。但在我的情况下,解决方案看起来是这样的:
it('should create a fileReader', function(){
var onChangeCallback;
spyOn(jQuery.fn, 'on').and.callFake(function(eventName, callback){
if(eventName === 'change'){
onChangeCallback = callback;
}
});
spyOn(window, 'FileReader').and.returnValue({
addEventListener: function(){},
readAsDataURL: function(){}
});
onChangeCallback({target:{files:[1,2,3]}});
expect(window.FileReader).toHaveBeenCalled();
});
虽然不能为fileInput.files
赋值,但可以将属性替换为自己的属性,从而实现相同的功能:
it('should create a fileReader', () => {
const fileInput = $('input[type=file]');
const fileInputElement = fileInput.get(0);
Object.defineProperty(fileInputElement, 'files', {
value: [{name: 'file.txt'}],
writable: false,
});
fileInput.trigger('input').trigger('change');
// expect outputs...
});
这比创建自己的事件对象要好一点,因为它更接近真实环境。
本文可能有助于
http://nerds.intuo.io/2016/05/12/mocking-file-uploads-in-javascript.html
function fillInFileInput(selector, file) {
// Get the input
let input = jQuery(selector);
// Get out file options
let { name, type, content } = file;
// Create a custom event for change and inject target
let event = jQuery.Event('change', {
target: {
files: [{
name: name, type: type
}]
}
});
// Stub readAsDataURL function
let stub = sinon.stub(FileReader.prototype, 'readAsDataURL', function() {
this.onload({ target: { result: content }});
});
// Trigger event
input.trigger(event);
// We don't want FileReader to be stubbed for all eternity
stub.restore();
}
我发布了一个基于Jakob答案的稍微修改过的解决方案。我需要一些轻微的修改才能让它为我工作。这对我使用"angular":"1.0.6","jasmine node":"1.3.1","jquery":"1.10.0"有效
var onChangeCallback;
spyOn(jQuery.fn, 'on').andCallFake(function(eventName, selector, callback){
if(eventName === 'change'){
onChangeCallback = callback;
}
});
spyOn(window, 'FileReader').andReturn({
addEventListener: function(){},
readAsDataURL: function(){}
});
onChangeCallback({currentTarget: {files:[{size: 4000}], value: 'asd'}});
相关文章:
- 我想在选择输入文件上显示图像
- 触发IE9中的输入文件点击
- 将图像数据设置为输入文件标记
- Asp-mvc剃刀将输入文件的值存储在文本框中
- 选择同一文件时未触发HTML输入文件选择事件
- 从Javascript中的输入文件中获取文件名
- 输入文件和自动提交 - 播放框架 2.
- 将 FormData 对象放入数组中以从不同的输入文件上载文件
- 警报输入“文件”文件名,使用 jQuery 和“split”
- 检查是否对任何输入文件进行了更改
- 仅获取所选输入文件的名称
- 如何在Joomla模块中通过JavaScript发送输入文件类型
- Javascript将输入文件传递给PHP
- 触发AngularJS中的输入文件点击事件
- 输入文件:如何在刷新后显示文件名
- Angular 2-模型驱动的表单,带有输入文件(文件上传)
- 如何制作一个输入文件以供使用
- 将html输入文件元素从一个表单复制到另一个表单
- 如何在jquery中清除输入文件字段
- 在3个输入文件中加载img