- M1-M2: 数据层与核心API(DuckDB, entries/tags/comments/search服务) - M3: SSR页面(EJS模板,接真实数据) - M4: 管理后台(登录/用户/内容源/AI ingest) - M5: 采集层(scheduler+rss/html/eryajf适配器) - M6: MCP只读接口(Streamable HTTP, 4工具) - M7: Docker部署(Dockerfile+docker-compose) - 测试: 10个用例全部通过 - 修复: DuckDB连接参数绑定、状态机迁移、标签树操作
56 lines
1.8 KiB
JavaScript
56 lines
1.8 KiB
JavaScript
import fs from "node:fs";
|
|
import os from "node:os";
|
|
import path from "node:path";
|
|
import { connect, close } from "../src/db/connection.js";
|
|
import { runMigrate } from "../src/db/migrate.js";
|
|
import { buildApp } from "../src/app.js";
|
|
|
|
export async function withApp(fn) {
|
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "awesome-test-"));
|
|
await connect(path.join(dir, "test.duckdb"));
|
|
await runMigrate({ adminInitPassword: "test123", aiIngestKey: "" });
|
|
const app = buildApp({
|
|
sessionSecret: "test-secret",
|
|
duckdbPath: path.join(dir, "test.duckdb"),
|
|
baseUrl: "http://test.local",
|
|
});
|
|
const server = app.listen(0);
|
|
await new Promise((r) => server.once("listening", r));
|
|
const base = `http://127.0.0.1:${server.address().port}`;
|
|
|
|
async function api(pathname, { method = "GET", body, cookie } = {}) {
|
|
const res = await fetch(base + pathname, {
|
|
method,
|
|
headers: {
|
|
...(body ? { "content-type": "application/json" } : {}),
|
|
...(cookie ? { cookie } : {}),
|
|
},
|
|
body: body ? JSON.stringify(body) : undefined,
|
|
});
|
|
let json = null;
|
|
try {
|
|
json = await res.json();
|
|
} catch {}
|
|
return { status: res.status, json, headers: res.headers };
|
|
}
|
|
|
|
async function loginAdmin() {
|
|
const res = await fetch(base + "/api/admin/login", {
|
|
method: "POST",
|
|
headers: { "content-type": "application/json" },
|
|
body: JSON.stringify({ username: "admin", password: "test123" }),
|
|
});
|
|
const cookies = res.headers.getSetCookie().map((c) => c.split(";")[0]);
|
|
return cookies.join("; ");
|
|
}
|
|
|
|
try {
|
|
await fn({ base, api, loginAdmin });
|
|
} finally {
|
|
server.closeAllConnections?.();
|
|
await new Promise((r) => server.close(r));
|
|
await close();
|
|
fs.rmSync(dir, { recursive: true, force: true, maxRetries: 3 });
|
|
}
|
|
}
|