Files
sunrise/tests/threads-cleanup.test.ts

50 lines
2.6 KiB
TypeScript

import { test } from 'node:test';
import assert from 'node:assert/strict';
import { mkdtemp, mkdir, writeFile, readFile, access, unlink, rmdir } from 'node:fs/promises';
import { join } from 'node:path';
import { tmpdir } from 'node:os';
import { cleanupPublished } from '../server/threads/cleanup.ts';
test('cleanup preserves unconfirmed images, deletes confirmed images and is repeatable', async () => {
const root = await mkdtemp(join(tmpdir(), 'threads-cleanup-'));
const recordPath = join(root, 'record.json');
const images = [join(root, 'one.jpg'), join(root, 'two.jpg')];
try {
for (const image of images) await writeFile(image, 'image');
const record = { status: 'publishing', images: images.map(imagePath => ({ imagePath })) };
await writeFile(recordPath, JSON.stringify(record));
assert.equal(await cleanupPublished(recordPath, root), false);
for (const image of images) await access(image);
await writeFile(recordPath, JSON.stringify({ ...record, status: 'published', postId: 'post-123' }));
assert.equal(await cleanupPublished(recordPath, root), true);
for (const image of images) await assert.rejects(access(image), { code: 'ENOENT' });
const saved = JSON.parse(await readFile(recordPath, 'utf8'));
assert.equal(saved.postId, 'post-123');
assert.ok(saved.imagesDeletedAt);
assert.equal(await cleanupPublished(recordPath, root), false);
} finally {
for (const path of [...images, recordPath]) await unlink(path).catch(() => {});
await rmdir(root);
}
});
test('cleanup validates every target before deleting and rejects outside files', async () => {
const root = await mkdtemp(join(tmpdir(), 'threads-cleanup-'));
const imageDir = join(root, 'images');
await mkdir(imageDir);
const inside = join(imageDir, 'one.jpg'), outside = join(root, 'outside.jpg'), recordPath = join(root, 'record.json');
try {
await writeFile(inside, 'image'); await writeFile(outside, 'keep');
await writeFile(recordPath, JSON.stringify({ status: 'published', postId: 'post',
images: [{ imagePath: inside }, { imagePath: outside }] }));
await assert.rejects(cleanupPublished(recordPath, imageDir), /outside/);
await access(inside); await access(outside);
await writeFile(recordPath, JSON.stringify({ status: 'published', postId: 'post',
images: [{ imagePath: inside }, { imagePath: join(imageDir, 'already-deleted.jpg') }] }));
assert.equal(await cleanupPublished(recordPath, imageDir), true);
} finally {
for (const path of [inside, outside, recordPath]) await unlink(path).catch(() => {});
await rmdir(imageDir); await rmdir(root);
}
});