【问题标题】:Mocking file input in React TestUtils在 React TestUtils 中模拟文件输入
【发布时间】:2016-08-13 15:23:41
【问题描述】:

我有一个具有以下渲染功能的组件:-

  render: function() {
   <input
    type="file"
    name: this.props.name,
    className={this.props.className}
    onChange={this.props.handleChange}
    accept={this.props.accept}/>
 }

状态由一个容器管理,该容器使用 jquery AJAX 调用上传文件服务器端:

 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 测试:

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

【问题讨论】:

  • 我只需执行const node = document.getElementsByClassName("close"); TestUtils.Simulate.click(node); 就可以重现相同的错误,其中我有一个带有class="close" 的按钮,它是该类的唯一元素/对象,并且这两行在里面我正在使用的另一个按钮事件处理程序。一直在寻找解决方案。使用 Chrome 版本。 51.0.2704.103,反应版本 15.3.1。
  • 我通过const node = document.getElementById("btnRequest") 解决了我的问题,这是一个打开(或关闭)模态窗口的按钮,而不是试图在模态窗口本身的关闭按钮之后进行。除了var fileInput = TestUtils.findAllInRenderedTree...,你能做一些类似的事情,一次做一个吗?

标签: unit-testing reactjs mocha.js fs reactjs-testutils


【解决方案1】:

您需要“真实”文件吗?我认为您的问题在于您如何管理“假”文件以及文件输入的更改事件。您可以使用 File Api 来“创建”一个虚拟文件,然后您只需正确设置文件输入。它不使用value,而是使用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 转换为实际的文件对象以提供给输入。

// 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
});

【讨论】:

    猜你喜欢
    • 2014-09-03
    • 1970-01-01
    • 2015-09-12
    • 2015-11-09
    • 2016-05-10
    • 2015-07-12
    • 1970-01-01
    • 2019-08-08
    • 2023-01-30
    相关资源
    最近更新 更多