Mocking file input in React TestUtils

Asked
Active3 hr before
Viewed126 times

10 Answers

mockingtestutilsreactinput
90%

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.,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.,Connect and share knowledge within a single location that is structured and easy to search.

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]
   }
});
load more v
88%

MyComponent.js:

import React from 'react';
class MyComponent extends React.Component {
    constructor(props) {
        super(props);
        this.state = {fileContents: ''};
        this.changeHandler = this.changeHandler.bind(this);
    }
    changeHandler(evt) {
        const reader = new FileReader();
        reader.addEventListener('load', () => {
            this.setState({fileContents: reader.result});
        });
        reader.readAsText(evt.target.files[0]);
    }
    render() {
        return <input type="file" onChange={this.changeHandler}/>;
    }
}
export default MyComponent;
load more v
72%

ReactTestUtils makes it easy to test React components in the testing framework of your choice. At Facebook we use Jest for painless JavaScript testing. Learn how to get started with Jest through the Jest website’s React Tutorial.,We recommend using React Testing Library which is designed to enable and encourage writing tests that use your components as the end users do.,For React versions <= 16, the Enzyme library makes it easy to assert, manipulate, and traverse your React Components’ output.

import ReactTestUtils from 'react-dom/test-utils'; // ES6
var ReactTestUtils = require('react-dom/test-utils'); // ES5 with npm
load more v
65%

Now you can use upload function from @testing-library/user-event,Is there a way to simulate or fire event to trigger change event on input that is used for uploading files?,I think this is actually an issue for dom-testing-library but I'll dig more into it in the mean time, before asking you to open the issue there.

import React from 'react'
import {renderIntoDocument, fireEvent} from 'react-testing-library'

test('some test', () => {
  const {getByLabelText} = renderIntoDocument(
    <div>
      <label htmlFor="avatar">Avatar</label>
      <input id="avatar" type="file" />
    </div>
  )
  const fileInputField = getByLabelText('Avatar')
  const event = {
    target: {
      value: '/not/sure/what/goes/in/here',
    },
  }
  fireEvent.change(fileInputField, event)
  // expect here things that should have happened when the file input changed
})
load more v
75%

I have a component with a following render f-tion:,If you add any files,it will delete all existing files related to this question-(questions only answer remains unchanged)

I have a component with a following render f-tion:

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

Vue Test Utils is a great package for Vue testing, and it provides many helper methods for mocking the functionality of different HTML form elements, but an input of type file is unfortunately not included. In this post, we’ll discuss how to combine Vue Test Utils helpers with Jest helpers to mock and test file upload in Vue (and hopefully spare you hours of frustration).,We’ll be focusing on image upload in this example, but the general principles should be applicable to other file types. First, we have a form element with an input of type file:,First, we need to create an event object that mimics the structure of an actual image upload event. Next, we need to mount the component using the mount method provided by Vue Test Utils.

<form method="POST" enctype="multipart/form-data">
   <input @change="onChange" type="file" accept="image/*">
</form>
load more v
22%

You could do this using the DataTransfer object. Unfortunately, it hasn't been added to JSDOM, so you can't test in Jest. There's an open issue to add the object—https://github.com/jsdom/jsdom/issues/1568,If you ran your tests in a browser using Karma, you could test like this:,If you're just wanting to simulate a value in input.element.files and changes to input.element.value in Jest, but not necessarily accurately simulating every DOM behavior, you can do it by defining a getter/setter for those fields. This works for me:

If you ran your tests in a browser using Karma, you could test like this:

const wrapper = shallow(FormComponent)
const input = wrapper.find('input[type="file"]')
const dT = new ClipboardEvent('').clipboardData || new DataTransfer()
dT.items.add(new File(['foo'], 'programmatically_created.txt'))
input.element.files = dT.files
input.trigger('change')
load more v
60%

There's a caveat around snapshot testing when using Enzyme and React 16+. If you mock out a module using the following style:,Let's rewrite the test from above using Enzyme instead of react-testing-library. We use Enzyme's shallow renderer in this example.,SetupSetup with Create React AppSetup without Create React AppSnapshot TestingDOM TestingCustom transformers

Setup with Create React App#

/n

If you are new to React, we recommend using Create React App. It is ready to use and ships with Jest! You will only need to add react-test-renderer for rendering snapshots.

react - test - renderer
load more v
48%

We put two lines of JavaScript in a ./tests.webpack.js file to help Karma and Webpack play together:,The React TestUtils let us render a React component by putting its DOM in a variable, instead of inserting it into a page. For example, to render a React component, we’d do something like this:,The cool part is that TestUtils lets us trigger user events as well. For a click event, we’d write something like this:

The React TestUtils let us render a React component by putting its DOM in a variable, instead of inserting it into a page. For example, to render a React component, we’d do something like this:

var component = TestUtils.renderIntoDocument(
<MyComponent />
);
load more v
23%

In this article we created a simple file upload component, then refactored it to make it easier to test and finally added extensive tests for our component and helper function. We also created a mock of FileReader that we can also use in other tests.,Let’s begin with a simple file upload component: a label, an input field and a preview if a file has been selected and stored in the components state.,Just to make this clear, this is a simplified version of a file upload component. In a real application we would add error handling and the code would do something with the selected file (for example, upload it to a server).

// FileUploadField.tsx

function FileUploadField(): ReactElement {
  const [preview, setPreviewImage] = useState<string | undefined>();
  const previewStyle = { width: '200px' };

  const handleChange = useCallback(({ target }) => {
    const reader = new FileReader();
    reader.addEventListener('load', (evt) => {
      if (reader.result) {
        setPreviewImage(reader.result as string);
      }
    });
    reader.readAsDataURL(target.files[0]);
  }, []);

  return (
    <div>
      <label htmlFor="fileUpload">Upload file:</label>
      <input type="file" id="fileUpload" onChange={handleChange} />
      {preview && (
        <div>
          <img src={preview} alt="Preview" style={previewStyle} />
        </div>
      )}
    </div>
  );
}
load more v

Other "mocking-testutils" queries related to "Mocking file input in React TestUtils"