Files
memind/shenmei-opinion-form-routes.test.mjs
T
john 32fb2cdeaf feat: chat uploads, vision turn isolation, and MindSpace agent improvements
Add chat file/image upload UX, attachment proxying, vision thumbnails, and per-turn image scoping so agents only use the current upload. Extend MindSpace asset context, billing token state, OA/scenario verify scripts, and related runtime config.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-11 00:23:01 +08:00

106 lines
3.7 KiB
JavaScript

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);
});