Files
3proxyUI/server/app.test.ts

93 lines
2.5 KiB
TypeScript

import fs from 'node:fs/promises';
import os from 'node:os';
import path from 'node:path';
import request from 'supertest';
import { afterEach, describe, expect, it } from 'vitest';
import { createApp } from './app';
import type { RuntimeSnapshot } from './lib/config';
import type { RuntimeController } from './lib/runtime';
import { StateStore } from './lib/store';
class FakeRuntime implements RuntimeController {
private status: RuntimeSnapshot = {
status: 'idle' as const,
pid: null,
startedAt: null,
lastError: null,
};
getSnapshot() {
return { ...this.status };
}
async start() {
this.status = {
status: 'live',
pid: 999,
startedAt: new Date('2026-04-01T00:00:00.000Z').toISOString(),
lastError: null,
};
return this.getSnapshot();
}
async restart() {
return this.start();
}
async reload() {
return this.getSnapshot();
}
}
const cleanupDirs: string[] = [];
afterEach(async () => {
await Promise.all(cleanupDirs.splice(0).map((dir) => fs.rm(dir, { recursive: true, force: true })));
});
describe('panel api', () => {
it('rejects user creation against a non-assignable service', async () => {
const app = await createTestApp();
const response = await request(app).post('/api/users').send({
username: 'bad-admin-user',
password: 'secret123',
serviceId: 'admin',
quotaMb: 100,
});
expect(response.status).toBe(400);
expect(response.body.error).toMatch(/enabled assignable/i);
});
it('pauses and deletes a user through the api', async () => {
const app = await createTestApp();
const initial = await request(app).get('/api/state');
const userId = initial.body.userRecords[0].id;
const username = initial.body.userRecords[0].username;
const paused = await request(app).post(`/api/users/${userId}/pause`);
expect(paused.status).toBe(200);
expect(paused.body.userRecords.find((entry: { id: string }) => entry.id === userId).paused).toBe(true);
const removed = await request(app).delete(`/api/users/${userId}`);
expect(removed.status).toBe(200);
expect(removed.body.userRecords.some((entry: { username: string }) => entry.username === username)).toBe(
false,
);
});
});
async function createTestApp() {
const dir = await fs.mkdtemp(path.join(os.tmpdir(), '3proxy-ui-'));
cleanupDirs.push(dir);
const runtime = new FakeRuntime();
const store = new StateStore(path.join(dir, 'state', 'panel-state.json'));
return createApp({
store,
runtime,
runtimeRootDir: dir,
});
}