Jsdom: рдХреБрдЫ рд╡рд┐рдзрд┐ рдХрд╛ рдкрд░реНрджрд╛рдлрд╛рд╢ рдХрд░реЗрдВ рдлрд╝рд╛рдЗрд▓ рд╕реВрдЪреА рдореЗрдВ рдлрд╝рд╛рдЗрд▓реЗрдВ рдЬреЛрдбрд╝реЗрдВ

рдХреЛ рдирд┐рд░реНрдорд┐рдд 23 рдЕрдХреНрддреВре░ 2015  ┬╖  30рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: jsdom/jsdom

рдлрд╝рд╛рдЗрд▓ рд▓рд┐рд╕реНрдЯ рд╕реНрдкреЗрдХреНрд╕ рдореЗрдВ рд▓рд┐рдЦрдиреЗ рдпреЛрдЧреНрдп рдирд╣реАрдВ рд╣реИрдВ, рд▓реЗрдХрд┐рди input.files рдкрд░реАрдХреНрд╖рдг рдпреЛрдЧреНрдп рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдЗрд╕реЗ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЙрдкрдпреЛрдЧ рд╡рд┐рдзрд┐ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреАред

/рд╕реАрд╕реА @cpojer

рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА

рдореИрдВ рдХрд┐рд╕реА рднреА jsdom рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЛрдб рдХреЛ рдмрджрд▓реЗ рдмрд┐рдирд╛ FileList рдмрдирд╛рдиреЗ рдореЗрдВ рдХрд╛рдордпрд╛рдм рд░рд╣рд╛:

const createFile = (size = 44320, name = 'ecp-logo.png', type = 'image/png') =>
  new File([new ArrayBuffer(size)], name , {
    type: type,
  });

const createFileList = (file) => {
  const fileList = new FileList();
  fileList[0] = file;
  return fileList;
}

const fileList = createFileList(createFile());

рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдореИрдВ jsdom рджреНрд╡рд╛рд░рд╛ рдкреНрд░рджрд╛рди рдХреА рдЧрдИ FileList рдкрд░ FileList рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЙрд▓рд┐рдВрдЧ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдмрдирд╛ рд░рд╣рд╛ рд╣реВрдВред рдЙрд╕рдХреЗ рдмрд╛рдж рдореИрдВ рдХреЗрд╡рд▓ рдРрд░реЗ рдиреЛрдЯреЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЙрд╕ рд╕реВрдЪреА рдореЗрдВ рдлрд╝рд╛рдЗрд▓ рдЬреЛрдбрд╝ рд░рд╣рд╛ рд╣реВрдВред рдореЗрд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдореБрдЭреЗ рд╕рд░рдгреА рдореЗрдВ рдХреЗрд╡рд▓ 1 рдлрд╝рд╛рдЗрд▓ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдлрд╝рд╛рдЗрд▓ рд╕реВрдЪреА рдореЗрдВ рдПрдХрд╛рдзрд┐рдХ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕реЗ рд▓реВрдк рдХреЗ рд▓рд┐рдП рднреА рдмрджрд▓рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдореИрдВ рдлрд╝рд╛рдЗрд▓ рдирд┐рд░реНрдорд╛рддрд╛ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХрд╕реНрдЯрдо рдирд╛рдо/рдкреНрд░рдХрд╛рд░/рдЖрдХрд╛рд░ рдХреЗ рд╕рд╛рде рдлрд╝рд╛рдЗрд▓ рдмрдирд╛ рд░рд╣рд╛ рд╣реВрдВ рдЬреЛ рдЬреЗрдПрд╕рдбреЙрдо рджреНрд╡рд╛рд░рд╛ рдкреНрд░рджрд╛рди рдХреА рдЧрдИ рд╣реИ рдЬреЛ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рдХрд╛ рдкрд╛рд▓рди рдХрд░ рд░рд╣реА рд╣реИред

рдпрд╣ рдХрд┐рд╕реА рдРрд╕реЗ рд╡реНрдпрдХреНрддрд┐ рдХреЗ рд▓рд┐рдП рдорджрджрдЧрд╛рд░ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдЬреЛ рджреЗрдЦ рд░рд╣рд╛ рд╣реИ рдХрд┐ jsdom рд╡рд╛рддрд╛рд╡рд░рдг рдореЗрдВ FileList рдХрд╛ рдордЬрд╛рдХ рдХреИрд╕реЗ рдмрдирд╛рдпрд╛ рдЬрд╛рдП, рд▓реЗрдХрд┐рди рдПрдХ рдореБрджреНрджрд╛ рдЕрднреА рднреА рдЦрдбрд╝рд╛ рд╣реИред рдЗрд╕ рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдлрд╛рдЗрд▓реЛрдВ рдХреА рд╕рд░рдгреА рдХреЗ рд╕рд╛рде рдлрд╛рдЗрд▓рд▓рд┐рд╕реНрдЯ рдмрдирд╛рдирд╛ FileList.item(index) рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рд░рдгреА рд╕реЗ рдЖрдЗрдЯрдо рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рдирд╣реАрдВ рджреЗрдЧрд╛ред рд▓реЗрдХрд┐рди, рдпрд╣рд╛рдВ рддрдХ тАЛтАЛтАЛтАЛрдХрд┐ рдЗрд╕рдХреА рд╡рд┐рдзрд┐ рдХреЛ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдУрд╡рд░рд░рд╛рдЗрдб рдХрд░рдХреЗ рддрдп рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:

const createFileList = (file) => {
  const fileList = new FileList();
  fileList[0] = file;
  fileList.item = index => fileList[index]; // override method functionality
  return fileList;
}

рдореБрдЭреЗ рдЕрднреА рднреА рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдмреЗрд╣рддрд░ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдЕрдЧрд░ jsdom рдмреЙрдХреНрд╕ рдХреЗ рдмрд╛рд╣рд░ рдкрд░реАрдХреНрд╖рдг рдЙрджреНрджреЗрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдЗрди рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛рдУрдВ рдХреА рдкреЗрд╢рдХрд╢ рдХрд░ рд╕рдХреЗред

рд╕рднреА 30 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

input.files = createFileList(file1, file2, ...) рдЕрдЪреНрдЫрд╛ рд░рд╣реЗрдЧрд╛ред

@cpojer рдХреНрдпрд╛ рдЖрдк рд╡рд╣рд╛рдВ рдбрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рд╡рд╛рд╕реНрддрд╡рд┐рдХ File рдСрдмреНрдЬреЗрдХреНрдЯ рдЙрддреНрдкрдиреНрди рдХрд░ рд░рд╣реЗ рд╣реИрдВ?

input.files рд▓рд┐рдЦрдиреЗ рдпреЛрдЧреНрдп рдмрдирд╛рдирд╛ рд╢рд╛рдпрдж рдЦрд░рд╛рдм рд╣реИ, рд╣рдо рд╢рд╛рдпрдж рдЦреБрдж рдХреЛ рднрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрдЪреНрдЪреЗ рд╕рд░рдгреА рдХреЛ рд╡рд╛рдкрд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдпрд╛ рдХреБрдЫ рдРрд╕рд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ fillFileList(input.files, [file]) ред

рд╣рдо рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХреЗрд╡рд▓ рдирдХрд▓реА рдбреЗрдЯрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рд╣рдо рд╡рд╕реНрддреБрдУрдВ рдХреА рдПрдХ рд╕рд░рдгреА рдХреЗ рд╕рд╛рде .files рдкреЙрдкреНрдпреБрд▓реЗрдЯ рдХрд░рддреЗ рд╣реИрдВред рд▓реЗрдХрд┐рди рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдлрд╝рд╛рдЗрд▓ рдСрдмреНрдЬреЗрдХреНрдЯ рд╣реЛрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдЙрдЪрд┐рдд рд╣реЛрдЧреАред

рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдЬреИрд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдкреНрд░реЙрдкрд░реНрдЯреА рдпрд╣рд╛рдВ рдареАрдХ рд╣реЛрдЧреА? рдбреАрдУрдПрдо рдЧреБрдг рдХрд┐рд╕реА рдХрд╛рд░рдг рд╕реЗ рдкреБрди: рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдиреЗ рдпреЛрдЧреНрдп рд╣реИрдВ ...

