2baf29b3ae
Deliver encrypted health zone, observation API, baseline maturity pipeline, page-data bindings, and H5/WeChat channel integration for health P0. Co-authored-by: Cursor <cursoragent@cursor.com>
106 lines
3.8 KiB
JavaScript
106 lines
3.8 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import fs from 'node:fs';
|
|
import os from 'node:os';
|
|
import path from 'node:path';
|
|
import test from 'node:test';
|
|
import {
|
|
buildHealthReportHtml,
|
|
defaultHealthReportFilename,
|
|
looksLikeHealthReportPageRequest,
|
|
resolveHealthMaterializeH5Root,
|
|
writeHealthReportPage,
|
|
healthReportPageExists,
|
|
} from './health-report-page.mjs';
|
|
import {
|
|
sanitizeHealthReportDeliveryText,
|
|
sanitizeHealthAssistantReportDelivery,
|
|
} from './health-report-finish-guard.mjs';
|
|
|
|
test('looksLikeHealthReportPageRequest matches common phrases', () => {
|
|
assert.equal(looksLikeHealthReportPageRequest('帮我生成一份健康报告'), true);
|
|
assert.equal(looksLikeHealthReportPageRequest('最近血压怎么样'), false);
|
|
});
|
|
|
|
test('resolveHealthMaterializeH5Root follows remote MindSpace service root', () => {
|
|
const portalRoot = '/tmp/health-portal';
|
|
assert.equal(
|
|
resolveHealthMaterializeH5Root(portalRoot, {
|
|
MINDSPACE_SERVER_ADAPTER: 'local',
|
|
}),
|
|
path.resolve(portalRoot),
|
|
);
|
|
assert.equal(
|
|
resolveHealthMaterializeH5Root(portalRoot, {
|
|
MINDSPACE_SERVER_ADAPTER: 'remote',
|
|
MINDSPACE_SERVICE_H5_ROOT: '/Users/john/Project/Memind',
|
|
}),
|
|
path.resolve('/Users/john/Project/Memind'),
|
|
);
|
|
});
|
|
|
|
test('writeHealthReportPage materializes html on disk', () => {
|
|
const h5Root = fs.mkdtempSync(path.join(os.tmpdir(), 'health-report-'));
|
|
const userId = '11111111-1111-1111-1111-111111111111';
|
|
const observations = [{
|
|
confirmed: true,
|
|
observedAt: Date.now(),
|
|
metricType: 'bp_systolic',
|
|
valueNum: 128,
|
|
unit: 'mmHg',
|
|
context: 'morning',
|
|
source: 'manual',
|
|
qualityFlag: 'ok',
|
|
}, {
|
|
confirmed: true,
|
|
observedAt: Date.now(),
|
|
metricType: 'bp_diastolic',
|
|
valueNum: 80,
|
|
unit: 'mmHg',
|
|
context: 'morning',
|
|
source: 'manual',
|
|
qualityFlag: 'ok',
|
|
}];
|
|
const filename = defaultHealthReportFilename();
|
|
const written = writeHealthReportPage({ h5Root, userId, observations, filename });
|
|
assert.equal(written.relativePath, `public/${filename}`);
|
|
assert.ok(fs.existsSync(written.absolutePath));
|
|
assert.match(fs.readFileSync(written.absolutePath, 'utf8'), /本人健康报告/);
|
|
assert.equal(healthReportPageExists(h5Root, userId, written.relativePath), true);
|
|
});
|
|
|
|
test('sanitizeHealthReportDeliveryText strips unverified health report links', () => {
|
|
const userId = '11111111-1111-1111-1111-111111111111';
|
|
const h5Root = fs.mkdtempSync(path.join(os.tmpdir(), 'health-report-guard-'));
|
|
const url = `http://127.0.0.1:8087/MindSpace/${userId}/public/health-report-2026-09-02.html`;
|
|
const text = `报告在这里:[健康报告](${url})`;
|
|
const result = sanitizeHealthReportDeliveryText(text, { userId, h5Root });
|
|
assert.equal(result.stripped, true);
|
|
assert.match(result.text, /链接已移除/);
|
|
});
|
|
|
|
test('sanitizeHealthAssistantReportDelivery only applies to health-assistant runs', () => {
|
|
const userId = '11111111-1111-1111-1111-111111111111';
|
|
const h5Root = fs.mkdtempSync(path.join(os.tmpdir(), 'health-report-guard2-'));
|
|
const url = `http://127.0.0.1:8087/MindSpace/${userId}/public/health-report-2026-09-02.html`;
|
|
const messages = [
|
|
{
|
|
role: 'user',
|
|
metadata: { memindRun: { selectedChatSkill: 'health-assistant' } },
|
|
content: [{ type: 'text', text: '生成健康报告' }],
|
|
},
|
|
{
|
|
role: 'assistant',
|
|
content: [{ type: 'text', text: `[报告](${url})` }],
|
|
},
|
|
];
|
|
const result = sanitizeHealthAssistantReportDelivery(messages, { userId, h5Root });
|
|
assert.equal(result.changed, true);
|
|
assert.match(result.messages[1].content[0].text, /链接已移除/);
|
|
});
|
|
|
|
test('buildHealthReportHtml includes assess summary block', () => {
|
|
const html = buildHealthReportHtml([], { now: Date.parse('2026-09-02T08:00:00+08:00') });
|
|
assert.match(html, /noindex/);
|
|
assert.match(html, /概况/);
|
|
});
|