standard.js style
This commit is contained in:
@@ -1,444 +1,442 @@
|
||||
import fs from 'fs';
|
||||
import {Readable} from 'stream';
|
||||
import buffer from 'buffer';
|
||||
import test from 'ava';
|
||||
import {Response} from 'node-fetch';
|
||||
import syncBlob, {blobFromSync, blobFrom, fileFromSync, fileFrom} from './from.js';
|
||||
import File from './file.js';
|
||||
import Blob from './index.js';
|
||||
import fs from 'fs'
|
||||
import { Readable } from 'stream'
|
||||
import buffer from 'buffer'
|
||||
import test from 'ava'
|
||||
import { Response } from 'node-fetch'
|
||||
import syncBlob, { blobFromSync, blobFrom, fileFromSync, fileFrom } from './from.js'
|
||||
import File from './file.js'
|
||||
import Blob from './index.js'
|
||||
|
||||
const license = fs.readFileSync('./LICENSE', 'utf-8');
|
||||
const license = fs.readFileSync('./LICENSE', 'utf-8')
|
||||
|
||||
test('new Blob()', t => {
|
||||
const blob = new Blob(); // eslint-disable-line no-unused-vars
|
||||
t.pass();
|
||||
});
|
||||
const blob = new Blob() // eslint-disable-line no-unused-vars
|
||||
t.pass()
|
||||
})
|
||||
|
||||
test('new Blob(parts)', t => {
|
||||
const data = 'a=1';
|
||||
const blob = new Blob([data]); // eslint-disable-line no-unused-vars
|
||||
t.pass();
|
||||
});
|
||||
const data = 'a=1'
|
||||
const blob = new Blob([data]) // eslint-disable-line no-unused-vars
|
||||
t.pass()
|
||||
})
|
||||
|
||||
test('Blob ctor parts', async t => {
|
||||
const parts = [
|
||||
'a',
|
||||
new Uint8Array([98]),
|
||||
new Uint16Array([25699]),
|
||||
new Uint8Array([101]).buffer,
|
||||
Buffer.from('f'),
|
||||
new Blob(['g']),
|
||||
{},
|
||||
new URLSearchParams('foo')
|
||||
];
|
||||
const parts = [
|
||||
'a',
|
||||
new Uint8Array([98]),
|
||||
new Uint16Array([25699]),
|
||||
new Uint8Array([101]).buffer,
|
||||
Buffer.from('f'),
|
||||
new Blob(['g']),
|
||||
{},
|
||||
new URLSearchParams('foo')
|
||||
]
|
||||
|
||||
const blob = new Blob(parts);
|
||||
t.is(await blob.text(), 'abcdefg[object Object]foo=');
|
||||
});
|
||||
const blob = new Blob(parts)
|
||||
t.is(await blob.text(), 'abcdefg[object Object]foo=')
|
||||
})
|
||||
|
||||
test('Blob ctor threats an object with @@iterator as a sequence', async t => {
|
||||
const blob = new Blob({[Symbol.iterator]: Array.prototype[Symbol.iterator]});
|
||||
const blob = new Blob({ [Symbol.iterator]: Array.prototype[Symbol.iterator] })
|
||||
|
||||
t.is(blob.size, 0);
|
||||
t.is(await blob.text(), '');
|
||||
});
|
||||
t.is(blob.size, 0)
|
||||
t.is(await blob.text(), '')
|
||||
})
|
||||
|
||||
test('Blob ctor reads blob parts from object with @@iterator', async t => {
|
||||
const input = ['one', 'two', 'three'];
|
||||
const expected = input.join('');
|
||||
const input = ['one', 'two', 'three']
|
||||
const expected = input.join('')
|
||||
|
||||
const blob = new Blob({
|
||||
* [Symbol.iterator]() {
|
||||
yield * input;
|
||||
}
|
||||
});
|
||||
const blob = new Blob({
|
||||
* [Symbol.iterator] () {
|
||||
yield * input
|
||||
}
|
||||
})
|
||||
|
||||
t.is(blob.size, new TextEncoder().encode(expected).byteLength);
|
||||
t.is(await blob.text(), expected);
|
||||
});
|
||||
t.is(blob.size, new TextEncoder().encode(expected).byteLength)
|
||||
t.is(await blob.text(), expected)
|
||||
})
|
||||
|
||||
test('Blob ctor throws a string', t => {
|
||||
t.throws(() => new Blob('abc'), {
|
||||
instanceOf: TypeError,
|
||||
message: 'Failed to construct \'Blob\': The provided value cannot be converted to a sequence.'
|
||||
});
|
||||
});
|
||||
t.throws(() => new Blob('abc'), {
|
||||
instanceOf: TypeError,
|
||||
message: 'Failed to construct \'Blob\': The provided value cannot be converted to a sequence.'
|
||||
})
|
||||
})
|
||||
|
||||
test('Blob ctor throws an error for an object that does not have @@iterable method', t => {
|
||||
t.throws(() => new Blob({}), {
|
||||
instanceOf: TypeError,
|
||||
message: 'Failed to construct \'Blob\': The object must have a callable @@iterator property.'
|
||||
});
|
||||
});
|
||||
t.throws(() => new Blob({}), {
|
||||
instanceOf: TypeError,
|
||||
message: 'Failed to construct \'Blob\': The object must have a callable @@iterator property.'
|
||||
})
|
||||
})
|
||||
|
||||
test('Blob ctor threats Uint8Array as a sequence', async t => {
|
||||
const input = [1, 2, 3];
|
||||
const blob = new Blob(new Uint8Array(input));
|
||||
const input = [1, 2, 3]
|
||||
const blob = new Blob(new Uint8Array(input))
|
||||
|
||||
t.is(await blob.text(), input.join(''));
|
||||
});
|
||||
t.is(await blob.text(), input.join(''))
|
||||
})
|
||||
|
||||
test('Blob size', t => {
|
||||
const data = 'a=1';
|
||||
const blob = new Blob([data]);
|
||||
t.is(blob.size, data.length);
|
||||
});
|
||||
const data = 'a=1'
|
||||
const blob = new Blob([data])
|
||||
t.is(blob.size, data.length)
|
||||
})
|
||||
|
||||
test('Blob type', t => {
|
||||
const type = 'text/plain';
|
||||
const blob = new Blob([], {type});
|
||||
t.is(blob.type, type);
|
||||
});
|
||||
const type = 'text/plain'
|
||||
const blob = new Blob([], { type })
|
||||
t.is(blob.type, type)
|
||||
})
|
||||
|
||||
test('Blob slice type', t => {
|
||||
const type = 'text/plain';
|
||||
const blob = new Blob().slice(0, 0, type);
|
||||
t.is(blob.type, type);
|
||||
});
|
||||
const type = 'text/plain'
|
||||
const blob = new Blob().slice(0, 0, type)
|
||||
t.is(blob.type, type)
|
||||
})
|
||||
|
||||
test('invalid Blob type', t => {
|
||||
const blob = new Blob([], {type: '\u001Ftext/plain'});
|
||||
t.is(blob.type, '');
|
||||
});
|
||||
const blob = new Blob([], { type: '\u001Ftext/plain' })
|
||||
t.is(blob.type, '')
|
||||
})
|
||||
|
||||
test('invalid Blob slice type', t => {
|
||||
const blob = new Blob().slice(0, 0, '\u001Ftext/plain');
|
||||
t.is(blob.type, '');
|
||||
});
|
||||
const blob = new Blob().slice(0, 0, '\u001Ftext/plain')
|
||||
t.is(blob.type, '')
|
||||
})
|
||||
|
||||
test('Blob text()', async t => {
|
||||
const data = 'a=1';
|
||||
const type = 'text/plain';
|
||||
const blob = new Blob([data], {type});
|
||||
t.is(await blob.text(), data);
|
||||
});
|
||||
const data = 'a=1'
|
||||
const type = 'text/plain'
|
||||
const blob = new Blob([data], { type })
|
||||
t.is(await blob.text(), data)
|
||||
})
|
||||
|
||||
test('Blob arrayBuffer()', async t => {
|
||||
const data = 'a=1';
|
||||
const type = 'text/plain';
|
||||
const blob = new Blob([data], {type});
|
||||
const data = 'a=1'
|
||||
const type = 'text/plain'
|
||||
const blob = new Blob([data], { type })
|
||||
|
||||
const decoder = new TextDecoder('utf-8');
|
||||
const buffer = await blob.arrayBuffer();
|
||||
t.is(decoder.decode(buffer), data);
|
||||
});
|
||||
const decoder = new TextDecoder('utf-8')
|
||||
const buffer = await blob.arrayBuffer()
|
||||
t.is(decoder.decode(buffer), data)
|
||||
})
|
||||
|
||||
test('Blob stream()', async t => {
|
||||
const data = 'a=1';
|
||||
const type = 'text/plain';
|
||||
const blob = new Blob([data], {type});
|
||||
const data = 'a=1'
|
||||
const type = 'text/plain'
|
||||
const blob = new Blob([data], { type })
|
||||
|
||||
for await (const chunk of blob.stream()) {
|
||||
t.is(chunk.join(), [97, 61, 49].join());
|
||||
}
|
||||
});
|
||||
for await (const chunk of blob.stream()) {
|
||||
t.is(chunk.join(), [97, 61, 49].join())
|
||||
}
|
||||
})
|
||||
|
||||
test('Blob stream() can be cancelled', async t => {
|
||||
const stream = new Blob(['Some content']).stream();
|
||||
const stream = new Blob(['Some content']).stream()
|
||||
|
||||
// Cancel the stream before start reading, or this will throw an error
|
||||
await stream.cancel();
|
||||
// Cancel the stream before start reading, or this will throw an error
|
||||
await stream.cancel()
|
||||
|
||||
const reader = stream.getReader();
|
||||
const reader = stream.getReader()
|
||||
|
||||
const {done, value: chunk} = await reader.read();
|
||||
const { done, value: chunk } = await reader.read()
|
||||
|
||||
t.true(done);
|
||||
t.is(chunk, undefined);
|
||||
});
|
||||
t.true(done)
|
||||
t.is(chunk, undefined)
|
||||
})
|
||||
|
||||
test('Blob toString()', t => {
|
||||
const data = 'a=1';
|
||||
const type = 'text/plain';
|
||||
const blob = new Blob([data], {type});
|
||||
t.is(blob.toString(), '[object Blob]');
|
||||
});
|
||||
const data = 'a=1'
|
||||
const type = 'text/plain'
|
||||
const blob = new Blob([data], { type })
|
||||
t.is(blob.toString(), '[object Blob]')
|
||||
})
|
||||
|
||||
test('Blob slice()', async t => {
|
||||
const data = 'abcdefgh';
|
||||
const blob = new Blob([data]).slice();
|
||||
t.is(await blob.text(), data);
|
||||
});
|
||||
const data = 'abcdefgh'
|
||||
const blob = new Blob([data]).slice()
|
||||
t.is(await blob.text(), data)
|
||||
})
|
||||
|
||||
test('Blob slice(0, 1)', async t => {
|
||||
const data = 'abcdefgh';
|
||||
const blob = new Blob([data]).slice(0, 1);
|
||||
t.is(await blob.text(), 'a');
|
||||
});
|
||||
const data = 'abcdefgh'
|
||||
const blob = new Blob([data]).slice(0, 1)
|
||||
t.is(await blob.text(), 'a')
|
||||
})
|
||||
|
||||
test('Blob slice(-1)', async t => {
|
||||
const data = 'abcdefgh';
|
||||
const blob = new Blob([data]).slice(-1);
|
||||
t.is(await blob.text(), 'h');
|
||||
});
|
||||
const data = 'abcdefgh'
|
||||
const blob = new Blob([data]).slice(-1)
|
||||
t.is(await blob.text(), 'h')
|
||||
})
|
||||
|
||||
test('Blob slice(0, -1)', async t => {
|
||||
const data = 'abcdefgh';
|
||||
const blob = new Blob([data]).slice(0, -1);
|
||||
t.is(await blob.text(), 'abcdefg');
|
||||
});
|
||||
const data = 'abcdefgh'
|
||||
const blob = new Blob([data]).slice(0, -1)
|
||||
t.is(await blob.text(), 'abcdefg')
|
||||
})
|
||||
|
||||
test('Blob(["hello ", "world"]).slice(5)', async t => {
|
||||
const parts = ['hello ', 'world'];
|
||||
const blob = new Blob(parts);
|
||||
t.is(await blob.slice(5).text(), ' world');
|
||||
});
|
||||
const parts = ['hello ', 'world']
|
||||
const blob = new Blob(parts)
|
||||
t.is(await blob.slice(5).text(), ' world')
|
||||
})
|
||||
|
||||
test('throw away unwanted parts', async t => {
|
||||
const blob = new Blob(['a', 'b', 'c']).slice(1, 2);
|
||||
t.is(await blob.text(), 'b');
|
||||
});
|
||||
const blob = new Blob(['a', 'b', 'c']).slice(1, 2)
|
||||
t.is(await blob.text(), 'b')
|
||||
})
|
||||
|
||||
test('Blob works with node-fetch Response.blob()', async t => {
|
||||
const data = 'a=1';
|
||||
const type = 'text/plain';
|
||||
const blob = new Blob([data], {type});
|
||||
const response = new Response(Readable.from(blob.stream()));
|
||||
const blob2 = await response.blob();
|
||||
t.is(await blob2.text(), data);
|
||||
});
|
||||
const data = 'a=1'
|
||||
const type = 'text/plain'
|
||||
const blob = new Blob([data], { type })
|
||||
const response = new Response(Readable.from(blob.stream()))
|
||||
const blob2 = await response.blob()
|
||||
t.is(await blob2.text(), data)
|
||||
})
|
||||
|
||||
test('Blob works with node-fetch Response.text()', async t => {
|
||||
const data = 'a=1';
|
||||
const type = 'text/plain';
|
||||
const blob = new Blob([data], {type});
|
||||
const response = new Response(Readable.from(blob.stream()));
|
||||
const text = await response.text();
|
||||
t.is(text, data);
|
||||
});
|
||||
const data = 'a=1'
|
||||
const type = 'text/plain'
|
||||
const blob = new Blob([data], { type })
|
||||
const response = new Response(Readable.from(blob.stream()))
|
||||
const text = await response.text()
|
||||
t.is(text, data)
|
||||
})
|
||||
|
||||
test('blob part backed up by filesystem', async t => {
|
||||
const blob = blobFromSync('./LICENSE');
|
||||
t.is(await blob.slice(0, 3).text(), license.slice(0, 3));
|
||||
t.is(await blob.slice(4, 11).text(), license.slice(4, 11));
|
||||
});
|
||||
const blob = blobFromSync('./LICENSE')
|
||||
t.is(await blob.slice(0, 3).text(), license.slice(0, 3))
|
||||
t.is(await blob.slice(4, 11).text(), license.slice(4, 11))
|
||||
})
|
||||
|
||||
test('Reading after modified should fail', async t => {
|
||||
const blob = blobFromSync('./LICENSE');
|
||||
await new Promise(resolve => {
|
||||
setTimeout(resolve, 500);
|
||||
});
|
||||
fs.closeSync(fs.openSync('./LICENSE', 'a'));
|
||||
const error = await t.throwsAsync(blob.text());
|
||||
t.is(error.constructor.name, 'DOMException');
|
||||
t.is(error instanceof Error, true);
|
||||
t.is(error.name, 'NotReadableError');
|
||||
const blob = blobFromSync('./LICENSE')
|
||||
await new Promise(resolve => {
|
||||
setTimeout(resolve, 500)
|
||||
})
|
||||
fs.closeSync(fs.openSync('./LICENSE', 'a'))
|
||||
const error = await t.throwsAsync(blob.text())
|
||||
t.is(error.constructor.name, 'DOMException')
|
||||
t.is(error instanceof Error, true)
|
||||
t.is(error.name, 'NotReadableError')
|
||||
|
||||
const file = fileFromSync('./LICENSE');
|
||||
// Above test updates the last modified date to now
|
||||
t.is(typeof file.lastModified, 'number');
|
||||
// The lastModifiedDate is deprecated and removed from spec
|
||||
t.false('lastModifiedDate' in file);
|
||||
const mod = file.lastModified - Date.now();
|
||||
t.true(mod <= 0 && mod >= -500); // Close to tolerance: 0.500ms
|
||||
});
|
||||
const file = fileFromSync('./LICENSE')
|
||||
// Above test updates the last modified date to now
|
||||
t.is(typeof file.lastModified, 'number')
|
||||
// The lastModifiedDate is deprecated and removed from spec
|
||||
t.false('lastModifiedDate' in file)
|
||||
const mod = file.lastModified - Date.now()
|
||||
t.true(mod <= 0 && mod >= -500) // Close to tolerance: 0.500ms
|
||||
})
|
||||
|
||||
test('Reading file after modified should fail', async t => {
|
||||
const file = fileFromSync('./LICENSE');
|
||||
await new Promise(resolve => {
|
||||
setTimeout(resolve, 100);
|
||||
});
|
||||
const now = new Date();
|
||||
// Change modified time
|
||||
fs.utimesSync('./LICENSE', now, now);
|
||||
const error = await t.throwsAsync(file.text());
|
||||
t.is(error.constructor.name, 'DOMException');
|
||||
t.is(error instanceof Error, true);
|
||||
t.is(error.name, 'NotReadableError');
|
||||
});
|
||||
const file = fileFromSync('./LICENSE')
|
||||
await new Promise(resolve => {
|
||||
setTimeout(resolve, 100)
|
||||
})
|
||||
const now = new Date()
|
||||
// Change modified time
|
||||
fs.utimesSync('./LICENSE', now, now)
|
||||
const error = await t.throwsAsync(file.text())
|
||||
t.is(error.constructor.name, 'DOMException')
|
||||
t.is(error instanceof Error, true)
|
||||
t.is(error.name, 'NotReadableError')
|
||||
})
|
||||
|
||||
test('Reading from the stream created by blobFrom', async t => {
|
||||
const blob = blobFromSync('./LICENSE');
|
||||
const actual = await blob.text();
|
||||
t.is(actual, license);
|
||||
});
|
||||
const blob = blobFromSync('./LICENSE')
|
||||
const actual = await blob.text()
|
||||
t.is(actual, license)
|
||||
})
|
||||
|
||||
test('create a blob from path asynchronous', async t => {
|
||||
const blob = await blobFrom('./LICENSE');
|
||||
const actual = await blob.text();
|
||||
t.is(actual, license);
|
||||
});
|
||||
const blob = await blobFrom('./LICENSE')
|
||||
const actual = await blob.text()
|
||||
t.is(actual, license)
|
||||
})
|
||||
|
||||
test('Reading empty blobs', async t => {
|
||||
const blob = blobFromSync('./LICENSE').slice(0, 0);
|
||||
const actual = await blob.text();
|
||||
t.is(actual, '');
|
||||
});
|
||||
const blob = blobFromSync('./LICENSE').slice(0, 0)
|
||||
const actual = await blob.text()
|
||||
t.is(actual, '')
|
||||
})
|
||||
|
||||
test('Blob-ish class is an instance of Blob', t => {
|
||||
class File {
|
||||
stream() {}
|
||||
class File {
|
||||
stream () {}
|
||||
|
||||
get [Symbol.toStringTag]() {
|
||||
return 'File';
|
||||
}
|
||||
}
|
||||
get [Symbol.toStringTag] () {
|
||||
return 'File'
|
||||
}
|
||||
}
|
||||
|
||||
t.true(new File() instanceof Blob);
|
||||
});
|
||||
t.true(new File() instanceof Blob)
|
||||
})
|
||||
|
||||
test('Instanceof check returns false for nullish values', t => {
|
||||
t.false(null instanceof Blob);
|
||||
});
|
||||
t.false(null instanceof Blob)
|
||||
})
|
||||
|
||||
/** @see https://github.com/w3c/FileAPI/issues/43 - important to keep boundary value */
|
||||
test('Dose not lowercase the blob values', t => {
|
||||
const type = 'multipart/form-data; boundary=----WebKitFormBoundaryTKqdrVt01qOBltBd';
|
||||
t.is(new Blob([], {type}).type, type);
|
||||
});
|
||||
const type = 'multipart/form-data; boundary=----WebKitFormBoundaryTKqdrVt01qOBltBd'
|
||||
t.is(new Blob([], { type }).type, type)
|
||||
})
|
||||
|
||||
test('Parts are immutable', async t => {
|
||||
const buf = new Uint8Array([97]);
|
||||
const blob = new Blob([buf]);
|
||||
buf[0] = 98;
|
||||
t.is(await blob.text(), 'a');
|
||||
});
|
||||
const buf = new Uint8Array([97])
|
||||
const blob = new Blob([buf])
|
||||
buf[0] = 98
|
||||
t.is(await blob.text(), 'a')
|
||||
})
|
||||
|
||||
test('Blobs are immutable', async t => {
|
||||
const buf = new Uint8Array([97]);
|
||||
const blob = new Blob([buf]);
|
||||
const chunk = await blob.stream().getReader().read();
|
||||
t.is(chunk.value[0], 97);
|
||||
chunk.value[0] = 98;
|
||||
t.is(await blob.text(), 'a');
|
||||
});
|
||||
const buf = new Uint8Array([97])
|
||||
const blob = new Blob([buf])
|
||||
const chunk = await blob.stream().getReader().read()
|
||||
t.is(chunk.value[0], 97)
|
||||
chunk.value[0] = 98
|
||||
t.is(await blob.text(), 'a')
|
||||
})
|
||||
|
||||
// This was necessary to avoid large ArrayBuffer clones (slice)
|
||||
test('Large chunks are divided into smaller chunks', async t => {
|
||||
const buf = new Uint8Array(65590);
|
||||
const blob = new Blob([buf]);
|
||||
let i = 0;
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
for await (const chunk of blob.stream()) {
|
||||
i++;
|
||||
}
|
||||
const buf = new Uint8Array(65590)
|
||||
const blob = new Blob([buf])
|
||||
let i = 0
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
for await (const chunk of blob.stream()) {
|
||||
i++
|
||||
}
|
||||
|
||||
t.is(i === 2, true);
|
||||
});
|
||||
t.is(i === 2, true)
|
||||
})
|
||||
|
||||
test('Can use named import - as well as default', async t => {
|
||||
// eslint-disable-next-line node/no-unsupported-features/es-syntax
|
||||
const {Blob, default: def} = await import('./index.js');
|
||||
t.is(Blob, def);
|
||||
});
|
||||
// eslint-disable-next-line node/no-unsupported-features/es-syntax
|
||||
const { Blob, default: def } = await import('./index.js')
|
||||
t.is(Blob, def)
|
||||
})
|
||||
|
||||
test('default from.js exports blobFromSync', t => {
|
||||
t.is(blobFromSync, syncBlob);
|
||||
});
|
||||
t.is(blobFromSync, syncBlob)
|
||||
})
|
||||
|
||||
if (buffer.Blob) {
|
||||
test('Can wrap buffer.Blob to a fetch-blob', async t => {
|
||||
const blob1 = new buffer.Blob(['blob part']);
|
||||
const blob2 = new Blob([blob1]);
|
||||
t.is(await blob2.text(), 'blob part');
|
||||
});
|
||||
test('Can wrap buffer.Blob to a fetch-blob', async t => {
|
||||
const blob1 = new buffer.Blob(['blob part'])
|
||||
const blob2 = new Blob([blob1])
|
||||
t.is(await blob2.text(), 'blob part')
|
||||
})
|
||||
}
|
||||
|
||||
test('File is a instance of blob', t => {
|
||||
t.true(new File([], '') instanceof Blob);
|
||||
});
|
||||
t.true(new File([], '') instanceof Blob)
|
||||
})
|
||||
|
||||
test('fileFrom returns the name', async t => {
|
||||
t.is((await fileFrom('./LICENSE')).name, 'LICENSE');
|
||||
});
|
||||
t.is((await fileFrom('./LICENSE')).name, 'LICENSE')
|
||||
})
|
||||
|
||||
test('fileFromSync returns the name', t => {
|
||||
t.is(fileFromSync('./LICENSE').name, 'LICENSE');
|
||||
});
|
||||
t.is(fileFromSync('./LICENSE').name, 'LICENSE')
|
||||
})
|
||||
|
||||
test('fileFromSync(path, type) sets the type', t => {
|
||||
t.is(fileFromSync('./LICENSE', 'text/plain').type, 'text/plain');
|
||||
});
|
||||
t.is(fileFromSync('./LICENSE', 'text/plain').type, 'text/plain')
|
||||
})
|
||||
|
||||
test('blobFromSync(path, type) sets the type', t => {
|
||||
t.is(blobFromSync('./LICENSE', 'text/plain').type, 'text/plain');
|
||||
});
|
||||
t.is(blobFromSync('./LICENSE', 'text/plain').type, 'text/plain')
|
||||
})
|
||||
|
||||
test('fileFrom(path, type) sets the type', async t => {
|
||||
const file = await fileFrom('./LICENSE', 'text/plain');
|
||||
t.is(file.type, 'text/plain');
|
||||
});
|
||||
const file = await fileFrom('./LICENSE', 'text/plain')
|
||||
t.is(file.type, 'text/plain')
|
||||
})
|
||||
|
||||
test('new File(,,{lastModified: 100})', t => {
|
||||
const mod = new File([], '', {lastModified: 100}).lastModified;
|
||||
t.is(mod, 100);
|
||||
});
|
||||
const mod = new File([], '', { lastModified: 100 }).lastModified
|
||||
t.is(mod, 100)
|
||||
})
|
||||
|
||||
test('new File(,,{lastModified: "200"})', t => {
|
||||
const mod = new File([], '', {lastModified: '200'}).lastModified;
|
||||
t.is(mod, 200);
|
||||
});
|
||||
const mod = new File([], '', { lastModified: '200' }).lastModified
|
||||
t.is(mod, 200)
|
||||
})
|
||||
|
||||
test('new File(,,{lastModified: true})', t => {
|
||||
const mod = new File([], '', {lastModified: true}).lastModified;
|
||||
t.is(mod, 1);
|
||||
});
|
||||
const mod = new File([], '', { lastModified: true }).lastModified
|
||||
t.is(mod, 1)
|
||||
})
|
||||
|
||||
test('new File(,,{lastModified: new Date()})', t => {
|
||||
const mod = new File([], '', {lastModified: new Date()}).lastModified - Date.now();
|
||||
t.true(mod <= 0 && mod >= -20); // Close to tolerance: 0.020ms
|
||||
});
|
||||
const mod = new File([], '', { lastModified: new Date() }).lastModified - Date.now()
|
||||
t.true(mod <= 0 && mod >= -20) // Close to tolerance: 0.020ms
|
||||
})
|
||||
|
||||
test('new File(,,{lastModified: undefined})', t => {
|
||||
const mod = new File([], '', {lastModified: undefined}).lastModified - Date.now();
|
||||
t.true(mod <= 0 && mod >= -20); // Close to tolerance: 0.020ms
|
||||
});
|
||||
const mod = new File([], '', { lastModified: undefined }).lastModified - Date.now()
|
||||
t.true(mod <= 0 && mod >= -20) // Close to tolerance: 0.020ms
|
||||
})
|
||||
|
||||
test('new File(,,{lastModified: null})', t => {
|
||||
const mod = new File([], '', {lastModified: null}).lastModified;
|
||||
t.is(mod, 0);
|
||||
});
|
||||
const mod = new File([], '', { lastModified: null }).lastModified
|
||||
t.is(mod, 0)
|
||||
})
|
||||
|
||||
test('Interpretes NaN value in lastModified option as 0', t => {
|
||||
t.plan(3);
|
||||
t.plan(3)
|
||||
|
||||
const values = ['Not a Number', [], {}];
|
||||
const values = ['Not a Number', [], {}]
|
||||
|
||||
// I can't really see anything about this in the spec,
|
||||
// but this is how browsers handle type casting for this option...
|
||||
for (const lastModified of values) {
|
||||
const file = new File(['Some content'], 'file.txt', {lastModified});
|
||||
// I can't really see anything about this in the spec,
|
||||
// but this is how browsers handle type casting for this option...
|
||||
for (const lastModified of values) {
|
||||
const file = new File(['Some content'], 'file.txt', { lastModified })
|
||||
|
||||
t.is(file.lastModified, 0);
|
||||
}
|
||||
});
|
||||
t.is(file.lastModified, 0)
|
||||
}
|
||||
})
|
||||
|
||||
test('new File(,,{}) sets current time', t => {
|
||||
const mod = new File([], '').lastModified - Date.now();
|
||||
t.true(mod <= 0 && mod >= -20); // Close to tolerance: 0.020ms
|
||||
});
|
||||
const mod = new File([], '').lastModified - Date.now()
|
||||
t.true(mod <= 0 && mod >= -20) // Close to tolerance: 0.020ms
|
||||
})
|
||||
|
||||
test('blobFrom(path, type) sets the type', async t => {
|
||||
const blob = await blobFrom('./LICENSE', 'text/plain');
|
||||
t.is(blob.type, 'text/plain');
|
||||
});
|
||||
const blob = await blobFrom('./LICENSE', 'text/plain')
|
||||
t.is(blob.type, 'text/plain')
|
||||
})
|
||||
|
||||
test('blobFrom(path) sets empty type', async t => {
|
||||
const blob = await blobFrom('./LICENSE');
|
||||
t.is(blob.type, '');
|
||||
});
|
||||
const blob = await blobFrom('./LICENSE')
|
||||
t.is(blob.type, '')
|
||||
})
|
||||
|
||||
test('new File() throws with too few args', t => {
|
||||
t.throws(() => new File(), {
|
||||
instanceOf: TypeError,
|
||||
message: 'Failed to construct \'File\': 2 arguments required, but only 0 present.'
|
||||
});
|
||||
});
|
||||
t.throws(() => new File(), {
|
||||
instanceOf: TypeError,
|
||||
message: 'Failed to construct \'File\': 2 arguments required, but only 0 present.'
|
||||
})
|
||||
})
|
||||
|
||||
test('can slice zero sized blobs', async t => {
|
||||
const blob = new Blob();
|
||||
const txt = await blob.slice(0, 0).text();
|
||||
t.is(txt, '');
|
||||
});
|
||||
const blob = new Blob()
|
||||
const txt = await blob.slice(0, 0).text()
|
||||
t.is(txt, '')
|
||||
})
|
||||
|
||||
test('returns a readable stream', t => {
|
||||
const stream = new File([], '').stream();
|
||||
t.true(typeof stream.getReader === 'function');
|
||||
});
|
||||
const stream = new File([], '').stream()
|
||||
t.true(typeof stream.getReader === 'function')
|
||||
})
|
||||
|
||||
test('checking instanceof blob#stream', async t => {
|
||||
// eslint-disable-next-line node/no-unsupported-features/es-syntax
|
||||
const {ReadableStream} = await import('node:stream/web').catch(_ => import('web-streams-polyfill/dist/ponyfill.es2018.js'));
|
||||
const stream = new File([], '').stream();
|
||||
t.true(stream instanceof ReadableStream);
|
||||
});
|
||||
test('checking instanceof blob#stream', t => {
|
||||
const stream = new File([], '').stream()
|
||||
t.true(stream instanceof globalThis.ReadableStream)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user