рд╣рд╛рд▓рд╛рдВрдХрд┐, рдореИрдВ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рдПрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдлрд╛рдЗрд▓рд▓рд┐рд╕реНрдЯ рдмрдирд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред

рдлрд╝рд╛рдЗрд▓ рд╕реВрдЪреА рдЖрдЗрдЯрдо рдХреЛ рдЙрдирдХреЗ рд╕рд░рдгреА-рд╕реВрдЪрдХрд╛рдВрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХреНрд╕реЗрд╕ рдХрд░рдирд╛ рднреА рд╕рдВрднрд╡ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред .item рдЙрдирдХреЗ рдХреНрд╖реЗрддреНрд░реЛрдВ рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдХрд╛ рдПрдХрдорд╛рддреНрд░ рддрд░реАрдХрд╛ рдирд╣реАрдВ рд╣реИред

рдареАрдХ рд╣реИ, рддреЛ рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдХреБрдЫ рд╕рдВрднрд╛рд╡рд┐рдд рд╕рдорд╕реНрдпрд╛рдПрдВ рд╣реИрдВ:

  • рдлрд╛рдЗрд▓рд▓рд┐рд╕реНрдЯ рдореЗрдВ рдареАрдХ рд╕реЗ рдЕрдиреБрдХреНрд░рдорд┐рдд рдкрд╣реБрдВрдЪ рдХрд╛рдо рдирд╣реАрдВ рдХрд░ рд░рд╣реА рд╣реИ (рдмрдЧ)
  • рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП рдлрд╛рдЗрд▓рд▓рд┐рд╕реНрдЯ рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдиреЗ рдХрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рдирд╣реАрдВ рд╣реИ (рд╡реЗрдм тАЛтАЛтАЛтАЛрдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рдлреАрдЪрд░ рдЧреИрдк)ред

рд▓реЗрдХрд┐рди inputEl.files рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рдирд╛ рд╕рдорд╕реНрдпрд╛ рдирд╣реАрдВ рд╣реИред

рд╣рд╛рдБ, рдореЗрд░рд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдЗрдВрдЬреАрдирд┐рдпрд░реЛрдВ рдХреЛ рдирд┐рдпрдорд┐рдд рдЕрд╕рд╛рдЗрдирдореЗрдВрдЯ рдкрд░ Object.defineProperty рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╣рдирд╛ рдХрдорд╛рд▓ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВ рдЗрд╕рдХреЗ рд╕рд╛рде рд░рд╣ рд╕рдХрддрд╛ рд╣реВрдВред

рдЦреИрд░, рдЙрдиреНрд╣реЗрдВ рд╡реИрд╕реЗ рднреА рдЕрд╕рд▓реА рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рдХрд░рдирд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП рдЙрдЪрд┐рдд рд▓рдЧрддрд╛ рд╣реИ ...

рдирдорд╕реНрддреЗ, рдореИрдВ рджреЗрдЦ рд░рд╣рд╛ рд╣реВрдВ рдХрд┐ рдпрд╣ рдПрдХ рд╡рд░реНрд╖ рд╕реЗ рдЕрдзрд┐рдХ рдкреБрд░рд╛рдирд╛ рд╣реИ, рдореИрдВ рдкреВрдЫрдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХрд┐ рдХреНрдпрд╛ рдЗрд╕ рдореБрджреНрджреЗ рдХреЗ рд╕рдВрдмрдВрдз рдореЗрдВ рдХреЛрдИ рдкреНрд░рдЧрддрд┐ рд╣реБрдИ рд╣реИ? рдореИрдВ рдЕрдкрдиреЗ рд░рд┐рдПрдХреНрдЯ/рд░реЗрдбрдХреНрд╕ рдРрдк рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬреЗрд╕реНрдЯ рдлреНрд░реЗрдорд╡рд░реНрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ рдЬреЛ рдЖрдВрддрд░рд┐рдХ рд░реВрдк рд╕реЗ jsdom рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред рдореБрдЭреЗ рдПрдХ рд╕рдорд╕реНрдпрд╛ рд╣реИ рдЬрд╣рд╛рдВ рдореБрдЭреЗ рдПрдХ рдпрд╛ рдЕрдзрд┐рдХ рдлрд╝рд╛рдЗрд▓ рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХреЗ рд╕рд╛рде рдЧрддрд┐рд╢реАрд▓ рд░реВрдк рд╕реЗ FileList рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред

lib/jsdom/living/filelist.js рдХреЛ рджреЗрдЦрддреЗ рд╣реБрдП рдореИрдВ рджреЗрдЦ рд╕рдХрддрд╛ рд╣реВрдВ рдХрд┐ рдлрд╛рдЗрд▓рд▓рд┐рд╕реНрдЯ рдХреЗ рд▓рд┐рдП рдПрдХ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рд╣реИ рд▓реЗрдХрд┐рди рдЗрд╕рдореЗрдВ рдлрд╛рдЗрд▓ рдкрд╛рд╕ рдХрд░рдиреЗ рдХрд╛ рдХреЛрдИ рд╡рд┐рдХрд▓реНрдк рдирд╣реАрдВ рд╣реИред рдореИрдВ рд╕рдордЭрддрд╛ рд╣реВрдВ рдХрд┐ рд╕реБрд░рдХреНрд╖рд╛ рдХрд╛рд░рдгреЛрдВ рд╕реЗ рдлрд╝рд╛рдЗрд▓рд▓рд┐рд╕реНрдЯ рдФрд░ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд╡рд┐рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХреЛ рдлрд╝рд╛рдЗрд▓ рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХреА рд╕рд░рдгреА рдпрд╛ рдХрдо рд╕реЗ рдХрдо рдЕрддрд┐рд░рд┐рдХреНрдд рд╡рд┐рдзрд┐ (рдорд╛рди рд▓реЗрдВ _setItem_) рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдиреЗ рдХрд╛ рдХреЛрдИ рдЗрд░рд╛рджрд╛ рд╣реИ рдЬреЛ рд╣рдореЗрдВ рдлрд╝рд╛рдЗрд▓ рдЬреЛрдбрд╝рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдкрд░реАрдХреНрд╖рдг рдЙрджреНрджреЗрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рд╕реВрдЪреА рдореЗрдВ рд╡рд╕реНрддреБрдУрдВ?

рдореИрдВ рдлрд╛рдЗрд▓рд▓рд┐рд╕реНрдЯ рдХреЗ рд╕рд╛рде рдПрдХ рдФрд░ рдореБрджреНрджрд╛ рднреА рджреЗрдЦрддрд╛ рд╣реВрдВред рдЕрдЧрд░ рдореИрдВ рдЧрд▓рддреА рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рддреЛ рдпрд╣ рдРрд░реЗ рдЬреИрд╕реА рд╡рд╕реНрддреБ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП, рдЬреЛ рдиреЛрдбрд▓рд┐рд╕реНрдЯ (lib/jsdom/living/node-list.js) рдХреЗ рд╕рдорд╛рди рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдлрд╝рд╛рдЗрд▓ рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХреЛ рджреЛ рддрд░реАрдХреЛрдВ рд╕реЗ рдПрдХреНрд╕реЗрд╕ рдХрд░рдиреЗ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП:

var fileList = document.getElementById("myfileinput").files;

fileList[0];
fileList.item(0);

рд╡рд░реНрддрдорд╛рди рдореЗрдВ, рдХреЗрд╡рд▓ рд╡рд┐рдзрд┐ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╣реА рдкрд╣реБрдВрдЪрдирд╛ рд╕рдВрднрд╡ рд╣реИред рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ NodeList рдХреЗ рд╕рдорд╛рди рддрд░реНрдХ рдпрд╣рд╛рдВ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП:

FileList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];

рдФрд░ рдлрд╛рдЗрд▓реЛрдВ рдХреЛ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рд╕реЗ рд╕рдВрдЧреНрд░рд╣рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдпрджрд┐ рд╣рдо рдлрд╛рдЗрд▓реЛрдВ рдХреЛ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХреЛ рдкрд╛рд╕ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдВрдЧреЗ:

