test: add HTTP integration tests for /api/icon-sets
Covers GET (open, returns bundled devices set), POST without auth (must return 401 not 500), POST with owner bearer (uploads icon, returns set), and GET /:set/:file (serves with correct content-type). Uses _setDirs for temp-dir isolation. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
72
tests/api/icon_sets.test.js
Normal file
72
tests/api/icon_sets.test.js
Normal file
@@ -0,0 +1,72 @@
|
||||
// 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'), '<svg><path/></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');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user