upload.js 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.upload = upload;
  6. var _dom = require("@testing-library/dom");
  7. var _click = require("./click");
  8. var _blur = require("./blur");
  9. var _focus = require("./focus");
  10. var _utils = require("./utils");
  11. function upload(element, fileOrFiles, init, {
  12. applyAccept = false
  13. } = {}) {
  14. var _input$files;
  15. const input = (0, _utils.isElementType)(element, 'label') ? element.control : element;
  16. if (!input || !(0, _utils.isElementType)(input, 'input', {
  17. type: 'file'
  18. })) {
  19. throw new TypeError(`The ${input === element ? 'given' : 'associated'} ${input == null ? void 0 : input.tagName} element does not accept file uploads`);
  20. }
  21. if ((0, _utils.isDisabled)(element)) return;
  22. (0, _click.click)(element, init == null ? void 0 : init.clickInit);
  23. const files = (Array.isArray(fileOrFiles) ? fileOrFiles : [fileOrFiles]).filter(file => !applyAccept || isAcceptableFile(file, input.accept)).slice(0, input.multiple ? undefined : 1); // blur fires when the file selector pops up
  24. (0, _blur.blur)(element); // focus fires when they make their selection
  25. (0, _focus.focus)(element); // do not fire an input event if the file selection does not change
  26. if (files.length === ((_input$files = input.files) == null ? void 0 : _input$files.length) && files.every((f, i) => {
  27. var _input$files2;
  28. return f === ((_input$files2 = input.files) == null ? void 0 : _input$files2.item(i));
  29. })) {
  30. return;
  31. } // the event fired in the browser isn't actually an "input" or "change" event
  32. // but a new Event with a type set to "input" and "change"
  33. // Kinda odd...
  34. const inputFiles = { ...files,
  35. length: files.length,
  36. item: index => files[index],
  37. [Symbol.iterator]() {
  38. let i = 0;
  39. return {
  40. next: () => ({
  41. done: i >= files.length,
  42. value: files[i++]
  43. })
  44. };
  45. }
  46. };
  47. (0, _dom.fireEvent)(input, (0, _dom.createEvent)('input', input, {
  48. target: {
  49. files: inputFiles
  50. },
  51. bubbles: true,
  52. cancelable: false,
  53. composed: true
  54. }));
  55. _dom.fireEvent.change(input, {
  56. target: {
  57. files: inputFiles
  58. },
  59. ...(init == null ? void 0 : init.changeInit)
  60. });
  61. }
  62. function isAcceptableFile(file, accept) {
  63. if (!accept) {
  64. return true;
  65. }
  66. const wildcards = ['audio/*', 'image/*', 'video/*'];
  67. return accept.split(',').some(acceptToken => {
  68. if (acceptToken.startsWith('.')) {
  69. // tokens starting with a dot represent a file extension
  70. return file.name.endsWith(acceptToken);
  71. } else if (wildcards.includes(acceptToken)) {
  72. return file.type.startsWith(acceptToken.substr(0, acceptToken.length - 1));
  73. }
  74. return file.type === acceptToken;
  75. });
  76. }