在 React TestUtils 中模拟文件输入 [英] Mocking file input in React TestUtils
问题描述
我有一个具有以下渲染功能的组件:-
I have a component with the following render function:-
render: function() {
<input
type="file"
name: this.props.name,
className={this.props.className}
onChange={this.props.handleChange}
accept={this.props.accept}/>
}
状态由容器管理,该容器使用 jquery AJAX 调用上传文件服务器端:
State is managed by a container which uploads the file server-side using jquery AJAX call:
getInitialState: function() {
return {
uploaded: false
};
}
handleChange: function(event) {
event.preventDefault();
var file = event.target.files[0];
if (!file) {
return;
}
var reader = new FileReader();
reader.readAsText(file, 'UTF-8');
var self = this;
reader.onload = function(e) {
var content = e.target.result;
var a = $.ajax({
type: 'PUT',
url: 'http://localhost:8080/upload',
contentType: 'application/json',
dataType: "json",
data: JSON.stringify({
"input": content
})
})
.fail(function(jqXHR, textStatus, errorThrown) {
console.log("ERROR WHEN UPLOADING");
});
$.when(a).done(function() {
self.setState({
uploaded: true,
});
});
}
}
这在服务器运行时完美无缺.但是,我想在不需要调用服务器的情况下进行测试.这是我目前编写的 Mocha 测试:
This works flawlessly with the server running. However, I'd like to test without the need to invoke the server. Here's the Mocha test I have written so far:
var React = require('react');
var assert = require('chai').assert;
var TestUtils = require('react-addons-test-utils');
var nock = require("nock");
var MyContainer = require('../containers/MyContainer');
describe('assert upload', function () {
it("user action", function () {
var api = nock("http://localhost:8080")
.put("/upload", {input: "input"})
.reply(200, {
});
var renderedComponent = TestUtils.renderIntoDocument(
<MyContainer />
);
var fileInput = TestUtils.findAllInRenderedTree(renderedComponent,
function(comp) {
return(comp.type == "file");
});
var fs = require('fs') ;
var filename = "upload_test.txt";
var fakeF = fs.readFile(filename, 'utf8', function(err, data) {
if (err) throw err;
});
TestUtils.Simulate.change(fileInput, { target: { value: fakeF } });
assert(renderedComponent.state.uploaded === true);
});
});
出现此错误:-
TypeError: Cannot read property '__reactInternalInstance$sn5kvzyx2f39pb9' of undefined
推荐答案
您需要真实"文件吗?我认为您的问题在于您如何管理假"文件以及文件输入的更改事件.您可以使用 File Api 来创建"一个虚拟文件,然后您只需正确设置文件输入.它不使用 value
,而是使用 files
.
Do you need a 'true' file? I think your issue is in how you're managing your 'fake' file, and your file input's change event. You can use the File Api to 'create' a dummy file, and then you just have to properly set your file input. It doesn't use value
, but rather files
.
// similar example from KCD https://github.com/testing-library/react-testing-library/issues/93#issuecomment-392126991
const file = new File(['(⌐□_□)'], 'chucknorris.png', { type: 'image/png' });
TestUtils.Simulate.change(fileInput, { target: { files: [ file ] } });
如果您确实需要文件"(upload_text.txt),那可能会更棘手.节点 fs.readFile
是异步的,并且数据在 callback
之外不可用,而且您必须将 data
转换为提供给输入的实际文件对象.
If you actually needed the 'file' (upload_text.txt), then that could be more tricky. Node fs.readFile
is async, and the data isn't available outside of the callback
, plus you'd have to convert the data
into an actual file object to give to the input.
// rough pass at this, you'll have to play with it
import fs from 'fs';
const filename = 'upload_text.txt';
fs.readFile(filename, 'utf8', (err, data) => {
if (err) throw err;
const file = new File(data, filename, { type: 'text/plain' });
TestUtils.Simulate.change(fileInput, { target: { files: [ file ] } });
// whatever comes next
});
这篇关于在 React TestUtils 中模拟文件输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!