// tests/api/icon_sets.test.js import { describe, it, expect, beforeAll, beforeEach } from 'vitest'; import { mkdtempSync, mkdirSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import path from 'node:path'; import request from 'supertest'; import { createApp } from '../../server.js'; import * as sets from '../../lib/icons/sets.js'; const PNG = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0, 0, 0, 0]); let app; let setsDir; let bundledDir; beforeAll(() => { process.env.OWNER_TOKEN = 'test-token'; app = createApp(); }); beforeEach(() => { // Set up fresh temp dirs with a fake bundled device icon so the bundled set is non-empty. setsDir = mkdtempSync(path.join(tmpdir(), 'iconsets-')); bundledDir = path.join(setsDir, '__bundled'); mkdirSync(bundledDir, { recursive: true }); writeFileSync(path.join(bundledDir, 'router.svg'), ''); sets._setDirs({ setsDir, bundledDir }); }); const owner = r => r.set('Authorization', 'Bearer test-token'); describe('GET /api/icon-sets', () => { it('returns 200 with an array including the bundled devices set', async () => { const res = await request(app).get('/api/icon-sets'); expect(res.status).toBe(200); expect(Array.isArray(res.body)).toBe(true); const dev = res.body.find(s => s.set === 'devices'); expect(dev).toBeDefined(); expect(dev.readonly).toBe(true); }); }); describe('POST /api/icon-sets/:set', () => { it('returns 401 (not 500) without auth', async () => { const res = await request(app) .post('/api/icon-sets/mytest') .attach('files', PNG, { filename: 'router.png', contentType: 'image/png' }); expect(res.status).toBe(401); }); it('returns 200 and uploads the icon with owner auth', async () => { const res = await owner( request(app).post('/api/icon-sets/mytest') ).attach('files', PNG, { filename: 'router.png', contentType: 'image/png' }); expect(res.status).toBe(200); expect(res.body.set).toBe('mytest'); expect(res.body.icons).toContain('router.png'); }); }); describe('GET /api/icon-sets/:set/:file', () => { it('serves a previously uploaded icon with image/png content-type', async () => { // Upload first await owner( request(app).post('/api/icon-sets/mytest') ).attach('files', PNG, { filename: 'router.png', contentType: 'image/png' }); const res = await request(app).get('/api/icon-sets/mytest/router.png'); expect(res.status).toBe(200); expect(res.headers['content-type']).toContain('image/png'); }); });