111 lines
4.0 KiB
TypeScript
111 lines
4.0 KiB
TypeScript
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
import express from 'express';
|
|
import request from 'supertest';
|
|
import { mkdtempSync, rmSync } from 'fs';
|
|
import { join } from 'path';
|
|
import { tmpdir } from 'os';
|
|
import { createUserFolderApi } from './user-folder-api.js';
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Helpers
|
|
// ---------------------------------------------------------------------------
|
|
|
|
function makeApp(userId: string, userFolderRoot: string): express.Application {
|
|
const app = express();
|
|
app.use((req, _res, next) => {
|
|
(req as any).user = { id: userId, role: 'user' };
|
|
next();
|
|
});
|
|
app.use('/api/users/me', createUserFolderApi({ userFolderRoot }));
|
|
return app;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Tests
|
|
// ---------------------------------------------------------------------------
|
|
|
|
describe('User Folder API — AGENTS.md routes', () => {
|
|
let tmpRoot: string;
|
|
let app: express.Application;
|
|
const USER_A = 'user-a';
|
|
|
|
beforeEach(() => {
|
|
tmpRoot = mkdtempSync(join(tmpdir(), 'agents-md-test-'));
|
|
app = makeApp(USER_A, tmpRoot);
|
|
});
|
|
|
|
afterEach(() => {
|
|
rmSync(tmpRoot, { recursive: true, force: true });
|
|
});
|
|
|
|
// ── GET /agents-md ────────────────────────────────────────────────────────
|
|
|
|
it('GET /agents-md returns exists=false when file is missing', async () => {
|
|
const res = await request(app).get('/api/users/me/agents-md');
|
|
expect(res.status).toBe(200);
|
|
expect(res.body).toEqual({ exists: false, content: '' });
|
|
});
|
|
|
|
// ── PUT /agents-md ────────────────────────────────────────────────────────
|
|
|
|
it('PUT /agents-md writes content; subsequent GET reflects it', async () => {
|
|
const text = '# My Instructions\n\nAlways be concise.\n';
|
|
|
|
const putRes = await request(app)
|
|
.put('/api/users/me/agents-md')
|
|
.set('Content-Type', 'text/plain')
|
|
.send(text);
|
|
expect(putRes.status).toBe(200);
|
|
expect(putRes.body.ok).toBe(true);
|
|
expect(typeof putRes.body.bytes).toBe('number');
|
|
|
|
const getRes = await request(app).get('/api/users/me/agents-md');
|
|
expect(getRes.status).toBe(200);
|
|
expect(getRes.body.exists).toBe(true);
|
|
expect(getRes.body.content).toBe(text);
|
|
});
|
|
|
|
it('PUT /agents-md with oversized body returns 413', async () => {
|
|
// 64 KB + 1 byte — exceeds USER_AGENTS_MAX_BYTES
|
|
const oversized = 'x'.repeat(64 * 1024 + 1);
|
|
|
|
const res = await request(app)
|
|
.put('/api/users/me/agents-md')
|
|
.set('Content-Type', 'text/plain')
|
|
.send(oversized);
|
|
expect(res.status).toBe(413);
|
|
expect(res.body.error).toMatch(/exceeds/);
|
|
});
|
|
|
|
// ── DELETE /agents-md ─────────────────────────────────────────────────────
|
|
|
|
it('DELETE /agents-md removes the file', async () => {
|
|
// First write something
|
|
await request(app)
|
|
.put('/api/users/me/agents-md')
|
|
.set('Content-Type', 'text/plain')
|
|
.send('# Hello\n');
|
|
|
|
// Confirm it exists
|
|
const beforeGet = await request(app).get('/api/users/me/agents-md');
|
|
expect(beforeGet.body.exists).toBe(true);
|
|
|
|
// Delete it
|
|
const delRes = await request(app).delete('/api/users/me/agents-md');
|
|
expect(delRes.status).toBe(200);
|
|
expect(delRes.body.ok).toBe(true);
|
|
expect(delRes.body.existed).toBe(true);
|
|
|
|
// Confirm it's gone
|
|
const afterGet = await request(app).get('/api/users/me/agents-md');
|
|
expect(afterGet.body.exists).toBe(false);
|
|
});
|
|
|
|
it('DELETE /agents-md when file does not exist returns ok=true, existed=false', async () => {
|
|
const res = await request(app).delete('/api/users/me/agents-md');
|
|
expect(res.status).toBe(200);
|
|
expect(res.body.ok).toBe(true);
|
|
expect(res.body.existed).toBe(false);
|
|
});
|
|
});
|