for (let i = 0; i < files.length; ++i) {
  this[i] = files[i];
}

рдпрд╣ рдХреИрд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдореЗрд░реА рдХреЛрдИ рдордЬрдмреВрдд рд░рд╛рдп рдирд╣реАрдВ рд╣реИ, рдпреЗ рдХреЗрд╡рд▓ рдЙрджрд╛рд╣рд░рдг рд╣реИрдВ рдЬрд┐рдирдХрд╛ рдЙрдкрдпреЛрдЧ рдореИрдВ рдмреЗрд╣рддрд░ рддрд░реАрдХреЗ рд╕реЗ рд╕рдордЭрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд░рддрд╛ рд╣реВрдВ рдЬреЛ рдореИрдВ рдЗрдВрдЧрд┐рдд рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣рд╛ рд╣реВрдВред

рдЕрддрд┐рд░рд┐рдХреНрдд рдкреНрд░рд╢реНрди (рдореИрдВ рдпрд╣рд╛рдВ рдкреВрдЫрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдЕрдирд╛рд╡рд╢реНрдпрдХ рдореБрджреНрджреЛрдВ рдХреЛ рдирд╣реАрдВ рдЦреЛрд▓рдирд╛ рдЪрд╛рд╣рддрд╛):

1.) рдХреНрдпрд╛ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рд░реВрдк рдореЗрдВ рдкреНрд░рджрд╛рди рдХрд┐рдП рдЧрдП рдкрде рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдлрд╝рд╛рдЗрд▓ рд╕реЗ рдлрд╝рд╛рдЗрд▓ рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдиреЗ рд╡рд╛рд▓реЗ рдкрд░реАрдХреНрд╖рдг рдЙрджреНрджреЗрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдлрд╝рд╛рдЗрд▓ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХреЛ рдЬреЛрдбрд╝рдирд╛ рдлрд╛рдпрджреЗрдордВрдж рд╣реЛрдЧрд╛? рдореБрдЭреЗ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдорд┐рд▓рд╛ (рдореБрдЭреЗ рдХреНрд╖рдорд╛ рдХрд░реЗрдВ, рдореБрдЭреЗ рдЕрдм рд▓рд┐рдВрдХ рдирд╣реАрдВ рдорд┐рд▓ рд░рд╣рд╛ рд╣реИ) рдЬрд┐рд╕рдиреЗ рдЗрд╕рдХреА рдЕрдиреБрдорддрд┐ рджреА:

const file = new File('../fixtures/files/test-image.png');

рдЗрд╕рдиреЗ рдореЗрд░реЗ рд▓рд┐рдП рдЧреБрдгреЛрдВ рдХреЗ рд╕рд╛рде рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдИ (рдЖрдХрд╛рд░, рдЕрдВрддрд┐рдо рд╕рдВрд╢реЛрдзрд┐рдд, рдкреНрд░рдХрд╛рд░ ...) рдореЗрд░реЗ рдмрд┐рдирд╛ рдЗрд╕реЗ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП:

const file = new File([''], 'test-image.png', {
  lastModified: 1449505890000,
  lastModifiedDate: new Date(1449505890000),
  name: "ecp-logo.png",
  size: 44320,
  type: "image/png",
});

рдореБрдЭреЗ рдирд╣реАрдВ рдкрддрд╛ рдХрд┐ рдпрд╣ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдореИрдВ рдХреЗрд╡рд▓ рдЗрддрдирд╛ рдЬрд╛рдирддрд╛ рд╣реВрдВ рдХрд┐ рдЗрд╕реЗ рдПрдХ рд╡рд░реНрд╖ рд╕реЗ рдЕрдзрд┐рдХ рд╕рдордп рддрдХ рдирд╣реАрдВ рд░рдЦрд╛ рдЧрдпрд╛ рдерд╛ рдФрд░ рд╣рдордиреЗ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдмрдВрдж рдХрд░ рджрд┐рдпрд╛ рдерд╛ред рдореИрдВ рдЗрд╕реЗ рдЕрдм рдФрд░ рдирд╣реАрдВ рдвреВрдВрдв рд╕рдХрддрд╛ред

2.) window.URL.createObjectURL jsdom рджреНрд╡рд╛рд░рд╛ рд╕рдорд░реНрдерд┐рдд рдирд╣реАрдВ рд╣реИред рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЗрд╕рдХреА рд╕реВрдЪрдирд╛ рджреА рдЬрд╛рдиреА рдЪрд╛рд╣рд┐рдПред

рдореИрдВ рдХрд┐рд╕реА рднреА jsdom рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЛрдб рдХреЛ рдмрджрд▓реЗ рдмрд┐рдирд╛ FileList рдмрдирд╛рдиреЗ рдореЗрдВ рдХрд╛рдордпрд╛рдм рд░рд╣рд╛:

const createFile = (size = 44320, name = 'ecp-logo.png', type = 'image/png') =>
  new File([new ArrayBuffer(size)], name , {
    type: type,
  });

const createFileList = (file) => {
  const fileList = new FileList();
  fileList[0] = file;
  return fileList;
}

const fileList = createFileList(createFile());

рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдореИрдВ jsdom рджреНрд╡рд╛рд░рд╛ рдкреНрд░рджрд╛рди рдХреА рдЧрдИ FileList рдкрд░ FileList рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЙрд▓рд┐рдВрдЧ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдмрдирд╛ рд░рд╣рд╛ рд╣реВрдВред рдЙрд╕рдХреЗ рдмрд╛рдж рдореИрдВ рдХреЗрд╡рд▓ рдРрд░реЗ рдиреЛрдЯреЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЙрд╕ рд╕реВрдЪреА рдореЗрдВ рдлрд╝рд╛рдЗрд▓ рдЬреЛрдбрд╝ рд░рд╣рд╛ рд╣реВрдВред рдореЗрд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдореБрдЭреЗ рд╕рд░рдгреА рдореЗрдВ рдХреЗрд╡рд▓ 1 рдлрд╝рд╛рдЗрд▓ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдлрд╝рд╛рдЗрд▓ рд╕реВрдЪреА рдореЗрдВ рдПрдХрд╛рдзрд┐рдХ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕реЗ рд▓реВрдк рдХреЗ рд▓рд┐рдП рднреА рдмрджрд▓рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдореИрдВ рдлрд╝рд╛рдЗрд▓ рдирд┐рд░реНрдорд╛рддрд╛ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХрд╕реНрдЯрдо рдирд╛рдо/рдкреНрд░рдХрд╛рд░/рдЖрдХрд╛рд░ рдХреЗ рд╕рд╛рде рдлрд╝рд╛рдЗрд▓ рдмрдирд╛ рд░рд╣рд╛ рд╣реВрдВ рдЬреЛ рдЬреЗрдПрд╕рдбреЙрдо рджреНрд╡рд╛рд░рд╛ рдкреНрд░рджрд╛рди рдХреА рдЧрдИ рд╣реИ рдЬреЛ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рдХрд╛ рдкрд╛рд▓рди рдХрд░ рд░рд╣реА рд╣реИред

рдпрд╣ рдХрд┐рд╕реА рдРрд╕реЗ рд╡реНрдпрдХреНрддрд┐ рдХреЗ рд▓рд┐рдП рдорджрджрдЧрд╛рд░ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдЬреЛ рджреЗрдЦ рд░рд╣рд╛ рд╣реИ рдХрд┐ jsdom рд╡рд╛рддрд╛рд╡рд░рдг рдореЗрдВ FileList рдХрд╛ рдордЬрд╛рдХ рдХреИрд╕реЗ рдмрдирд╛рдпрд╛ рдЬрд╛рдП, рд▓реЗрдХрд┐рди рдПрдХ рдореБрджреНрджрд╛ рдЕрднреА рднреА рдЦрдбрд╝рд╛ рд╣реИред рдЗрд╕ рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдлрд╛рдЗрд▓реЛрдВ рдХреА рд╕рд░рдгреА рдХреЗ рд╕рд╛рде рдлрд╛рдЗрд▓рд▓рд┐рд╕реНрдЯ рдмрдирд╛рдирд╛ FileList.item(index) рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рд░рдгреА рд╕реЗ рдЖрдЗрдЯрдо рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рдирд╣реАрдВ рджреЗрдЧрд╛ред рд▓реЗрдХрд┐рди, рдпрд╣рд╛рдВ рддрдХ тАЛтАЛтАЛтАЛрдХрд┐ рдЗрд╕рдХреА рд╡рд┐рдзрд┐ рдХреЛ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдУрд╡рд░рд░рд╛рдЗрдб рдХрд░рдХреЗ рддрдп рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:

