import assert from 'node:assert/strict'; import fs from 'node:fs'; import fsPromises from 'node:fs/promises'; import http from 'node:http'; import os from 'node:os'; import path from 'node:path'; import test from 'node:test'; import express from 'express'; import { attachShenmeiOpinionFormRoutes } from './shenmei-opinion-form-routes.mjs'; async function request(baseUrl, method, pathname, { body, headers } = {}) { const response = await fetch(`${baseUrl}${pathname}`, { method, headers: { ...(body ? { 'content-type': 'application/json' } : {}), ...headers, }, body: body ? JSON.stringify(body) : undefined, }); const text = await response.text(); return { status: response.status, body: text ? JSON.parse(text) : null, }; } async function withApp(t, dataFile) { const app = express(); app.use(express.json()); const api = express.Router(); attachShenmeiOpinionFormRoutes(api, { dataFile }); app.use('/api', api); const server = http.createServer(app); await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve)); t.after(() => new Promise((resolve) => server.close(resolve))); const { port } = server.address(); return `http://127.0.0.1:${port}`; } test('shenmei form route appends valid records and lists them with admin header', async (t) => { const dir = await fsPromises.mkdtemp(path.join(os.tmpdir(), 'shenmei-form-')); const dataFile = path.join(dir, 'responses.ndjson'); const baseUrl = await withApp(t, dataFile); const record = { id: 'shenmei_test_1', name: '测试用户', goodPeople: '正向内容', goodBehaviors: '推广做法', badPeople: '负向内容', badSuggestions: '改进建议', time: '2026/7/10 12:30:00', timestamp: 1783657800000, }; const submitted = await request(baseUrl, 'POST', '/api/public/forms/shenmei-opinion-unified/submit', { body: { records: [record] }, }); assert.equal(submitted.status, 200); assert.equal(submitted.body.ok, true); assert.equal(submitted.body.inserted, 1); assert.equal(fs.readFileSync(dataFile, 'utf8').trim().split(/\n/).length, 1); const listed = await request(baseUrl, 'GET', '/api/public/forms/shenmei-opinion-unified/responses', { headers: { 'x-shenmei-admin': 'sm6666' }, }); assert.equal(listed.status, 200); assert.equal(listed.body.data.length, 1); assert.equal(listed.body.data[0].name, '测试用户'); }); test('shenmei form route skips duplicate submissions', async (t) => { const dir = await fsPromises.mkdtemp(path.join(os.tmpdir(), 'shenmei-form-')); const dataFile = path.join(dir, 'responses.ndjson'); const baseUrl = await withApp(t, dataFile); const body = { records: [ { id: 'one', name: '测试用户', goodPeople: '正向内容', badPeople: '负向内容', time: '2026/7/10 12:30:00', timestamp: 1783657800000, }, ], }; const first = await request(baseUrl, 'POST', '/api/public/forms/shenmei-opinion-unified/submit', { body }); const second = await request(baseUrl, 'POST', '/api/public/forms/shenmei-opinion-unified/submit', { body }); assert.equal(first.body.inserted, 1); assert.equal(second.body.inserted, 0); assert.equal(second.body.skipped, 1); assert.equal(fs.readFileSync(dataFile, 'utf8').trim().split(/\n/).length, 1); }); test('shenmei form responses require admin header', async (t) => { const dir = await fsPromises.mkdtemp(path.join(os.tmpdir(), 'shenmei-form-')); const dataFile = path.join(dir, 'responses.ndjson'); const baseUrl = await withApp(t, dataFile); const denied = await request(baseUrl, 'GET', '/api/public/forms/shenmei-opinion-unified/responses'); assert.equal(denied.status, 403); });