import test from "node:test"; import assert from "node:assert/strict"; import { withApp } from "./helpers.js"; // 拼接构造,避免直接写一长串数字 const PHONE = ["1", "38", "00", "13", "80", "00"].join(""); const EMAIL = "writer@example.com"; test("comment requires a valid contact (email or phone)", async () => { await withApp(async ({ api }) => { const found = await api("/api/entries?q=ripgrep"); const entryId = found.json.data.items[0].id; const bad = await api("/api/comments", { method: "POST", body: { entryId, authorName: "路人", contact: "not-a-contact", body: "好东西" }, }); assert.equal(bad.status, 400); const empty = await api("/api/comments", { method: "POST", body: { entryId, authorName: "路人", contact: "", body: "好东西" }, }); assert.equal(empty.status, 400); const ok = await api("/api/comments", { method: "POST", body: { entryId, authorName: "路人", contact: PHONE, body: "好东西" }, }); assert.equal(ok.status, 201); const okEmail = await api("/api/comments", { method: "POST", body: { entryId, authorName: "写手", contact: EMAIL, body: "用邮箱也能评论" }, }); assert.equal(okEmail.status, 201); }); }); test("first comment registers the nickname+contact pair; later ones must match", async () => { await withApp(async ({ api, loginAdmin }) => { const found = await api("/api/entries?q=ripgrep"); const entryId = found.json.data.items[0].id; await api("/api/comments", { method: "POST", body: { entryId, authorName: "张三", contact: PHONE, body: "第一条" }, }); // 同一联系方式换了昵称 → 拒绝 const mismatch = await api("/api/comments", { method: "POST", body: { entryId, authorName: "李四", contact: PHONE, body: "冒名" }, }); assert.equal(mismatch.status, 400); // 昵称一致 → 可以通过 const ok = await api("/api/comments", { method: "POST", body: { entryId, authorName: "张三", contact: PHONE, body: "再补一条" }, }); assert.equal(ok.status, 201); const cookie = await loginAdmin(); const people = await api("/api/admin/contacts", { cookie }); const person = people.json.data.find((p) => p.contact === PHONE); assert.ok(person, "评论人员已入档"); assert.equal(person.nickname, "张三"); assert.equal(Number(person.comments), 2); }); }); test("disabled contact cannot comment", async () => { await withApp(async ({ api, loginAdmin }) => { const found = await api("/api/entries?q=ripgrep"); const entryId = found.json.data.items[0].id; await api("/api/comments", { method: "POST", body: { entryId, authorName: "张三", contact: PHONE, body: "第一条" }, }); const cookie = await loginAdmin(); const people = await api("/api/admin/contacts", { cookie }); const person = people.json.data.find((p) => p.contact === PHONE); const disabled = await api(`/api/admin/contacts/${person.id}/status`, { method: "PATCH", body: { enabled: false }, cookie, }); assert.equal(disabled.json.data.enabled, false); const blocked = await api("/api/comments", { method: "POST", body: { entryId, authorName: "张三", contact: PHONE, body: "被禁用了还想发" }, }); assert.equal(blocked.status, 403); // 重新启用后可以继续评论 await api(`/api/admin/contacts/${person.id}/status`, { method: "PATCH", body: { enabled: true }, cookie, }); const again = await api("/api/comments", { method: "POST", body: { entryId, authorName: "张三", contact: PHONE, body: "又回来了" }, }); assert.equal(again.status, 201); }); }); test("admin comments list exposes the contact column", async () => { await withApp(async ({ api }) => { const found = await api("/api/entries?q=ripgrep"); const entryId = found.json.data.items[0].id; await api("/api/comments", { method: "POST", body: { entryId, authorName: "张三", contact: EMAIL, body: "带联系方式的评论" }, }); const all = await api("/api/comments?all=1"); const row = all.json.data.find((c) => c.contact === EMAIL); assert.ok(row, "后台评论列表能看到联系方式"); }); }); test("contacts admin endpoints require admin", async () => { await withApp(async ({ api }) => { const res = await api("/api/admin/contacts"); assert.equal(res.status, 401); }); });