AI Implementation feature(917): Category Icons (#65)
This commit was merged in pull request #65.
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import sharp from 'sharp';
|
||||
import {
|
||||
CANONICAL_SYSTEM_ICON_KEYS,
|
||||
SYSTEM_ICON_SIZE,
|
||||
seedSystemCategoryIcons,
|
||||
} from '../../backend/src/database/system-category-icons';
|
||||
|
||||
function makeTempDir(): string {
|
||||
return fs.mkdtempSync(path.join(os.tmpdir(), 'hipctf-icons-'));
|
||||
}
|
||||
|
||||
describe('seedSystemCategoryIcons', () => {
|
||||
const cleanup: string[] = [];
|
||||
|
||||
afterEach(() => {
|
||||
while (cleanup.length > 0) {
|
||||
const dir = cleanup.pop();
|
||||
if (dir && fs.existsSync(dir)) fs.rmSync(dir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
it('writes six 128x128 PNGs into a fresh temp directory', async () => {
|
||||
const dir = makeTempDir();
|
||||
cleanup.push(dir);
|
||||
|
||||
const result = await seedSystemCategoryIcons(dir);
|
||||
|
||||
expect(result.written.length).toBe(CANONICAL_SYSTEM_ICON_KEYS.length);
|
||||
expect(result.skipped.length).toBe(0);
|
||||
|
||||
for (const key of CANONICAL_SYSTEM_ICON_KEYS) {
|
||||
const target = path.join(dir, 'icons', `${key}.png`);
|
||||
expect(fs.existsSync(target)).toBe(true);
|
||||
const stat = fs.statSync(target);
|
||||
expect(stat.size).toBeGreaterThan(0);
|
||||
const meta = await sharp(target).metadata();
|
||||
expect(meta.format).toBe('png');
|
||||
expect(meta.width).toBe(SYSTEM_ICON_SIZE);
|
||||
expect(meta.height).toBe(SYSTEM_ICON_SIZE);
|
||||
}
|
||||
});
|
||||
|
||||
it('is idempotent and does not overwrite an existing admin-uploaded icon', async () => {
|
||||
const dir = makeTempDir();
|
||||
cleanup.push(dir);
|
||||
|
||||
const first = await seedSystemCategoryIcons(dir);
|
||||
expect(first.written.length).toBe(CANONICAL_SYSTEM_ICON_KEYS.length);
|
||||
|
||||
const adminIconPath = path.join(dir, 'icons', 'CRY.png');
|
||||
const adminMtime = fs.statSync(adminIconPath).mtimeMs;
|
||||
await new Promise((r) => setTimeout(r, 25));
|
||||
|
||||
const second = await seedSystemCategoryIcons(dir);
|
||||
expect(second.written.length).toBe(0);
|
||||
expect(second.skipped.length).toBe(CANONICAL_SYSTEM_ICON_KEYS.length);
|
||||
|
||||
expect(fs.statSync(adminIconPath).mtimeMs).toBe(adminMtime);
|
||||
for (const key of CANONICAL_SYSTEM_ICON_KEYS) {
|
||||
const target = path.join(dir, 'icons', `${key}.png`);
|
||||
expect(fs.statSync(target).size).toBeGreaterThan(0);
|
||||
}
|
||||
});
|
||||
|
||||
it('creates the icons subdirectory when the parent directory is empty', async () => {
|
||||
const dir = makeTempDir();
|
||||
cleanup.push(dir);
|
||||
|
||||
const target = path.join(dir, 'icons');
|
||||
expect(fs.existsSync(target)).toBe(false);
|
||||
|
||||
const result = await seedSystemCategoryIcons(dir);
|
||||
expect(result.written.length).toBe(CANONICAL_SYSTEM_ICON_KEYS.length);
|
||||
expect(fs.existsSync(target)).toBe(true);
|
||||
expect(fs.readdirSync(target).sort()).toEqual(
|
||||
[...CANONICAL_SYSTEM_ICON_KEYS].map((k) => `${k}.png`).sort(),
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user