import { listStorageFiles, removeStorageObjects, STORAGE_BATCH_SIZE, type StorageBucketPort, type StorageEntry, } from './storage-objects.ts' function assertEquals(actual: unknown, expected: unknown, message: string): void { const a = JSON.stringify(actual) const e = JSON.stringify(expected) if (a !== e) throw new Error(`${message}: expected ${e}, got ${a}`) } class FakeBucket implements StorageBucketPort { readonly bucket = 'audio' listCalls: Array<{ prefix: string; offset: number }> = [] removed: string[][] = [] constructor(private tree: Record, private failRemoveAt = -1) {} list(prefix: string, offset: number, limit: number): Promise { this.listCalls.push({ prefix, offset }) return Promise.resolve((this.tree[prefix] ?? []).slice(offset, offset + limit)) } remove(paths: string[]): Promise { if (this.removed.length === this.failRemoveAt) return Promise.reject(new Error('storage_delete_failed:audio')) this.removed.push(paths) return Promise.resolve() } } Deno.test('storage-objects: listStorageFiles walks folders and pages', async () => { const many = Array.from({ length: STORAGE_BATCH_SIZE + 3 }, (_, i) => ({ name: `f${i}.wav`, id: `id${i}` })) const bucket = new FakeBucket({ u: [{ name: 'history', id: null }, { name: 'top.wav', id: 'top' }], 'u/history': many, }) const files = await listStorageFiles(bucket, 'u') assertEquals(files.length, STORAGE_BATCH_SIZE + 4, 'all files found') assertEquals(files[files.length - 1], 'u/top.wav', 'depth-first order') assertEquals( bucket.listCalls, [{ prefix: 'u', offset: 0 }, { prefix: 'u/history', offset: 0 }, { prefix: 'u/history', offset: STORAGE_BATCH_SIZE }], 'paged listing', ) }) Deno.test('storage-objects: removeStorageObjects batches and stops on the first failure', async () => { const paths = Array.from({ length: STORAGE_BATCH_SIZE * 2 + 1 }, (_, i) => `u/${i}`) const ok = new FakeBucket({}) await removeStorageObjects(ok, paths) assertEquals(ok.removed.map((b) => b.length), [STORAGE_BATCH_SIZE, STORAGE_BATCH_SIZE, 1], 'batch sizes') const failing = new FakeBucket({}, 1) let message = '' try { await removeStorageObjects(failing, paths) } catch (error) { message = error instanceof Error ? error.message : '' } assertEquals(message, 'storage_delete_failed:audio', 'error propagates') assertEquals(failing.removed.length, 1, 'later batches are not attempted') const empty = new FakeBucket({}) await removeStorageObjects(empty, []) assertEquals(empty.removed.length, 0, 'nothing to remove') })