在 React TestUtils 中模拟文件输入 [英] Mocking file input in React TestUtils

查看:33
本文介绍了在 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