Jsdom: كشف بعض طريقة إضافة ملفات إلى قائمة الملفات

تم إنشاؤها على ٢٣ أكتوبر ٢٠١٥  ·  30تعليقات  ·  مصدر: jsdom/jsdom

ملفات FileList ليست قابلة للكتابة في المواصفات ، ولكن لجعل input.files قابلاً للاختبار ، سنحتاج إلى تنفيذ طريقة استخدام لتعديلها.

/ cccpojer

feature

التعليق الأكثر فائدة

تمكنت من إنشاء FileList دون الحاجة إلى تغيير أي من كود مكتبة jsdom:

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());

في هذه الحالة ، أقوم بإنشاء كائن FileList الذي يستدعي المُنشئ في FileList المقدم من jsdom. بعد ذلك أقوم فقط بإضافة ملف إلى تلك القائمة باستخدام تدوين المصفوفة. في حالتي ، أحتاج فقط إلى ملف واحد في مجموعة ولكن يمكن أيضًا تغيير هذا إلى حلقة لإضافة ملفات متعددة إلى FileList. أنا أقوم بإنشاء ملف باسم / نوع / حجم مخصص من خلال مُنشئ الملفات الذي يوفره أيضًا jsdom والوظيفة التي تتبع المواصفات.

قد يكون هذا مفيدًا لشخص يبحث عن كيفية محاكاة FileList في بيئة jsdom ، ولكن لا تزال هناك مشكلة واحدة قائمة. لن يسمح إنشاء FileList بمصفوفة Files باستخدام هذه الطريقة بالحصول على عناصر من المصفوفة باستخدام طريقة 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 بمصفوفة من الكائنات. لكنني أعتقد أن اشتراط أن يكون كائن ملف أمر معقول.

يبدو أنه سيكون من الجيد تحديد الخاصية هنا؟ خصائص DOM قابلة لإعادة التكوين لسبب ...

أفضل إنشاء قائمة ملفات حقيقية ببيانات حقيقية.

يجب أن يكون من الممكن أيضًا الوصول إلى عناصر FileList باستخدام فهارس الصفيف الخاصة بهم. .item ليس الطريقة الوحيدة للوصول إلى حقولهم.

حسنًا ، يبدو أن هناك بعض المشكلات المحتملة:

  • لا يحتوي FileList على عمل وصول مفهرس بشكل صحيح (خطأ)
  • لا توجد طريقة لإنشاء كائنات FileList للاختبار (فجوة ميزات منصة الويب).

لكن تعديل ملفات الإدخال ليس هو المشكلة.

نعم ، أعني أنه ليس من الرائع إخبار المهندسين باستخدام Object.defineProperty على مهمة عادية ولكن يمكنني التعايش معها.

حسنًا ، يجب عليهم القيام بذلك على أي حال في متصفح حقيقي ، لذلك يبدو الأمر معقولًا بالنسبة لي ...

مرحبًا ، أرى أن هذا يزيد عن عام ، أود أن أسأل عما إذا كان هناك أي تقدم تم إحرازه بشأن هذه المشكلة؟ أستخدم إطار عمل Jest لاختبار تطبيق React / Redux الذي يستخدم jsdom داخليًا. لدي مشكلة حيث أحتاج إلى إنشاء FileList ديناميكيًا باستخدام كائن ملف واحد أو أكثر.

بالنظر إلى lib / jsdom / living / filelist.js يمكنني رؤية وجود مُنشئ لـ FileList ولكن لا يوجد أي خيار لتمرير الملفات إليه. أنا أفهم أن FileList و File ليس لديهما مُنشئ وفقًا للمواصفات لأسباب أمنية ولكن هناك أي نية للسماح للمُنشئ بقبول مجموعة من كائنات الملف أو على الأقل طريقة إضافية (دعنا نقول _setItem_) من شأنها أن تسمح لنا بإضافة ملف كائنات في القائمة خصيصا لأغراض الاختبار؟

أرى أيضًا مشكلة أخرى مع FileList. إذا لم أكن مخطئًا في أنه يجب أن يكون كائنًا يشبه Array ، مثل NodeList (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');

هذا الملف الذي تم إنشاؤه لي بخصائص (الحجم ، lastModified ، النوع ...) دون أن أضطر إلى إنشائه يدويًا:

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. لست متأكدا إذا كان ينبغي الإبلاغ عنها.

تمكنت من إنشاء FileList دون الحاجة إلى تغيير أي من كود مكتبة jsdom:

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());

في هذه الحالة ، أقوم بإنشاء كائن FileList الذي يستدعي المُنشئ في FileList المقدم من jsdom. بعد ذلك أقوم فقط بإضافة ملف إلى تلك القائمة باستخدام تدوين المصفوفة. في حالتي ، أحتاج فقط إلى ملف واحد في مجموعة ولكن يمكن أيضًا تغيير هذا إلى حلقة لإضافة ملفات متعددة إلى FileList. أنا أقوم بإنشاء ملف باسم / نوع / حجم مخصص من خلال مُنشئ الملفات الذي يوفره أيضًا jsdom والوظيفة التي تتبع المواصفات.