const createFileList = (file) => {
  const fileList = new FileList();
  fileList[0] = file;
  fileList.item = index => fileList[index]; // override method functionality
  return fileList;
}

рдореБрдЭреЗ рдЕрднреА рднреА рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдмреЗрд╣рддрд░ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдЕрдЧрд░ jsdom рдмреЙрдХреНрд╕ рдХреЗ рдмрд╛рд╣рд░ рдкрд░реАрдХреНрд╖рдг рдЙрджреНрджреЗрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдЗрди рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛рдУрдВ рдХреА рдкреЗрд╢рдХрд╢ рдХрд░ рд╕рдХреЗред

рд╣рд╛рдп рджреЛрд╕реНрддреЛрдВ ,
рдореБрдЭреЗ $("#selectorID of Upload file")[0].files[0] рдСрдмреНрдЬреЗрдХреНрдЯ рдХрд╛ рдордЬрд╝рд╛рдХ рдЙрдбрд╝рд╛рддреЗ рд╕рдордп рдХреБрдЫ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рдирд╛ рдкрдбрд╝ рд░рд╣рд╛ рд╣реИ рдЬреЛ FileList рд▓реМрдЯрд╛ рд░рд╣рд╛ рд╣реИред
рдХреНрдпрд╛ рдХреЛрдИ рдореБрдЭреЗ рдлрд╛рдЗрд▓рд▓рд┐рд╕реНрдЯ рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдиреЗ рдореЗрдВ рдорджрдж рдХрд░ рд╕рдХрддрд╛ рд╣реИ? рдХреНрдпреЛрдВрдХрд┐ рдореБрдЭреЗ WWW рдореЗрдВ рдХрд╣реАрдВ рднреА рдХреЛрдИ рд╕рдВрджрд░реНрдн рд▓рд┐рдВрдХ рдирд╣реАрдВ рдорд┐рд▓ рд░рд╣рд╛ рд╣реИ

рдпрд╣ рдлрд┐рд▓рд╣рд╛рд▓ рд╕рдВрднрд╡ рдирд╣реАрдВ рд╣реИред

рдзрдиреНрдпрд╡рд╛рдж рдбреЛрдорд┐рдирд┐рдХ,

рдореБрдЭреЗ рдлрд╝рд╛рдЗрд▓ рдЕрдкрд▓реЛрдб рдкрд░рд┐рд╡рд░реНрддрди рдИрд╡реЗрдВрдЯ рдХреЗ рд▓рд┐рдП рдПрдХ рдЯреЗрд╕реНрдЯ рдХреЗрд╕ рд▓рд┐рдЦрдирд╛ рд╣реЛрдЧрд╛ред рдЙрд╕ рдкрд░реАрдХреНрд╖рдг рдкрд░рд┐рджреГрд╢реНрдп рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХрд╛ рдХреЛрдИ рд╡реИрдХрд▓реНрдкрд┐рдХ рддрд░реАрдХрд╛ред

рдЗрд╕ рдкрд░ рдХреЛрдИ рдкреНрд░рдЧрддрд┐?

@niksajanjic рдХреНрдпрд╛ рдЖрдкрдиреЗ рдЗрд╕ рд╕реВрддреНрд░ рдореЗрдВ рдкреНрд░рд╕реНрддреБрдд рд╕рд░реНрд╡реЛрддреНрддрдо рд╕рдорд╛рдзрд╛рди рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдмрдВрдзрди рдХрд┐рдпрд╛ рд╣реИ?
рд╕рдВрджрд░реНрдн: const file = new File('../fixtures/files/test-image.png');
рдпрд╛ рдРрд╕рд╛ рд╣реА рдХреБрдЫ?
рд╢реНрд░реЗрд╖реНрда

@domenic рдЗрд╕ рдореБрджреНрджреЗ рдкрд░ рдЙрд╕ рдЯреНрд╡рд┐рдЯрд░ рдкреЛрд╕реНрдЯ рдореЗрдВ рдереЛрдбрд╝рд╛ рд╕рд╛ рдЕрд╕рдВрддреЛрд╖ рд╣реИ

@domenic рдареАрдХ рд╣реИ, рдореИрдВрдиреЗ рдЗрд╕рдХреЗ рд▓рд┐рдП рдореВрд▓ рд╢реБрд░реБрдЖрдд рдХреА рд╣реИред рд╕рднреА рдЬрд╛рдБрдЪреЗрдВ рдирд╣реАрдВ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдпрд╣ рдЕрдирд┐рд╡рд╛рд░реНрдп рд░реВрдк рд╕реЗ

рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдПрдБ

function createFile(file_path) {
  const { mtimeMs: lastModified, size } = fs.statSync(file_path)

  return new File(
    [new fs.readFileSync(file_path)],
    path.basename(file_path),
    {
      lastModified,
      type: mime.lookup(file_path) || '',
    }
  )
}

рдлрд╝рд╛рдЗрд▓ рд╕реВрдЪреА рдЬреЛрдбрд╝реЗрдВ

function addFileList(input, file_paths) {
  if (typeof file_paths === 'string')
    file_paths = [file_paths]
  else if (!Array.isArray(file_paths)) {
    throw new Error('file_paths needs to be a file path string or an Array of file path strings')
  }

  const file_list = file_paths.map(fp => createFile(fp))
  file_list.__proto__ = Object.create(FileList.prototype)

  Object.defineProperty(input, 'files', {
    value: file_list,
    writeable: false,
  })

  return input
}

рдбреЗрдореЛ рдлрд╝рд╛рдЗрд▓

/*eslint-disable no-console, no-unused-vars */

/*
https://github.com/jsdom/jsdom/issues/1272
*/

const fs = require('fs')
const path = require('path')
const mime = require('mime-types')

const { JSDOM } = require('jsdom')
const dom = new JSDOM(`
<!DOCTYPE html>
<body>
  <input type="file">
</body>
`)

const { window } = dom
const { document, File, FileList } = window


const file_paths = [
  '/Users/williamrusnack/Documents/form_database/test/try-input-file.html',
  '/Users/williamrusnack/Documents/form_database/test/try-jsdom-input-file.js',
]

function createFile(file_path) {
  const { mtimeMs: lastModified, size } = fs.statSync(file_path)

  return new File(
    [new fs.readFileSync(file_path)],
    path.basename(file_path),
    {
      lastModified,
      type: mime.lookup(file_path) || '',
    }
  )
}

function addFileList(input, file_paths) {
  if (typeof file_paths === 'string')
    file_paths = [file_paths]
  else if (!Array.isArray(file_paths)) {
    throw new Error('file_paths needs to be a file path string or an Array of file path strings')
  }

  const file_list = file_paths.map(fp => createFile(fp))
  file_list.__proto__ = Object.create(FileList.prototype)

  Object.defineProperty(input, 'files', {
    value: file_list,
    writeable: false,
  })

  return input
}



const input = document.querySelector('input')

addFileList(input, file_paths)

for (let i = 0; i < input.files.length; ++i) {
  const file = input.files[i]
  console.log('file', file)
  console.log('file.name', file.name)
  console.log('file.size', file.size)
  console.log('file.type', file.type)
  console.log('file.lastModified', file.lastModified)
  console.log()
}

