Spaces:
Running
Running
| import { | |
| detectImageFormat, | |
| discardArtifactFiles, | |
| discardMovedFile, | |
| moveArtifactFilesForDeletion, | |
| moveFileIfExists, | |
| readImageDimensions, | |
| restoreArtifactFiles, | |
| restoreMovedFile, | |
| writeFileAtomic | |
| } from './agent-file-utils'; | |
| import assert from 'node:assert/strict'; | |
| import { mkdir, mkdtemp, readdir, readFile, rm, writeFile } from 'node:fs/promises'; | |
| import os from 'node:os'; | |
| import path from 'node:path'; | |
| import { describe, it } from 'node:test'; | |
| const PNG_BASE64 = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+/p9sAAAAASUVORK5CYII='; | |
| describe('readImageDimensions', () => { | |
| it('reads PNG dimensions without external image libraries', () => { | |
| const buffer = Buffer.alloc(24); | |
| Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]).copy(buffer, 0); | |
| buffer.write('IHDR', 12, 'ascii'); | |
| buffer.writeUInt32BE(64, 16); | |
| buffer.writeUInt32BE(32, 20); | |
| assert.deepEqual(readImageDimensions(buffer), { width: 64, height: 32 }); | |
| }); | |
| it('returns null dimensions for unknown formats', () => { | |
| assert.deepEqual(readImageDimensions(Buffer.from('not an image')), { width: null, height: null }); | |
| }); | |
| }); | |
| describe('detectImageFormat', () => { | |
| it('uses image bytes instead of requested output format', () => { | |
| const buffer = Buffer.from(PNG_BASE64, 'base64'); | |
| assert.deepEqual(detectImageFormat(buffer, 'webp'), { | |
| outputFormat: 'png', | |
| mimeType: 'image/png' | |
| }); | |
| }); | |
| it('falls back to the requested format for unknown bytes', () => { | |
| assert.deepEqual(detectImageFormat(Buffer.from('not an image'), 'webp'), { | |
| outputFormat: 'webp', | |
| mimeType: 'image/webp' | |
| }); | |
| }); | |
| }); | |
| describe('writeFileAtomic', () => { | |
| it('removes temporary files when the final rename fails', async () => { | |
| const tempDir = await mkdtemp(path.join(os.tmpdir(), 'agent-atomic-')); | |
| const targetPath = path.join(tempDir, 'target.png'); | |
| await mkdir(targetPath); | |
| try { | |
| await assert.rejects(() => writeFileAtomic(targetPath, Buffer.from('image'))); | |
| const entries = await readdir(tempDir); | |
| assert.deepEqual( | |
| entries.filter((entry) => entry.includes('.tmp-')), | |
| [] | |
| ); | |
| } finally { | |
| await rm(tempDir, { recursive: true, force: true }); | |
| } | |
| }); | |
| }); | |
| describe('moveFileIfExists', () => { | |
| it('moves a file and can restore it afterward', async () => { | |
| const tempDir = await mkdtemp(path.join(os.tmpdir(), 'agent-move-')); | |
| const sourcePath = path.join(tempDir, 'artifact.png'); | |
| await writeFile(sourcePath, 'image-data'); | |
| try { | |
| const moved = await moveFileIfExists(sourcePath); | |
| assert.ok(moved); | |
| if (!moved) throw new Error('expected moved file'); | |
| await assert.rejects(() => readFile(sourcePath)); | |
| await restoreMovedFile(moved); | |
| assert.equal(await readFile(sourcePath, 'utf8'), 'image-data'); | |
| } finally { | |
| await rm(tempDir, { recursive: true, force: true }); | |
| } | |
| }); | |
| it('discards moved directories without leaving purge paths behind', async () => { | |
| const tempDir = await mkdtemp(path.join(os.tmpdir(), 'agent-move-dir-')); | |
| const sourcePath = path.join(tempDir, 'artifact-dir'); | |
| await mkdir(sourcePath); | |
| await writeFile(path.join(sourcePath, 'content.txt'), 'image-data'); | |
| try { | |
| const moved = await moveFileIfExists(sourcePath); | |
| assert.ok(moved); | |
| if (!moved) throw new Error('expected moved directory'); | |
| await discardMovedFile(moved); | |
| const entries = await readdir(tempDir); | |
| assert.deepEqual(entries, []); | |
| } finally { | |
| await rm(tempDir, { recursive: true, force: true }); | |
| } | |
| }); | |
| }); | |
| describe('moveArtifactFilesForDeletion', () => { | |
| it('moves and restores multiple artifact files through shared helpers', async () => { | |
| const tempDir = await mkdtemp(path.join(os.tmpdir(), 'agent-artifact-move-')); | |
| const firstPath = path.join(tempDir, 'first.png'); | |
| const secondPath = path.join(tempDir, 'second.png'); | |
| await writeFile(firstPath, 'first'); | |
| await writeFile(secondPath, 'second'); | |
| try { | |
| const moved = await moveArtifactFilesForDeletion([firstPath, secondPath]); | |
| assert.equal(moved.length, 2); | |
| await assert.rejects(() => readFile(firstPath)); | |
| await assert.rejects(() => readFile(secondPath)); | |
| await restoreArtifactFiles(moved); | |
| assert.equal(await readFile(firstPath, 'utf8'), 'first'); | |
| assert.equal(await readFile(secondPath, 'utf8'), 'second'); | |
| } finally { | |
| await rm(tempDir, { recursive: true, force: true }); | |
| } | |
| }); | |
| it('discards moved artifact files through the shared helper', async () => { | |
| const tempDir = await mkdtemp(path.join(os.tmpdir(), 'agent-artifact-discard-')); | |
| const sourcePath = path.join(tempDir, 'artifact.png'); | |
| await writeFile(sourcePath, 'image-data'); | |
| try { | |
| const moved = await moveArtifactFilesForDeletion([sourcePath]); | |
| await discardArtifactFiles(moved); | |
| assert.deepEqual(await readdir(tempDir), []); | |
| } finally { | |
| await rm(tempDir, { recursive: true, force: true }); | |
| } | |
| }); | |
| }); | |