FileListã¯ä»æ§ã«æžã蟌ãããšã¯ã§ããŸãããã input.files
ãã¹ãå¯èœã«ããã«ã¯ãutilã¡ãœãããå®è£
ããŠå€æŽããå¿
èŠããããŸãã
/ cc @cpojer
input.files = createFileList(file1, file2, ...)
ãããã§ãããã
@cpojerããã«å
¥ããå®éã®File
ãªããžã§ã¯ããçæããŠããŸããïŒ
input.files
æžã蟌ã¿å¯èœã«ããã®ã¯ããããæªãããšã§ãããããããçã®é
åãè¿ããŠèªåã§åãããã fillFileList(input.files, [file])
ãããªããšãããããšãã§ããŸãã
å®éã«ã¯ã¢ãã¯ããŒã¿ã®ã¿ã䜿çšããããã .files
ã«ãªããžã§ã¯ãã®é
åãå
¥åããŸãã ãããããããFileãªããžã§ã¯ãã§ããå¿
èŠãããã®ã¯ãåççã ãšæããŸãã
ããã§ã¯definePropertyã§åé¡ãªãããã§ãã DOMããããã£ã¯æ¬¡ã®çç±ã§åæ§æå¯èœã§ã...
ãã ããå®éã®ããŒã¿ã䜿çšããŠå®éã®FileListãäœæããããšæããŸãã
é
åã€ã³ããã¯ã¹ã䜿çšããŠFileListã¢ã€ãã ã«ã¢ã¯ã»ã¹ããããšãå¯èœã§ããå¿
èŠããããŸãã .item
ã¯ããã£ãŒã«ãã«ã¢ã¯ã»ã¹ããå¯äžã®æ¹æ³ã§ã¯ãããŸããã
OKãããã§ããã€ãã®æœåšçãªåé¡ãããããã«èãããŸãïŒ
ãã ããinputEl.filesã®å€æŽã¯åé¡ã§ã¯ãããŸããã
ããããšã³ãžãã¢ã«éåžžã®å²ãåœãŠã§Object.definePropertyã䜿çšããããã«æ瀺ããã®ã¯çŽ æŽãããããšã§ã¯ãããŸããããç§ã¯ãããšäžç·ã«æ®ããããšãã§ããŸãã
ãŸãããšã«ããå®éã®ãã©ãŠã¶ã§ãããããªããã°ãªããªãã®ã§ãããã¯ç§ã«ã¯åççã ãšæããŸã...
ããã«ã¡ã¯ãããã¯1幎以äžåã®ãã®ã ãšæããŸããããã®åé¡ã«é¢ããŠäœãé²å±ããã£ããã©ããå°ããããšæããŸãã Jestãã¬ãŒã ã¯ãŒã¯ã䜿çšããŠãå éšã§jsdomã䜿çšããReact / Reduxã¢ããªããã¹ãããŸãã 1ã€ä»¥äžã®Fileãªããžã§ã¯ãã䜿çšããŠFileListãåçã«äœæããå¿ èŠããããšããåé¡ããããŸãã
lib / jsdom / living / filelist.jsãèŠããšãFileListã®ã³ã³ã¹ãã©ã¯ã¿ãŒãããããšãããããŸããããã¡ã€ã«ãæž¡ããªãã·ã§ã³ã¯ãããŸããã FileListãšFileã«ã¯ã»ãã¥ãªãã£äžã®çç±ããä»æ§ã«åŸã£ãã³ã³ã¹ãã©ã¯ã¿ãŒããªãããšã¯ç解ããŠããŸãããã³ã³ã¹ãã©ã¯ã¿ãŒãFileãªããžã§ã¯ãã®é åããŸãã¯å°ãªããšãFileãè¿œå ã§ããè¿œå ã®ã¡ãœããïŒããšãã°_setItem_ïŒãåãå ¥ããããšãèš±å¯ããæå³ã¯ãããŸããïŒç¹ã«ãã¹ãç®çã§ãªããžã§ã¯ãããªã¹ãã«è¿œå ããŸããïŒ
FileListã«é¢ãããã1ã€ã®åé¡ããããŸãã 誀解ããªãéããNodeListïŒlib / jsdom / living / node-list.jsïŒãšåãããã«ãé åã®ãããªãªããžã§ã¯ãã§ããå¿ èŠããããŸããã€ãŸãã次ã®2ã€ã®æ¹æ³ã§Fileãªããžã§ã¯ãã«ã¢ã¯ã»ã¹ã§ããå¯èœæ§ããããŸãã
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.ïŒæååãšããŠæäŸããããã¹ã䜿çšããŠå®éã®ãã¡ã€ã«ããFileãªããžã§ã¯ããäœæããããã¹ãç®çã§Fileã³ã³ã¹ãã©ã¯ã¿ãŒãè¿œå ããããšã¯æçã§ããããïŒ ãããèš±å¯ããã©ã€ãã©ãªãèŠã€ããŸããïŒç³ãèš³ãããŸãããããªã³ã¯ãèŠã€ãããŸããïŒïŒ
const file = new File('../fixtures/files/test-image.png');
ããã«ãããæåã§äœæããªããŠããããããã£ïŒsizeãlastModifiedãtype ...ïŒã䜿çšããŠãã¡ã€ã«ãäœæãããŸããã
const file = new File([''], 'test-image.png', {
lastModified: 1449505890000,
lastModifiedDate: new Date(1449505890000),
name: "ecp-logo.png",
size: 44320,
type: "image/png",
});
ãã®ã©ã€ãã©ãªãã©ã®ããã«æ©èœãããã¯ããããŸãããã1幎以äžã¡ã³ããã³ã¹ãããŠãããã䜿çšããããŸããã ããèŠã€ãããªãããã§ãã
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ã€ã ãã§ããããããforã«ãŒãã«å€æŽããŠãFileListã«è€æ°ã®ãã¡ã€ã«ãè¿œå ããããšãã§ããŸãã jsdomãæäŸããFileã³ã³ã¹ãã©ã¯ã¿ãŒã䜿çšããŠãã«ã¹ã¿ã ã®åå/ã¿ã€ã/ãµã€ãºã§ãã¡ã€ã«ãäœæããŠããŸãããã®æ©èœã¯ä»æ§ã«åŸã£ãŠããŸãã
ããã¯ãjsdomç°å¢ã§FileListãã¢ãã¯ããæ¹æ³ãæ¢ããŠãã人ã«ã¯åœ¹ç«ã€ãããããŸãããã1ã€ã®åé¡ããŸã æ®ã£ãŠããŸãã ãã®ã¡ãœããã䜿çšããŠãã¡ã€ã«ã®é åã䜿çšããŠ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ããããã®æ©èœããã¹ãç®çã§ããã«æäŸã§ããã°ãããã§ãè¯ããšæããŸãã
ããã«ã¡ã¯ãã¿ã㪠ã
FileListãè¿ã$ïŒ "ïŒselectorID of Upload file"ïŒ[0] .files [0]ãªããžã§ã¯ããã¢ãã¯ããŠãããšãã«ãããã€ãã®åé¡ã«çŽé¢ããŠããŸãã
誰ããFileListãªããžã§ã¯ãã®äœæãæäŒã£ãŠãããŸããïŒ WWWã®ã©ãã«ãåç
§ãªã³ã¯ãèŠã€ãããªããã
çŸåšã¯ã§ããŸããã
Domenicã«æè¬ããŸãã
ãã¡ã€ã«ã¢ããããŒãå€æŽã€ãã³ãã®ãã¹ãã±ãŒã¹ãäœæããå¿ èŠããããŸãã ãã®ãã¹ãã·ããªãªãå®è¡ããå¥ã®æ¹æ³ã
ããã«ã€ããŠäœãé²å±ã¯ãããŸããïŒ
@niksajanjicãã®ã¹ã¬ããã§æ瀺ãããæè¯ã®ãœãªã¥ãŒã·ã§ã³ãå®è£
ããããšã«
åç
§ïŒ const file = new File('../fixtures/files/test-image.png');
ãŸãã¯ããã«äŒŒããã®ïŒ
äžçª
@domenicãã®åé¡ã«é¢ããTwitterã®æçš¿ã«ã¯å°ãç°è°ãããããã§ã
@domenicããããŸãããããã®åºæ¬çãªã¹ã¿ãŒããèšå®ããŸããã ãã¹ãŠã®ãã§ãã¯ãããã«ããããã§ã¯ãããŸããããããã¯æ¬è³ªçã«@niksajanjicã話ããŠãããã®ã§ãã
createFile
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åŸã®æçš¿ã§èª¬æããæ¹æ³ã§ãã¹ããè¡ããŸããã æ®å¿µãªãããæ°ãæåŸãååã®1人ããã®ã³ãŒããã³ããŒããããšãããšãã«ãæ°ããããŒãžã§ã³ã®jsdomã§ã®äœæ¥ãåæ¢ããŸããã ãã®ããããã®æç¹ã§FileListã®ãã¹ããã³ã¡ã³ãã¢ãŠãããå¿ èŠããããŸããã ãããããç§ãã¡ã¯ãããã®ãã¹ããæžãæ¹æ³ãèŠã€ããããšãã§ãããéå»æ°ã¶æéã誰ãããããââãäžåºŠèŠãŠãæ¹æ³ãèŠã€ããããšãè©Šã¿ãæéããããŸããã§ããã
@niksajanjicæŽæ°ããŠããã ãããããšãããããŸãã ç§ã¯ããªããææ¡ãããœãªã¥ãŒã·ã§ã³ã«åãçµãã§ãããããã¯æ©èœããŠããããã§ãïŒäžèšã®ã³ãŒããåç
§ïŒããè¿œå æ¹æ³ãç解ããã®ã¯éåžžã«é£ãããããjsdomã«è¿œå ãããå¯èœæ§ã¯äœããšæããŸãã
å¿
èŠã«å¿ããŠããæ°è»œã«ã芧ã«ãªãããå©çšãã ããã
jsdomãããžã§ã¯ãã解決çãèŠã€ãããŸã§ããã®åé¡ã解決ããç°¡åãªãã«ããŒã¹ã¯ãªãããäœæããŸããã
https://bitbucket.org/william_rusnack/addfilelist/src/master/
1ã€ã®ãã¡ã€ã«ãè¿œå ããŸãã
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
`` `javascript
const {addFileList} = requireïŒ '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
ãåãåãé¢æ°ãäœæããjestã䜿çšããŠãã®åäœãã¹ããäœæããããšèããŸããã 以äžã®ãã«ããŒé¢æ°ã䜿çšããŠãé¢æ°ãæäœããã®ã«ååãª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 ïŒ
æ®å¿µãªããã jsdom
ã¯å®éã«DataTransfer
ãŸã
ãã®ä»ã®åèæç®ïŒ
ãœãŒã¹ãå°ãæ€çŽ¢ãããšã exports.FileList = require("./generated/FileList").interface;
èŠã€ãããŸãã
ãããããGitHubããã¯ãæçµçã«./generated
æ§ç¯ãããœãŒã¹ãã©ãã§èŠã€ããããæ確ã§ã¯ãããŸãã
yarn prepare
ïŒ https ïŒ yarn convert-idl
ïŒ https ïŒ npmããã±ãŒãžã®äž»ãªãšã¯ã¹ããŒãã¯./lib/api.js
ã§ãéåžžã«å°ããªãããªãã¯APIããšã¯ã¹ããŒãããŸãã
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ã«ã¯ã FileList
apiãããã¯ã¢ããããå®éã®JSå®è£
ãå«ãŸããŠããŸãã
ããã§ã ./node_modules/jsdom/lib/jsdom/living/generated/FileList.js
ãèŠããšãå®éã«çæãããããããªãã¯APIãã衚瀺ãããŸããããã¯ã䜿ãæ
£ãããã®ãå«ããéåžžã®äœ¿çšæ³ã§ç¢ºèªã§ããŸãã
class FileList {
constructor() {
throw new TypeError("Illegal constructor");
}
ãã®ãã¡ã€ã«ã¯module.exports = iface;
ãšã¯ã¹ããŒãããŸããããã«ã¯ã iface.interface
ããŒã®ã¿ã䜿çšãããéåžžã®ããããªãã¯APIå
¬éã«ãã£ãŠåŸãããæ©èœãããã¯ããã«å€ãã®æ©èœãå«ãŸããŠããŸãã ãããã£ãŠã 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);
},
ã³ã³ãœãŒã«ã§ãããããã£ãŠã¿ããšã FileListImpl
ããµããŒãããŠããArray
èŠçŽ ã®è¡šçŸåè±ããªAPIãããããã§ãã ãããã£ãŠã次ã®ãããªããšãã§ããŸãã
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
ãªãå Žåã );
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
}
ãããŠããããæåã§ã°ããŒãã«å€æ°ã«ã¯ã€ã€ãªã³ã°ããŠã avaãã¹ãã§äœ¿çšã§ããããã«ããŸãã
import {
restoreGlobalDataTransfer,
stubGlobalDataTransfer,
} from ../helpers/jsdom-helpers'
test.before(t => {
stubGlobalDataTransfer()
})
test.after(t => {
restoreGlobalDataTransfer()
})
ææ°ã®ãã©ãŠã¶ïŒIE <= 11以å€ïŒã¯ãã¹ãŠãinput.filesãFileListã«èšå®ããããšããµããŒãããããã«ãªããŸãã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;
}
Jestçµç±ã§JSDOMã䜿çšããŠããå Žåã¯ããã¹ã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; }
Jestçµç±ã§JSDOMã䜿çšããŠããå Žåã¯ããã¹ã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;
'å€éš'ã€ã³ããŒãã«ã¢ã¯ã»ã¹ã§ããããã«ããŸãã
ããã¯ç§ãè¿ã¥ããŸããããå éšæ€èšŒãééããããšã¯ã§ããŸããïŒ
exports.is = value => {
return utils.isObjectïŒvalueïŒ&& utils.hasOwnïŒvalueãimââplSymbolïŒ&& value [implSymbol] instanceof Impl.implementation;
};
TypeErrorïŒãHTMLInputElementãã®ãfilesãããããã£ã®èšå®ã«å€±æããŸããïŒæå®ãããå€ã¯ã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; }
Jestçµç±ã§JSDOMã䜿çšããŠããå Žåã¯ããã¹ã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;
'å€éš'ã€ã³ããŒãã«ã¢ã¯ã»ã¹ã§ããããã«ããŸãã
ããã¯ç§ãè¿ã¥ããŸããããå éšæ€èšŒãééããããšã¯ã§ããŸããïŒ
exports.is = value => {
return utils.isObjectïŒvalueïŒ&& utils.hasOwnïŒvalueãimââplSymbolïŒ&& value [implSymbol] instanceof Impl.implementation;
};TypeErrorïŒãHTMLInputElementãã®ãfilesãããããã£ã®èšå®ã«å€±æããŸããïŒæå®ãããå€ã¯ãFileListãã¿ã€ãã§ã¯ãããŸããã
éãããæéã è¶ ã€ã©ã€ã©ãã
æ°é®®ãªè³ã§åã³å§ããåŸãç§ã¯åé¡ãèŠã€ããŸããã ã©ãããããããã·ã³ãã«ãžã®åç §ãç Žæ£ãã2ã€ã®å¥ã ã®jsdomç°å¢ãå®è¡ããŠããŸããã
æãåèã«ãªãã³ã¡ã³ã
jsdomã©ã€ãã©ãªã³ãŒããå€æŽããã«FileListãäœæã§ããŸããã
ãã®å ŽåãjsdomãæäŸããFileListã§ã³ã³ã¹ãã©ã¯ã¿ãŒãåŒã³åºãFileListãªããžã§ã¯ããäœæããŠããŸãã ãã®åŸãé åè¡šèšã䜿çšããŠãã®ãªã¹ãã«ãã¡ã€ã«ãè¿œå ããŸãã ç§ã®å Žåãé åã«å¿ èŠãªãã¡ã€ã«ã¯1ã€ã ãã§ããããããforã«ãŒãã«å€æŽããŠãFileListã«è€æ°ã®ãã¡ã€ã«ãè¿œå ããããšãã§ããŸãã jsdomãæäŸããFileã³ã³ã¹ãã©ã¯ã¿ãŒã䜿çšããŠãã«ã¹ã¿ã ã®åå/ã¿ã€ã/ãµã€ãºã§ãã¡ã€ã«ãäœæããŠããŸãããã®æ©èœã¯ä»æ§ã«åŸã£ãŠããŸãã
ããã¯ãjsdomç°å¢ã§FileListãã¢ãã¯ããæ¹æ³ãæ¢ããŠãã人ã«ã¯åœ¹ç«ã€ãããããŸãããã1ã€ã®åé¡ããŸã æ®ã£ãŠããŸãã ãã®ã¡ãœããã䜿çšããŠãã¡ã€ã«ã®é åã䜿çšããŠFileListãäœæãããšãFileList.itemïŒindexïŒã¡ãœããã䜿çšããŠé åããã¢ã€ãã ãååŸããããšã¯ã§ããŸããã ããããããã§ãã次ã®ãããªã¡ãœããããªãŒããŒã©ã€ãããããšã§ä¿®æ£ã§ããŸãã
jsdomããããã®æ©èœããã¹ãç®çã§ããã«æäŸã§ããã°ãããã§ãè¯ããšæããŸãã