@BebeSparkelSparkel рдореИрдВрдиреЗ рдПрдХ рддрд░рд╣ рд╕реЗ рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛, рдЬрд┐рд╕реЗ рдореИрдВрдиреЗ рдЕрдкрдиреА рдмрд╛рдж рдХреА рдкреЛрд╕реНрдЯ рдореЗрдВ рд╕рдордЭрд╛рдпрд╛ рдерд╛ред рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, рдХреБрдЫ рдорд╣реАрдиреЗ рдмрд╛рдж рдЬрдм рдореЗрд░реЗ рдПрдХ рд╕рд╣рдпреЛрдЧреА рдиреЗ рдЙрд╕ рдХреЛрдб рдХреЛ рдХреЙрдкреА рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА рддреЛ рдЙрд╕рдиреЗ jsdom рдХреЗ рдирдП рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдкрд░ рдХрд╛рдо рдХрд░рдирд╛ рдмрдВрдж рдХрд░ рджрд┐рдпрд╛ред рдЗрд╕рд▓рд┐рдП, рд╣рдореЗрдВ рдЙрд╕ рд╕рдордп рдлрд╛рдЗрд▓рд▓рд┐рд╕реНрдЯ рдХреЗ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдкрд░ рдЯрд┐рдкреНрдкрдгреА рдХрд░рдиреА рдкрдбрд╝реАред рд╡рд╣рд╛рдВ рд╕реЗ, рд╣рдореЗрдВ рдЙрди рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЛ рд▓рд┐рдЦрдиреЗ рдХрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рдирд╣реАрдВ рдорд┐рд▓рд╛ рдФрд░ рдкрд┐рдЫрд▓реЗ рдХреБрдЫ рдорд╣реАрдиреЛрдВ рдореЗрдВ рдХрд┐рд╕реА рдХреЗ рдкрд╛рд╕ рдЗрд╕реЗ рджреЛрдмрд╛рд░рд╛ рджреЗрдЦрдиреЗ рдФрд░ рд░рд╛рд╕реНрддрд╛ рдЦреЛрдЬрдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рдиреЗ рдХрд╛ рд╕рдордп рдирд╣реАрдВ рдерд╛ред

@niksajanjic рдЖрдкрдХреЗ рдЕрдкрдбреЗрдЯ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред рдореИрдВ рдЖрдкрдХреЗ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рд╕реНрддрд╛рд╡рд┐рдд рд╕рдорд╛рдзрд╛рди рдкрд░ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдФрд░ рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реИ (рдЙрдкрд░реЛрдХреНрдд рдХреЛрдб рджреЗрдЦреЗрдВ), рд▓реЗрдХрд┐рди рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕реЗ jsdom рдореЗрдВ рдЬреЛрдбрд╝рдиреЗ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рдирд╣реАрдВ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛рдирд╛ рдмрд╣реБрдд рдореБрд╢реНрдХрд┐рд▓ рд╣реЛрдЧрд╛ рдХрд┐ рдЗрд╕реЗ рдХреИрд╕реЗ рдЬреЛрдбрд╝рд╛ рдЬрд╛рдПред
рдмреЗрдЭрд┐рдЭрдХ рдПрдХ рдмрд╛рд░ рджреЗрдЦ рд▓реЗрдВ рдФрд░ рдЕрдЧрд░ рдЖрдк рдЪрд╛рд╣реЗрдВ рддреЛ рдЗрд╕рдХрд╛ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд░реЗрдВ

рдПрдХ рд╕рд╛рдзрд╛рд░рдг рд╕рд╣рд╛рдпрдХ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдмрдирд╛рдИ рдЬреЛ рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рддреА рд╣реИ рдЬрдм рддрдХ рдХрд┐ jsdom рдкреНрд░реЛрдЬреЗрдХреНрдЯ рд╕рдорд╛рдзрд╛рди рдХреЗ рд╕рд╛рде рдирд╣реАрдВ рдЖрддрд╛ред
https://bitbucket.org/william_rusnack/addfilelist/src/master/

рдПрдХ рдлрд╝рд╛рдЗрд▓ рдЬреЛрдбрд╝реЗрдВ:

const input = document.querySelector('input[type=file]')
addFileList(input, 'path/to/file')

рдПрдХрд╛рдзрд┐рдХ рдлрд╝рд╛рдЗрд▓реЗрдВ рдЬреЛрдбрд╝реЗрдВ:

const input = document.querySelector('input[type=file]')
addFileList(input, [
  'path/to/file',
  'path/to/another/file',
  // add as many as you want
])

рд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдВ рдФрд░ рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ

npm install https://github.com/BebeSparkelSparkel/addFileList.git

```рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ
const {addFileList} = рдЖрд╡рд╢реНрдпрдХрддрд╛ ('addFileList')

## Functions
**addFileList**(input, file_paths)  
Effects: puts the file_paths as File object into input.files as a FileList  
Returns: input  
Arguments:  
- input: HTML input element  
- file_paths: String or Array of string file paths to put in input.files  
`const { addFileList } = require('addFileList')`  

## Example
Extract from example.js
```javascript
// add a single file
addFileList(input, 'example.js')

// log input's FileList
console.log(input.files)

// log file properties
const [ file ] = input.files
console.log(file)
console.log(
  '\nlastModified', file.lastModified,
  '\nname', file.name,
  '\nsize', file.size,
  '\ntype', file.type,
  '\n'
)

рдирддреАрдЬрд╛

$ node example.js 
FileList [ File {} ]
File {}

lastModified 1518523506000 
name example.js 
size 647 
type application/javascript 

@BebeSparkelSparkel рдЖрдкрдХрд╛ рд░реЗрдкреЛ рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЧрдпрд╛ рд▓рдЧрддрд╛ рд╣реИ?

рдореБрдЭреЗ рднреА рдЗрд╕реА рддрд░рд╣ рдХреА рд╕рдорд╕реНрдпрд╛ рдереА- рдореИрдВрдиреЗ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рд▓рд┐рдЦрд╛ рдерд╛ рдЬреЛ рдЗрдирдкреБрдЯ рдХреЗ рд░реВрдк рдореЗрдВ FileList рд▓реЗрддрд╛ рдерд╛ рдФрд░ рдЬреЗрд╕реНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕рдХреЗ рд▓рд┐рдП рдПрдХ рдпреВрдирд┐рдЯ рдЯреЗрд╕реНрдЯ рд▓рд┐рдЦрдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛ред рдореИрдВ рдЕрдкрдиреЗ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд FileList рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рдЦрд░рд╛рдм рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдиреАрдЪреЗ рджрд┐рдП рдЧрдП рд╕рд╣рд╛рдпрдХ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдерд╛ред рдлреНрд▓реЛ рдПрдиреЛрдЯреЗрд╢рди рдХреЗ рд╕рд╛рде рд╕рд┐рдВрдЯреИрдХреНрд╕ ES6 рд╣реИред рдХреЛрдИ рд╡рд╛рджрд╛ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдпрд╣ рд╕рднреА рдкрд░рд┐рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдореЗрдВ рдХрд╛рдо рдХрд░реЗрдЧрд╛ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рд╡рд╛рд╕реНрддрд╡рд┐рдХ FileList рд╡рд░реНрдЧ рдХреА рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рдХреЗрд╡рд▓ рдирдХрд▓реА рдмрдирд╛ рд░рд╣рд╛ рд╣реИ ...

const createFileList = (files: Array<File>): FileList => {
  return {
    length: files.length,
    item: (index: number) => files[index],
    * [Symbol.iterator]() {
      for (let i = 0; i < files.length; i++) {
        yield files[i];
      }
    },
    ...files,
  };
};

рдЕрдЧреНрд░рднрд╛рдЧ рдореЗрдВ, рдореИрдВ рдПрдХ 'рдЕрд╕рд▓реА' FileList рд▓рд┐рдП рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреА рддрд░рд╣ рдХреБрдЫ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ:

export const makeFileList = files => {
  const reducer = (dataTransfer, file) => {
    dataTransfer.items.add(file)
    return dataTransfer
  }

  return files.reduce(reducer, new DataTransfer()).files
}

рд╕рдВрджрд░реНрдн: https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer

рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, jsdom рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЕрднреА рддрдХ DataTransfer рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрд╣ рдореЗрд░реЗ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдореЗрдВ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ:

