最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Test file upload in react jest - Stack Overflow

programmeradmin3浏览0评论

I have code like (kept only relevant code)

function App() {
  const [values, setValues] = useState([]);

  async function onUpload(event) {
    if (event?.target.files?.length) {
      const data = await event.target.files[0].text();
      const json = JSON.parse(data);
      setValues(json);
    } else {
      throw new Error('couldnt get files');
    }
  }

  return (
    <div>
      {Boolean(!values.length) && (
        <input data-testid="upInput" accept="application/JSON" type="file" onChange={onUpload} />
      )}
      {Boolean(values.length) && (
        <div data-testid="handler">
          <ValuesHandler values={values} />
        </div>
      )}
    </div>
  );
}

Now I want to test that values are set correctly when the user uploads a file, and that ValuesHandler is then present in the page.

I am trying in this direction in my App.test.tsx

import user from '@testing-library/user-event';
import someValues from '../somefile.json';
import { render } from '@testing-library/react';

test('should pass', () => {
    const { getByTestId, queryByTestId } = render(<App />);
    const str = JSON.stringify(someValues);
    const blob = new Blob([str]);
    const file = new File([blob], 'values.json', {
        type: 'application/JSON',
    });
    const input = getByTestId('upInput');

    user.upload(input, file);

    const handler = queryByTestId('handler');

    expect(handler).toBeTruthy();
});

This fails with handler being null.

The main suspect is that this line is not working in jest. Or I am not handling it properly.

    const data = await event.target.files[0].text();

I am thinking about mocking the Blob.text method to return the content of the file directly.. Not sure how though.

I have code like (kept only relevant code)

function App() {
  const [values, setValues] = useState([]);

  async function onUpload(event) {
    if (event?.target.files?.length) {
      const data = await event.target.files[0].text();
      const json = JSON.parse(data);
      setValues(json);
    } else {
      throw new Error('couldnt get files');
    }
  }

  return (
    <div>
      {Boolean(!values.length) && (
        <input data-testid="upInput" accept="application/JSON" type="file" onChange={onUpload} />
      )}
      {Boolean(values.length) && (
        <div data-testid="handler">
          <ValuesHandler values={values} />
        </div>
      )}
    </div>
  );
}

Now I want to test that values are set correctly when the user uploads a file, and that ValuesHandler is then present in the page.

I am trying in this direction in my App.test.tsx

import user from '@testing-library/user-event';
import someValues from '../somefile.json';
import { render } from '@testing-library/react';

test('should pass', () => {
    const { getByTestId, queryByTestId } = render(<App />);
    const str = JSON.stringify(someValues);
    const blob = new Blob([str]);
    const file = new File([blob], 'values.json', {
        type: 'application/JSON',
    });
    const input = getByTestId('upInput');

    user.upload(input, file);

    const handler = queryByTestId('handler');

    expect(handler).toBeTruthy();
});

This fails with handler being null.

The main suspect is that this line is not working in jest. Or I am not handling it properly.

    const data = await event.target.files[0].text();

I am thinking about mocking the Blob.text method to return the content of the file directly.. Not sure how though.

Share Improve this question edited Jul 21, 2021 at 2:45 Lin Du 102k134 gold badges332 silver badges560 bronze badges asked Jul 20, 2021 at 9:23 AngularDebutantAngularDebutant 1,5766 gold badges26 silver badges48 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 16

You need to mock .text() method of File. Just add the mocked .text() method to the File.prototype.

E.g.

App.tsx:

import React, { useState } from 'react';

export function App() {
  const [values, setValues] = useState([]);

  async function onUpload(event) {
    if (event?.target.files?.length) {
      const data = await event.target.files[0].text();
      const json = JSON.parse(data);
      setValues(json);
    } else {
      throw new Error('couldnt get files');
    }
  }

  return (
    <div>
      {Boolean(!values.length) && (
        <input data-testid="upInput" accept="application/JSON" type="file" onChange={onUpload} />
      )}
      {Boolean(values.length) && <div data-testid="handler">ValuesHandler</div>}
    </div>
  );
}

App.test.tsx:

import React from 'react';
import user from '@testing-library/user-event';
import { render, waitFor } from '@testing-library/react';
import { App } from './App';

const someValues = [{ name: 'teresa teng' }];

describe('68452480', () => {
  test('should pass', async () => {
    const { getByTestId, queryByTestId } = render(<App />);
    const str = JSON.stringify(someValues);
    const blob = new Blob([str]);
    const file = new File([blob], 'values.json', {
      type: 'application/JSON',
    });
    File.prototype.text = jest.fn().mockResolvedValueOnce(str);
    const input = getByTestId('upInput');
    user.upload(input, file);
    await waitFor(() => expect(queryByTestId('handler')).toBeTruthy());
  });
});

test result:

 PASS  examples/68452480/App.test.tsx (9.968 s)
  68452480
    ✓ should pass (53 ms)

----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------|---------|----------|---------|---------|-------------------
All files |   88.89 |    78.57 |     100 |   88.89 |                   
 App.tsx  |   88.89 |    78.57 |     100 |   88.89 | 12                
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        10.694 s
发布评论

评论列表(0)

  1. 暂无评论