upload static method Null safety

void upload(
  1. Element element,
  2. List<File> files,
  3. {Map clickInit = const {},
  4. Map changeInit = const {},
  5. bool applyAccept = false}
)

Uploads files to element.

element must be a FileUploadInputElement or a LabelElement for a FileUploadInputElement. When uploading multiple files, make sure that element's multiple attribute is set to true.

See: testing-library.com/docs/ecosystem-user-event/#uploadelement-file--clickinit-changeinit-

Options

clickInit and changeInit

Use clickInit and changeInit to initialize the click and change events that occur as a part of the upload.

applyAccept

By default, the accept attribute on element will be ignored when uploading files. Set applyAccept to true to allow accept to filter files.

Example

<div>
  <label for="single-input">Single Input:</label>
  <input id="single-input" type="file" accept=".png,.jpeg" />
</div>
<div>
  <label for="multi-input">Multi-Input:</label>
  <input id="multi-input" type="file" accept=".png,.jpeg" multiple />
</div>
import 'dart:html';

import 'package:react/react.dart' as react;
import 'package:react_testing_library/react_testing_library.dart' as rtl;
import 'package:react_testing_library/user_event.dart';
import 'package:test/test.dart';

void main() {
  test('Single file input', () {
    final file = File([], 'file1.mp3');

    // Render the DOM shown in the example snippet above.
    final view = rtl.render(react.div({}, [
      react.label({
        'htmlFor': 'single-input',
      }, 'Single Input:'),
      react.input({
        'id': 'single-input',
        'type': 'file',
        'accept': '.png,.jpeg',
      }),
    ]));

    // Use react_testing_library queries to store references to the nodes.
    final input = view.getByLabelText('Single Input:') as FileUploadInputElement;

    // Use `UserEvent.upload` to simulate a user uploading a file in the input.
    UserEvent.upload(input, [file]);

    // Verify the value of the input.
    expect(input.files.single.name, 'file1.mp3');
  });

  test('Multiple file input', () {
    final files = [
      File([], 'file1.mp3'),
      File([], 'file2.jpeg'),
      File([], 'file3.png'),
    ];

    // Render the DOM shown in the example snippet above.
    final view = rtl.render(react.div({}, [
      react.label({
        'htmlFor': 'multi-input',
      }, 'Multi-Input:'),
      react.input({
        'data-test-id': 'multi-input',
        'type': 'file',
        'multiple': true,
        'accept': '.png,.jpeg',
      }),
    ]));

    // Use react_testing_library queries to store references to the node.
    final input = view.getByLabelText('Multi-Input:') as FileUploadInputElement;

    // Use `UserEvent.upload` to simulate a user uploading a file in the input.
    UserEvent.upload(input, files, applyAccept: true);

    // Verify the value of the input.
    expect(input.files, hasLength(2));
    expect(input.files.first.name, 'file2.jpeg');
    expect(input.files[1].name, 'file3.png');
  });
}

Warning About Errors

Unlike the JS API, any uncaught errors thrown during event propagation will get rethrown. This helps surface errors that could otherwise go unnoticed since they aren't printed to the terminal when running tests.

NOTE: render() supports React vDom elements / custom components created using either the react or over_react packages.

The examples shown here use the react package since the react_testing_library does not have a direct dependency on over_react - but both libraries are fully supported.

{@category UserActions}

Implementation

static void upload(
  /*InputElement | LabelElement*/ Element element,
  List<File> files, {
  Map clickInit = const {},
  Map changeInit = const {},
  bool applyAccept = false,
}) {
  final init = {
    'clickInit': _jsifyEventData(clickInit),
    'changeInit': _jsifyEventData(changeInit),
  };
  final options = {'applyAccept': applyAccept};
  eventHandlerErrorCatcher(() {
    getProperty(_userEvent, 'upload')(
      element,
      files,
      _jsifyEventData(init),
      jsifyAndAllowInterop(options),
    );
  });

  // Convert the `element.files` because the JS `upload` sets it equal to a
  // map with with an `item` method to access files.
  final control = element is LabelElement ? element.control : null;
  if (control is InputElement) {
    control.files = _unjsifyFileList(control.files ?? []);
  } else if (element is FileUploadInputElement) {
    element.files = _unjsifyFileList(element.files ?? []);
  }
}