рдЕрдиреНрдп рд░реЗрдлрд░реА:


рд╕реНрд░реЛрдд рдХреЛ рдереЛрдбрд╝рд╛ рдЦреЛрдЬрдиреЗ рдкрд░ рдореБрдЭреЗ exports.FileList = require("./generated/FileList").interface;

~рд▓реЗрдХрд┐рди рдЧрд┐рдЯрд╣рдм рд╕реЗ рдореБрдЭреЗ рдпрд╣ рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рдерд╛ рдХрд┐ ./generated рдмрдирд╛рдиреЗ рд╡рд╛рд▓реЗ рд╕реНрд░реЛрдд рдХреЛ рдХрд╣рд╛рдВ рдЦреЛрдЬрд╛ рдЬрд╛рдП ~

рдПрдирдкреАрдПрдо рдкреИрдХреЗрдЬ рдХрд╛ рдореБрдЦреНрдп рдирд┐рд░реНрдпрд╛рдд ./lib/api.js рдФрд░ рдПрдХ рдмрд╣реБрдд рдЫреЛрдЯрд╛ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдПрдкреАрдЖрдИ рдирд┐рд░реНрдпрд╛рдд рдХрд░рддрд╛ рд╣реИ:

exports.JSDOM = JSDOM;
exports.VirtualConsole = VirtualConsole;
exports.CookieJar = CookieJar;
exports.ResourceLoader = ResourceLoader;
exports.toughCookie = toughCookie;

рд▓реЗрдХрд┐рди рдореЗрд░реА ./node_modules/jsdom/lib/jsdom рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рджреЗрдЦ рд░рд╣реЗ рд╣реИрдВ .. рдореИрдВ рджреЗрдЦ рд╕рдХрддрд╛ рд╣реВрдВ рдХрд┐ ./node_modules/jsdom/lib/jsdom/living/file-api рд╕рд╣рд┐рдд рд╕рднреА рдЖрдВрддрд░рд┐рдХ/рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдлрд╝рд╛рдЗрд▓реЗрдВ рднреА рд╣реИрдВ:

Blob-impl.js  File-impl.js  FileList-impl.js  FileReader-impl.js

FileList-impl.js рдпрд╣рд╛рдВ рд╡рд╛рд╕реНрддрд╡рд┐рдХ JS рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реИ рдЬреЛ jsdom рдореЗрдВ рдЙрдЬрд╛рдЧрд░ FileList api рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИред

рдЕрдм рдпрджрд┐ рд╣рдо ./node_modules/jsdom/lib/jsdom/living/generated/FileList.js рджреЗрдЦреЗрдВ рддреЛ рд╣рдореЗрдВ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЙрддреНрдкрдиреНрди 'рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдПрдкреАрдЖрдИ' рджрд┐рдЦрд╛рдИ рджреЗрддрд╛ рд╣реИ рдЬрд┐рд╕реЗ рд╣рдо рд╕рд╛рдорд╛рдиреНрдп рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рджреЗрдЦрддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдореЗрдВ рд╣рдорд╛рд░реЗ рд╕рднреА рдкрд░рд┐рдЪрд┐рдд рднреА рд╢рд╛рдорд┐рд▓ рд╣реИрдВ:

