Files
2026-07-13 12:47:58 +08:00

367 lines
10 KiB
TypeScript

import path from 'path'
import { assert } from 'vitest'
import { WriteEntry } from '../../../src/sandbox/filesystem'
import { isDebug, sandboxTest } from '../../setup.js'
sandboxTest('write file', async ({ sandbox }) => {
const filename = 'test_write.txt'
const content = 'This is a test file.'
// Attempt to write with undefined path and content
await sandbox.files
// @ts-ignore
.write(undefined, content)
.then((e) => {
assert.isUndefined(e)
})
.catch((err) => {
assert.instanceOf(err, Error)
assert.include(err.message, 'Path or files are required')
})
const info = await sandbox.files.write(filename, content)
assert.isFalse(Array.isArray(info))
assert.equal(info.name, filename)
assert.equal(info.type, 'file')
assert.equal(info.path, `/home/user/${filename}`)
const exists = await sandbox.files.exists(filename)
assert.isTrue(exists)
const readContent = await sandbox.files.read(filename)
assert.equal(readContent, content)
if (isDebug) {
await sandbox.files.remove(filename)
}
})
sandboxTest('write multiple files', async ({ sandbox }) => {
const numTestFiles = 10
// Attempt to write with empty files array
const emptyInfo = await sandbox.files.write([])
assert.isTrue(Array.isArray(emptyInfo))
assert.equal(emptyInfo.length, 0)
// Attempt to write with undefined path and file array
await sandbox.files
// @ts-ignore
.write(undefined, [
{ path: 'one_test_file.txt', data: 'This is a test file.' },
])
.then((e) => {
assert.isUndefined(e)
})
.catch((err) => {
assert.instanceOf(err, Error)
assert.include(err.message, 'Path or files are required')
})
// Attempt to write with path and file array
await sandbox.files
// @ts-ignore
.write('/path/to/file', [
{ path: 'one_test_file.txt', data: 'This is a test file.' },
])
.then((e) => {
assert.isUndefined(e)
})
.catch((err) => {
assert.instanceOf(err, Error)
assert.include(
err.message,
'Cannot specify both path and array of files. You have to specify either path and data for a single file or an array for multiple files.'
)
})
// Attempt to write with one file in array
const info = await sandbox.files.write([
{ path: 'one_test_file.txt', data: 'This is a test file.' },
])
assert.isTrue(Array.isArray(info))
assert.equal(info[0].name, 'one_test_file.txt')
assert.equal(info[0].type, 'file')
assert.equal(info[0].path, '/home/user/one_test_file.txt')
// Attempt to write with multiple files in array
const files: WriteEntry[] = []
for (let i = 0; i < numTestFiles; i++) {
let path = ''
if (i % 2 == 0) {
path = `/${i}/multi_test_file${i}.txt`
} else {
path = `/home/user/multi_test_file${i}.txt`
}
files.push({
path: path,
data: `This is a test file ${i}.`,
})
}
const infos = await sandbox.files.write(files)
assert.isTrue(Array.isArray(infos))
assert.equal(infos.length, files.length)
// Attempt to write with multiple files in array
for (let i = 0; i < files.length; i++) {
const file = files[i]
const info = infos[i]
assert.equal(info.name, path.basename(file.path))
assert.equal(info.path, file.path)
assert.equal(info.type, 'file')
const exists = await sandbox.files.exists(file.path)
assert.isTrue(exists)
const readContent = await sandbox.files.read(file.path)
assert.equal(readContent, file.data)
}
if (isDebug) {
for (const file of files) {
await sandbox.files.remove(file.path)
}
}
})
sandboxTest('write file', async ({ sandbox }) => {
const filename = 'test_write.txt'
const content = 'This is a test file.'
const info = await sandbox.files.write(filename, content)
assert.isFalse(Array.isArray(info))
assert.equal(info.name, filename)
assert.equal(info.type, 'file')
assert.equal(info.path, `/home/user/${filename}`)
const exists = await sandbox.files.exists(filename)
assert.isTrue(exists)
const readContent = await sandbox.files.read(filename)
assert.equal(readContent, content)
if (isDebug) {
await sandbox.files.remove(filename)
}
})
sandboxTest('overwrite file', async ({ sandbox }) => {
const filename = 'test_overwrite.txt'
const initialContent = 'Initial content.'
const newContent = 'New content.'
await sandbox.files.write(filename, initialContent)
await sandbox.files.write(filename, newContent)
const readContent = await sandbox.files.read(filename)
assert.equal(readContent, newContent)
if (isDebug) {
await sandbox.files.remove(filename)
}
})
sandboxTest('write to non-existing directory', async ({ sandbox }) => {
const filename = 'non_existing_dir/test_write.txt'
const content = 'This should succeed too.'
await sandbox.files.write(filename, content)
const exists = await sandbox.files.exists(filename)
assert.isTrue(exists)
const readContent = await sandbox.files.read(filename)
assert.equal(readContent, content)
if (isDebug) {
await sandbox.files.remove(filename)
}
})
sandboxTest('writeFiles with empty array', async ({ sandbox }) => {
const emptyInfo = await sandbox.files.writeFiles([])
assert.isTrue(Array.isArray(emptyInfo))
assert.equal(emptyInfo.length, 0)
})
sandboxTest('writeFiles with multiple files', async ({ sandbox }) => {
const numTestFiles = 10
const files: WriteEntry[] = []
for (let i = 0; i < numTestFiles; i++) {
const filePath = `writefiles_test_${i}.txt`
files.push({
path: filePath,
data: `This is a test file ${i}.`,
})
}
const infos = await sandbox.files.writeFiles(files)
assert.isTrue(Array.isArray(infos))
assert.equal(infos.length, files.length)
for (let i = 0; i < files.length; i++) {
const file = files[i]
const info = infos[i]
assert.equal(info.name, path.basename(file.path))
assert.equal(info.path, `/home/user/${file.path}`)
assert.equal(info.type, 'file')
const exists = await sandbox.files.exists(info.path)
assert.isTrue(exists)
const readContent = await sandbox.files.read(info.path)
assert.equal(readContent, file.data)
}
if (isDebug) {
for (const file of files) {
await sandbox.files.remove(file.path)
}
}
})
sandboxTest('writeFiles with different data types', async ({ sandbox }) => {
const textData = 'Text string data'
const arrayBufferData = new TextEncoder().encode('ArrayBuffer data').buffer
const blobData = new Blob(['Blob data'], { type: 'text/plain' })
const streamContent = 'ReadableStream data'
const encoder = new TextEncoder()
const streamData = new ReadableStream({
start(controller) {
controller.enqueue(encoder.encode(streamContent))
controller.close()
},
})
const files: WriteEntry[] = [
{ path: 'writefiles_text.txt', data: textData },
{ path: 'writefiles_arraybuffer.txt', data: arrayBufferData },
{ path: 'writefiles_blob.txt', data: blobData },
{ path: 'writefiles_stream.txt', data: streamData },
]
const infos = await sandbox.files.writeFiles(files)
assert.equal(infos.length, 4)
// Verify text file
const textContent = await sandbox.files.read('writefiles_text.txt')
assert.equal(textContent, textData)
// Verify ArrayBuffer file
const arrayBufferContent = await sandbox.files.read(
'writefiles_arraybuffer.txt'
)
assert.equal(arrayBufferContent, 'ArrayBuffer data')
// Verify Blob file
const blobContent = await sandbox.files.read('writefiles_blob.txt')
assert.equal(blobContent, 'Blob data')
// Verify ReadableStream file
const streamFileContent = await sandbox.files.read('writefiles_stream.txt')
assert.equal(streamFileContent, streamContent)
if (isDebug) {
for (const file of files) {
await sandbox.files.remove(file.path)
}
}
})
sandboxTest('writeFiles creates parent directories', async ({ sandbox }) => {
const files: WriteEntry[] = [
{
path: 'writefiles_nested_dir/nested/file1.txt',
data: 'Content in nested directory',
},
]
const infos = await sandbox.files.writeFiles(files)
assert.equal(infos.length, 1)
assert.equal(
infos[0].path,
'/home/user/writefiles_nested_dir/nested/file1.txt'
)
const exists = await sandbox.files.exists(infos[0].path)
assert.isTrue(exists)
const content = await sandbox.files.read(infos[0].path)
assert.equal(content, 'Content in nested directory')
if (isDebug) {
await sandbox.files.remove(files[0].path)
}
})
sandboxTest('writeFiles overwrites existing files', async ({ sandbox }) => {
const filename = 'writefiles_overwrite.txt'
const initialContent = 'Initial content'
const newContent = 'New content'
// Write initial file
await sandbox.files.writeFiles([{ path: filename, data: initialContent }])
let readContent = await sandbox.files.read(filename)
assert.equal(readContent, initialContent)
// Overwrite with new content
await sandbox.files.writeFiles([{ path: filename, data: newContent }])
readContent = await sandbox.files.read(filename)
assert.equal(readContent, newContent)
if (isDebug) {
await sandbox.files.remove(filename)
}
})
sandboxTest(
'write ReadableStream with octet stream upload',
async ({ sandbox }) => {
const filename = 'test_write_octet_stream.bin'
const content = 'Streamed octet-stream upload. '.repeat(10_000)
const stream = new Blob([content]).stream()
const info = await sandbox.files.write(filename, stream, {
useOctetStream: true,
})
assert.equal(info.path, `/home/user/${filename}`)
const readContent = await sandbox.files.read(filename)
assert.equal(readContent, content)
if (isDebug) {
await sandbox.files.remove(filename)
}
}
)
sandboxTest(
'write ReadableStream with octet stream upload and gzip',
async ({ sandbox }) => {
const filename = 'test_write_octet_stream_gzip.bin'
const content = 'Streamed gzipped octet-stream upload. '.repeat(10_000)
const stream = new Blob([content]).stream()
const info = await sandbox.files.write(filename, stream, {
useOctetStream: true,
gzip: true,
})
assert.equal(info.path, `/home/user/${filename}`)
const readContent = await sandbox.files.read(filename)
assert.equal(readContent, content)
if (isDebug) {
await sandbox.files.remove(filename)
}
}
)