Bug
File class is not shared with window's children.
File class is somehow shared.
instanceof File)describe('Create new File', function() {
it('should has same File class', function() {
const file = new File(/* arguments */);
console.log(file instanceof File); // true
// test runs in new window with different File
doSomethingWithFile(file); // false
});
});
// App code
const doSomethingWithFile = file => console.log(file instanceof File);
Where did I encounter a problem: https://github.com/jaydenseric/extract-files/blob/10236ac78548a3f9c64d148aa79e1444e8dff285/src/index.js#L33
Object.prototype.toString.call(node[key]) === "[object File]" // works
// vendor/extract-files/index.js
// https://github.com/jaydenseric/extract-files/blob/master/src/index.js
// https://github.com/cypress-io/cypress/issues/933
/**
* Checks a node is an enumerable object.
* @param {*} node - A node to check.
* @returns {Boolean} Is the node an enumerable object.
*/
export const isObject = node => typeof node === 'object' && node !== null
/**
* A file extraction.
* @typedef {Object} ExtractedFile
* @property {String} path - Original location in the object tree.
* @property {String} file - The actual file.
*/
/**
* Reversibly extracts files from an object tree.
* @param {object} tree - An object tree to extract files from.
* @param {string} [treePath=''] - Optional tree path to prefix file paths.
* @returns {ExtractedFile[]} Extracted files.
*/
export function extractFiles(tree, treePath = '') {
const files = []
const recurse = (node, nodePath) => {
// Iterate enumerable properties of the node
Object.keys(node).forEach(key => {
// Skip non-object
if (!isObject(node[key])) return
const path = `${nodePath}${key}`
if (
// Node is a File
(typeof File !== 'undefined' &&
Object.prototype.toString.call(node[key]) === '[object File]') ||
// Node is a ReactNativeFile
node[key] instanceof ReactNativeFile
) {
// Extract the file and it's object tree path
files.push({ path, file: node[key] })
// Delete the file. Array items must be deleted without reindexing to
// allow repopulation in a reverse operation.
delete node[key]
// No further checks or recursion
return
}
if (typeof FileList !== 'undefined' && node[key] instanceof FileList)
// Convert read-only FileList to an array for manipulation
node[key] = Array.from(node[key])
// Recurse into child node
recurse(node[key], `${path}.`)
})
}
if (isObject(tree))
// Recurse object tree
recurse(
tree,
// If a tree path was provided, append a dot
treePath === '' ? treePath : `${treePath}.`
)
return files
}
/**
* A React Native FormData file object.
* @see {@link https://github.com/facebook/react-native/blob/v0.45.1/Libraries/Network/FormData.js#L34}
* @typedef {Object} ReactNativeFileObject
* @property {String} uri - File system path.
* @property {String} [type] - File content type.
* @property {String} [name] - File name.
*/
/**
* A React Native file.
*/
export class ReactNativeFile {
/**
* Constructs a new file.
* @param {ReactNativeFileObject} file
* @example
* const file = new ReactNativeFile({
* uri: uriFromCameraRoll,
* type: 'image/jpeg',
* name: 'photo.jpg'
* })
*/
constructor({ uri, type, name }) {
this.uri = uri
this.type = type
this.name = name
}
/**
* Creates an array of file instances.
* @param {ReactNativeFileObject[]} files
* @example
* const files = ReactNativeFile.list([{
* uri: uriFromCameraRoll1,
* type: 'image/jpeg',
* name: 'photo-1.jpg'
* }, {
* uri: uriFromCameraRoll2,
* type: 'image/jpeg',
* name: 'photo-2.jpg'
* }])
*/
static list = files => files.map(file => new ReactNativeFile(file))
}
// package.json (this works only for yarn)
"resolutions": {
"apollo-upload-client/extract-files": "file:./vendor/extract-files"
}
// webpack.config.js
module: {
rules: [
{
test: /\.(js|jsx|mjs)$/,
include: [
path.resolve(__dirname, '../node_modules/extract-files'),
// ...
],
}
]
}
This should be fairly simple to fix: you simply need to instantiate Files from your application's window, and not from the test spec window.
// nope
// this is using the global window in the test spec
new File()
cy.window().then((win) => {
// yup
// this is using the File constructor from the application window
new win.File()
})
This isn't related to Windows OS. It affects all usecases where File/Blob/Filelist instances are created in cypress test files. I use MacOS, for example.
I've added comment to recently updated issue: https://github.com/cypress-io/cypress/issues/170#issuecomment-442843559
Most helpful comment
This should be fairly simple to fix: you simply need to instantiate Files from your application's window, and not from the test spec window.