class FileList {
  constructor() {
    throw new TypeError("Illegal constructor");
  }

рдпрд╣ рдлрд╝рд╛рдЗрд▓ module.exports = iface; рдирд┐рд░реНрдпрд╛рдд рдХрд░рддреА рд╣реИ, рдЬрд┐рд╕рдореЗрдВ 'рд╕рд╛рдорд╛рдиреНрдп' рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдПрдкреАрдЖрдИ рдПрдХреНрд╕рдкреЛрдЬрд░ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╣рдорд╛рд░реЗ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рд╛рдкреНрдд рдХреА рдЬрд╛рдиреЗ рд╡рд╛рд▓реА рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдмрд╣реБрдд рдЕрдзрд┐рдХ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рд╣реЛрддреА рд╣реИ, рдЬреЛ рдХреЗрд╡рд▓ iface.interface рдХреБрдВрдЬреА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреА рд╣реИред рддреЛ рд╢рд╛рдпрдж рд╣рдо рдХреБрдЫ рдордЬреЗрджрд╛рд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЕрдЧрд░ рд╣рдо рд╕реАрдзреЗ require("./generated/FileList") рдХрд░рддреЗ рд╣реИрдВред рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╡рд┐рд╡рд░рдг рдХреЛ рд╣рдЯрд╛рдХрд░, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд╣реИ рдЬреЛ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:

const iface = {
  _mixedIntoPredicates: [],
  is(obj) {..snip..},
  isImpl(obj) {..snip..},
  convert(obj, { context = "The provided value" } = {}) {..snip..},
  create(constructorArgs, privateData) {..snip..},
  createImpl(constructorArgs, privateData) {..snip..},
  _internalSetup(obj) {},
  setup(obj, constructorArgs, privateData) {...snip...},
  interface: FileList,
  expose: {
    Window: { FileList },
    Worker: { FileList }
  }
}; // iface

рддреЛ рдЕрдм рдЬрдмрдХрд┐ рд╣рдо рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдЕрднреА рдФрд░ рд╢рдХреНрддрд┐ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреА рд╣реИ.. рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ jsdom рдЕрдиреНрдп рдХреНрд╖реЗрддреНрд░ рдЗрд╕реЗ рдХреИрд╕реЗ рдПрдХреНрд╕реЗрд╕ рдХрд░рддреЗ рд╣реИрдВ..

HTMLInputElement-impl рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓рдиреЗ рдкрд░, рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ FileList.createImpl() рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╣рдореЗрдВ рдкреИрд░рд╛рдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рддрд░реАрдХрд╛ рдирд╣реАрдВ рджрд┐рдЦрд╛рддрд╛ рд╣реИ:

createImpl рдирд┐рд░реНрдпрд╛рдд рдХрд┐рдП рдЧрдП iface рдореЗрдВ setup рдЖрд╕рдкрд╛рд╕ рд╕рд┐рд░реНрдл рдПрдХ рдЫреЛрдЯрд╛ рдЖрд╡рд░рдг рд╣реИ:

createImpl(constructorArgs, privateData) {
    let obj = Object.create(FileList.prototype);
    obj = this.setup(obj, constructorArgs, privateData);
    return utils.implForWrapper(obj);
  },

рдХрдВрд╕реЛрд▓ рдореЗрдВ рдЗрд╕рдХреЗ рд╕рд╛рде рдЦреЗрд▓рдиреЗ рд╕реЗ рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ Array рддрддреНрд╡ рдХреА рдЕрднрд┐рд╡реНрдпрдВрдЬрдХ рдПрдкреАрдЖрдИ рд╣реИ рдЬреЛ FileListImpl рджреНрд╡рд╛рд░рд╛ рд╕рдорд░реНрдерд┐рдд рд╣реИред рддреЛ рд╣рдо рдЗрд╕ рддрд░рд╣ рдХреА рдЪреАрдЬреЗрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

var flist = require('./node_modules/jsdom/lib/jsdom/living/generated/FileList.js')
var myFileListImpl = flist.createImpl()
myFileListImpl.push('aa')

рдЗрд╕ рдкрд░ рдПрдХ Symbol(wrapper) рд╕рдВрдкрддреНрддрд┐ рд╣реИ, рдЬрд┐рд╕реЗ рдПрдХреНрд╕реЗрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдореЗрдВ ./node_modules/jsdom/lib/jsdom/living/generated/utils.js:37 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реЛрдЧрд╛:

var utils = require('./node_modules/jsdom/lib/jsdom/living/generated/utils.js')
var wrapper = myFileListImpl[utils.wrapperSymbol]

рдирд┐рд░реНрдпрд╛рдд рдХрд┐рдП рдЧрдП iface рдореЗрдВ рдПрдХ рдлрд╝рдВрдХреНрд╢рди convert , рдЬреЛ throw new TypeError( ${context} 'рдлрд╛рдЗрд▓рд▓рд┐рд╕реНрдЯ' рдкреНрд░рдХрд╛рд░ рдХрд╛ рдирд╣реАрдВ рд╣реЛрдЧрд╛ред ); рдЬрдм рдкреНрд░рджрд╛рди рдХреА рдЧрдИ рд╡рд╕реНрддреБ FileList ред рд╣рдо рдЪреАрдЬреЛрдВ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕рдХрд╛ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рдЕрдЧрд░ рд╣рдо рдЗрд╕реЗ рдХрдЪреНрдЪреЗ myFileListImpl рдкрд░ рдХреЙрд▓ рдХрд░рддреЗ рд╣реИрдВ рддреЛ рдпрд╣ рддреНрд░реБрдЯрд┐ рдлреЗрдВрдХрддрд╛ рд╣реИ:

flist.convert(myFileListImpl)

рдЬрдмрдХрд┐ рдКрдкрд░ рдирд┐рдХрд╛рд▓реЗ рдЧрдП wrapper рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рд╣рдо рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рддреНрд░реБрдЯрд┐ рдирд╣реАрдВ рдлреЗрдВрдХрддрд╛ рд╣реИ:

flist.convert(myFileListImpl[utils.wrapperSymbol])

рдЗрд╕рдХреЗ рд╕рд╛рде, рд╣рдо myFileListImpl рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдПрдХ рд╕реНрд╡реАрдХрд╛рд░реНрдп FileList рдСрдмреНрдЬреЗрдХреНрдЯ рд╡рд╛рдкрд╕ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрд╣рд╛рдВ рд╣рдореЗрдВ рдЗрд╕рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдПрдХ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдХрд╛рдо рдХрд┐рдпрд╛ рдЙрджрд╛рд╣рд░рдг (рд╣рдорд╛рд░реЗ рдкрд┐рдЫрд▓реЗ рдХреЛрдб рдХреЗ рдмрдЬрд╛рдп util.wrapperForImpl() рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ):

var _FileList = require('./node_modules/jsdom/lib/jsdom/living/generated/FileList.js')
var utils = require('./node_modules/jsdom/lib/jsdom/living/generated/utils.js')

var myMutableFileListImpl = _FileList.createImpl()

myMutableFileListImpl.length // 0
myMutableFileListImpl.push(new File([], 'a.jpg'))
myMutableFileListImpl.length // 1

var myFileList = utils.wrapperForImpl(myMutableFileListImpl)
_FileList.convert(myFileList) // no error

myFileList.length // 1
myFileList[0] // the File{} object

рдЕрдм рдЙрд╕ рдЬреНрдЮрд╛рди рдХреЗ рд╕рд╛рде, рдореИрдВ рдЕрдкрдиреЗ рдореВрд▓ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб рд╣реИрдХ рдХреЗ jsdom рдкрд░реАрдХреНрд╖рдг рд╕рдВрд╕реНрдХрд░рдг рдХреЛ рд▓рд╛рдЧреВ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ (рдЖрд▓рд╕реНрдп рдХреЗ рд▓рд┐рдП ImmutableJS рдХреЗ рд╢реАрд░реНрд╖ рдкрд░ рд▓рд╛рдЧреВ):

import { Map, Record } from 'immutable'

import jsdomFileList from 'jsdom/lib/jsdom/living/generated/FileList'
import { wrapperForImpl } from 'jsdom/lib/jsdom/living/generated/utils'

// Note: relying on internal API's is super hacky, and will probably break
// As soon as we can, we should use whatever the proper outcome from this issue is:
//   https://github.com/jsdom/jsdom/issues/1272#issuecomment-486088445

export const makeFileList = files => {
  const reducer = (fileListImpl, file) => {
    fileListImpl.push(file)
    return fileListImpl
  }

  const fileListImpl = files.reduce(reducer, jsdomFileList.createImpl())

  return wrapperForImpl(fileListImpl)
}

export class DataTransferStub extends Record({ items: Map() }) {
  get files() {
    return makeFileList(this.items.toList().toArray())
  }
}

export const stubGlobalDataTransfer = () => {
  global.DataTransfer = DataTransferStub
}

export const restoreGlobalDataTransfer = () => {
  global.DataTransfer = undefined
}

рдФрд░ рдлрд┐рд░ рдЗрд╕реЗ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдореЗрд░реЗ рд╡реИрд╢реНрд╡рд┐рдХ рдпреБрджреНрдзреЛрдВ рдореЗрдВ рддрд╛рд░ рджреЗрдВ рддрд╛рдХрд┐ рдореЗрд░реЗ рдПрд╡рд╛ рдкрд░реАрдХреНрд╖рдг рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХреЗрдВ:

import {
  restoreGlobalDataTransfer,
  stubGlobalDataTransfer,
} from ../helpers/jsdom-helpers'

test.before(t => {
  stubGlobalDataTransfer()
})

test.after(t => {
  restoreGlobalDataTransfer()
})

рд╕рднреА рдЖрдзреБрдирд┐рдХ рдмреНрд░рд╛рдЙрдЬрд╝рд░ (рдЕрд░реНрдерд╛рдд IE <= 11 рдирд╣реАрдВ) рдЕрдм рдПрдХ рдлрд╝рд╛рдЗрд▓ рд╕реВрдЪреА рдореЗрдВ input.files рд╕реЗрдЯ рдХрд░рдиреЗ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддреЗ рд╣реИрдВ https://stackoverflow.com/a/47522812/2744776

рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╣рд╛рд▓рд┐рдпрд╛ рд░рд┐рд▓реАрдЬ рдореЗрдВ рдпрд╣ рдмрджрд▓ рдЧрдпрд╛ рд╣реИред рдпрд╣рд╛рдБ рдореЗрд░реЗ рд▓рд┐рдП рдХреНрдпрд╛ рдХрд╛рдо рдХрд┐рдпрд╛ рд╣реИ:

const jsdomUtils = require('jsdom/lib/jsdom/living/generated/utils');
const jsdomFileList = require('jsdom/lib/jsdom/living/generated/FileList');
function makeFileList(...files) {
    const impl = jsdomFileList.createImpl(window);
    const ret = Object.assign([...files], {
        item: (ix) => ret[ix],
        [jsdomUtils.implSymbol]: impl,
    });
    impl[jsdomUtils.wrapperSymbol] = ret;
    Object.setPrototypeOf(ret, FileList.prototype);
    return ret;
}

рдпрджрд┐ рдЖрдк рдЬреЗрд╕реНрдЯ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЬреЗрдПрд╕рдбреАрдУрдПрдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ рдХрд┐ рдкрд░реАрдХреНрд╖рдг рд╡реАрдПрдо рдХреЗ рдмрд╛рд╣рд░ рдЖрдВрддрд░рд┐рдХ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдореИрдВрдиреЗ рдЗрд╕ рддрд░рд╣ рдПрдХ рдХрд╕реНрдЯрдо рдЯреЗрд╕реНрдЯ рдПрдирд╡реА рдмрдирд╛рдпрд╛ рд╣реИ:

const JsdomEnvironment = require('jest-environment-jsdom');

/** See jsdom/jsdom#1272 */
class EnvWithSyntheticFileList extends JsdomEnvironment {
    async setup() {
        await super.setup();
        this.global.jsdomUtils = require('jsdom/lib/jsdom/living/generated/utils');
        this.global.jsdomFileList = require('jsdom/lib/jsdom/living/generated/FileList');
    }
}

module.exports = EnvWithSyntheticFileList;

рддрд╛рдХрд┐ рдореИрдВ 'рдмрд╛рд╣рд░реА' рдЖрдпрд╛рдд рддрдХ рдкрд╣реБрдВрдЪ рд╕рдХреВрдВред

рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╣рд╛рд▓рд┐рдпрд╛ рд░рд┐рд▓реАрдЬ рдореЗрдВ рдпрд╣ рдмрджрд▓ рдЧрдпрд╛ рд╣реИред рдпрд╣рд╛рдБ рдореЗрд░реЗ рд▓рд┐рдП рдХреНрдпрд╛ рдХрд╛рдо рдХрд┐рдпрд╛ рд╣реИ:

const jsdomUtils = require('jsdom/lib/jsdom/living/generated/utils');
const jsdomFileList = require('jsdom/lib/jsdom/living/generated/FileList');
function makeFileList(...files) {
    const impl = jsdomFileList.createImpl(window);
    const ret = Object.assign([...files], {
        item: (ix) => ret[ix],
        [jsdomUtils.implSymbol]: impl,
    });
    impl[jsdomUtils.wrapperSymbol] = ret;
    Object.setPrototypeOf(ret, FileList.prototype);
    return ret;
}

рдпрджрд┐ рдЖрдк рдЬреЗрд╕реНрдЯ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЬреЗрдПрд╕рдбреАрдУрдПрдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ рдХрд┐ рдкрд░реАрдХреНрд╖рдг рд╡реАрдПрдо рдХреЗ рдмрд╛рд╣рд░ рдЖрдВрддрд░рд┐рдХ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдореИрдВрдиреЗ рдЗрд╕ рддрд░рд╣ рдПрдХ рдХрд╕реНрдЯрдо рдЯреЗрд╕реНрдЯ рдПрдирд╡реА рдмрдирд╛рдпрд╛ рд╣реИ:

const JsdomEnvironment = require('jest-environment-jsdom');

/** See jsdom/jsdom#1272 */
class EnvWithSyntheticFileList extends JsdomEnvironment {
    async setup() {
        await super.setup();
        this.global.jsdomUtils = require('jsdom/lib/jsdom/living/generated/utils');
        this.global.jsdomFileList = require('jsdom/lib/jsdom/living/generated/FileList');
    }
}

module.exports = EnvWithSyntheticFileList;

рддрд╛рдХрд┐ рдореИрдВ 'рдмрд╛рд╣рд░реА' рдЖрдпрд╛рдд рддрдХ рдкрд╣реБрдВрдЪ рд╕рдХреВрдВред

рдпрд╣ рдореБрдЭреЗ рдХрд░реАрдм рдорд┐рд▓рд╛ рд▓реЗрдХрд┐рди рдореИрдВ рдЖрдВрддрд░рд┐рдХ рд╕рддреНрдпрд╛рдкрди рд╕реЗ рдЖрдЧреЗ рдирд╣реАрдВ рдмрдврд╝ рд╕рдХрддрд╛:

Exports.is = рдорд╛рди => {
рд╡рд╛рдкрд╕реА utils.isObject(value) && utils.hasOwn(value, implSymbol) && value[implSymbol] instanceof Impl.implementation;
};

рд▓реЗрдЦрди рддреНрд░реБрдЯрд┐: 'HTMLInputElement' рдкрд░ 'рдлрд╝рд╛рдЗрд▓реЗрдВ' рдЧреБрдг рд╕реЗрдЯ рдХрд░рдиреЗ рдореЗрдВ рд╡рд┐рдлрд▓: рдкреНрд░рджрд╛рди рдХрд┐рдпрд╛ рдЧрдпрд╛ рдорд╛рди 'рдлрд╝рд╛рдЗрд▓рд╕реВрдЪреА' рдкреНрд░рдХрд╛рд░ рдХрд╛ рдирд╣реАрдВ рд╣реИред

рдШрдВрдЯреЗ рдмрд┐рддрд╛рдПред рдЕрддрд┐ рдирд┐рд░рд╛рд╢рд╛рдЬрдирдХ

рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╣рд╛рд▓рд┐рдпрд╛ рд░рд┐рд▓реАрдЬ рдореЗрдВ рдпрд╣ рдмрджрд▓ рдЧрдпрд╛ рд╣реИред рдпрд╣рд╛рдБ рдореЗрд░реЗ рд▓рд┐рдП рдХреНрдпрд╛ рдХрд╛рдо рдХрд┐рдпрд╛ рд╣реИ:

const jsdomUtils = require('jsdom/lib/jsdom/living/generated/utils');
const jsdomFileList = require('jsdom/lib/jsdom/living/generated/FileList');
function makeFileList(...files) {
    const impl = jsdomFileList.createImpl(window);
    const ret = Object.assign([...files], {
        item: (ix) => ret[ix],
        [jsdomUtils.implSymbol]: impl,
    });
    impl[jsdomUtils.wrapperSymbol] = ret;
    Object.setPrototypeOf(ret, FileList.prototype);
    return ret;
}

рдпрджрд┐ рдЖрдк рдЬреЗрд╕реНрдЯ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЬреЗрдПрд╕рдбреАрдУрдПрдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ рдХрд┐ рдкрд░реАрдХреНрд╖рдг рд╡реАрдПрдо рдХреЗ рдмрд╛рд╣рд░ рдЖрдВрддрд░рд┐рдХ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдореИрдВрдиреЗ рдЗрд╕ рддрд░рд╣ рдПрдХ рдХрд╕реНрдЯрдо рдЯреЗрд╕реНрдЯ рдПрдирд╡реА рдмрдирд╛рдпрд╛ рд╣реИ:

const JsdomEnvironment = require('jest-environment-jsdom');

/** See jsdom/jsdom#1272 */
class EnvWithSyntheticFileList extends JsdomEnvironment {
    async setup() {
        await super.setup();
        this.global.jsdomUtils = require('jsdom/lib/jsdom/living/generated/utils');
        this.global.jsdomFileList = require('jsdom/lib/jsdom/living/generated/FileList');
    }
}

module.exports = EnvWithSyntheticFileList;

рддрд╛рдХрд┐ рдореИрдВ 'рдмрд╛рд╣рд░реА' рдЖрдпрд╛рдд рддрдХ рдкрд╣реБрдВрдЪ рд╕рдХреВрдВред

рдпрд╣ рдореБрдЭреЗ рдХрд░реАрдм рдорд┐рд▓рд╛ рд▓реЗрдХрд┐рди рдореИрдВ рдЖрдВрддрд░рд┐рдХ рд╕рддреНрдпрд╛рдкрди рд╕реЗ рдЖрдЧреЗ рдирд╣реАрдВ рдмрдврд╝ рд╕рдХрддрд╛:

Exports.is = рдорд╛рди => {
рд╡рд╛рдкрд╕реА utils.isObject(value) && utils.hasOwn(value, implSymbol) && value[implSymbol] instanceof Impl.implementation;
};

рд▓реЗрдЦрди рддреНрд░реБрдЯрд┐: 'HTMLInputElement' рдкрд░ 'рдлрд╝рд╛рдЗрд▓реЗрдВ' рдЧреБрдг рд╕реЗрдЯ рдХрд░рдиреЗ рдореЗрдВ рд╡рд┐рдлрд▓: рдкреНрд░рджрд╛рди рдХрд┐рдпрд╛ рдЧрдпрд╛ рдорд╛рди 'рдлрд╝рд╛рдЗрд▓рд╕реВрдЪреА' рдкреНрд░рдХрд╛рд░ рдХрд╛ рдирд╣реАрдВ рд╣реИред

рдШрдВрдЯреЗ рдмрд┐рддрд╛рдПред рдЕрддрд┐ рдирд┐рд░рд╛рд╢рд╛рдЬрдирдХ

рдПрдХ рдирдП рджрд┐рдорд╛рдЧ рдХреЗ рд╕рд╛рде рдлрд┐рд░ рд╕реЗ рд╢реБрд░реБрдЖрдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рдореБрдЭреЗ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рдкрддрд╛ рдЪрд▓рд╛ред рдХрд┐рд╕реА рддрд░рд╣ рдореЗрд░реЗ рдкрд╛рд╕ 2 рдЕрд▓рдЧ-рдЕрд▓рдЧ jsdom рд╡рд╛рддрд╛рд╡рд░рдг рдЪрд▓ рд░рд╣реЗ рдереЗ рдЬреЛ рдкреНрд░рддреАрдХреЛрдВ рдХреЗ рд╕рдВрджрд░реНрднреЛрдВ рдХреЛ рдлреЗрдВрдХ рджреЗрддреЗ рдереЗред

рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