50 lines
2.6 KiB
TypeScript
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);
|
|
}
|
|
});
|