قد يكون هذا مفيدًا لشخص يبحث عن كيفية محاكاة FileList في بيئة jsdom ، ولكن لا تزال هناك مشكلة واحدة قائمة. لن يسمح إنشاء FileList بمصفوفة Files باستخدام هذه الطريقة بالحصول على عناصر من المصفوفة باستخدام طريقة 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.
هل يمكن لأي شخص مساعدتي في إنشاء كائن FileList؟ لأنني لا أستطيع العثور على أي ارتباط مرجعي في أي مكان في WWW

هذا غير ممكن حاليا.

شكرا دومينيك ،

أحتاج إلى كتابة حالة اختبار لحدث تغيير تحميل الملف. بأي طريقة بديلة لتنفيذ سيناريو الاختبار هذا.

أي تقدم في هذا؟

niksajanjic هل تمكنت من تنفيذ أفضل الحلول المعروضة في هذا الموضوع؟
المرجع: const file = new File('../fixtures/files/test-image.png');
أو شيء مشابه له؟
أفضل

domenic يبدو أن هناك القليل من المعارضة في

@ دومينيك طيب ، لقد أعددت البداية الأساسية لهذا. ليست كل الشيكات موجودة ولكن هذا ما كان يتحدث عنه niksajanjic .

إنشاء ملف

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) || '',
    }
  )
}

addFileList

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 عندما حاول أحد زملائي نسخ هذا الرمز. لذلك ، كان علينا التعليق على اختبارات FileList في تلك المرحلة. من هناك ، لم نتمكن من إيجاد طريقة لكتابة تلك الاختبارات وفي الأشهر القليلة الماضية لم يكن لدى أحد الوقت لإلقاء نظرة أخرى عليها ومحاولة إيجاد طريقة.

niksajanjic شكرا
لا تتردد في إلقاء نظرة واستخدامه إذا كنت تريد ذلك

إنشاء نص برمجي مساعد بسيط يحل هذه المشكلة حتى يأتي مشروع 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;

~ لكن لم يكن واضحًا بالنسبة لي من GitHub أين يمكنني العثور على المصدر الذي ينتهي ببناء ./generated ~

التصدير الرئيسي لحزمة npm هو ./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 الفعلي الذي يدعم FileList المكشوفة في jsdom.

الآن إذا نظرنا إلى ./node_modules/jsdom/lib/jsdom/living/generated/FileList.js فإننا نرى "واجهة برمجة التطبيقات العامة" التي تم إنشاؤها فعليًا والتي انتهى بنا الأمر إلى رؤيتها من خلال الاستخدام العادي ، بما في ذلك كل ما هو مألوف لدينا:

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

يصدر هذا الملف module.exports = iface; ، والذي يحتوي على وظائف أكثر بكثير مما ننتهي إليه من خلال عرض API العام "العادي" ، والذي يستخدم فقط المفتاح 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 هو مجرد غلاف صغير حول setup في iface :

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". ); عندما لا يكون العنصر المقدم هو 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
}

ثم قم بتوصيله يدويًا في vars العالمية الخاصة بي حتى تتمكن اختبارات ava الخاصة بي من استخدامه:

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

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

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

جميع المتصفحات الحديثة (على سبيل المثال ليست IE <= 11) تدعم الآن إعداد ملفات الإدخال إلى قائمة الملفات 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;
}

إذا كنت تستخدم JSDOM عبر Jest ، فعليك التأكد من طلب الأجزاء الداخلية خارج اختبار VM. لقد أنشأت بيئة اختبار مخصصة مثل هذا:

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;
}

إذا كنت تستخدم JSDOM عبر Jest ، فعليك التأكد من طلب الأجزاء الداخلية خارج اختبار VM. لقد أنشأت بيئة اختبار مخصصة مثل هذا:

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;

حتى أتمكن من الوصول إلى الواردات "الخارجية".

لقد جعلني هذا قريبًا ولكن لا يمكنني تجاوز التحقق الداخلي:

الصادرات.is = القيمة => {
return utils.isObject (value) &&
} ؛

TypeError: فشل في تعيين خاصية "files" على "HTMLInputElement": القيمة المقدمة ليست من النوع "FileList".

أمضى ساعات. محبط للغاية

يبدو أن هذا قد تغير في إصدار حديث. إليك ما نجح معي:

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;
}

إذا كنت تستخدم JSDOM عبر Jest ، فعليك التأكد من طلب الأجزاء الداخلية خارج اختبار VM. لقد أنشأت بيئة اختبار مخصصة مثل هذا:

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;

حتى أتمكن من الوصول إلى الواردات "الخارجية".

لقد جعلني هذا قريبًا ولكن لا يمكنني تجاوز التحقق الداخلي:

الصادرات.is = القيمة => {
return utils.isObject (value) &&
} ؛

TypeError: فشل في تعيين خاصية "files" على "HTMLInputElement": القيمة المقدمة ليست من النوع "FileList".

أمضى ساعات. محبط للغاية

بعد أن بدأت مرة أخرى بعقل جديد ، وجدت المشكلة. بطريقة ما كان لدي بيئتان منفصلتان jsdom تعملان والتي تخلصت من الإشارات إلى الرموز.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات