Files
memind/user-space.test.mjs
john 9b4a25799f Add smart ACK provider for WeChat MP replies
Replace fixed ackText with a rule-based AckProvider that picks
response templates by message type and intent (translate, summary,
rewrite, poster, ppt, mindmap, code, search, schedule). Pure sync,
zero I/O, auto-falls back to config.ackText on any error.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 15:19:03 +08:00

88 lines
3.1 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 {
buildUserSpaceConstraints,
ensureUserZoneDirs,
mirrorAssetToZone,
renderUserSpaceHints,
resolveUserWorkspaceRoot,
syncUserZonesFromAssets,
UPLOAD_ZONE_CODES,
} from './user-space.mjs';
const USER_ID = 'a6fb1e97-2b0f-447b-b138-4561d8e5c53e';
test('user workspace is MindSpace/<userId> with zone subdirs', () => {
const h5Root = fs.mkdtempSync(path.join(os.tmpdir(), 'h5-'));
const workspace = resolveUserWorkspaceRoot(h5Root, { id: USER_ID, username: 'john' });
assert.ok(workspace.endsWith(`${path.sep}MindSpace${path.sep}${USER_ID}`));
ensureUserZoneDirs(workspace);
for (const code of UPLOAD_ZONE_CODES) {
assert.ok(fs.existsSync(path.join(workspace, code)));
}
});
test('mirrorAssetToZone copies upload into oa/', () => {
const h5Root = fs.mkdtempSync(path.join(os.tmpdir(), 'h5-'));
const workspace = resolveUserWorkspaceRoot(h5Root, { id: USER_ID, username: 'john' });
const source = path.join(h5Root, 'source.csv');
fs.writeFileSync(source, 'a,b\n1,2\n');
const dest = mirrorAssetToZone({
workspaceRoot: workspace,
categoryCode: 'oa',
filename: 'export.csv',
sourcePath: source,
});
assert.equal(dest, path.join(workspace, 'oa', 'export.csv'));
assert.equal(fs.readFileSync(dest, 'utf8'), 'a,b\n1,2\n');
});
test('syncUserZonesFromAssets backfills from canonical storage', async () => {
const h5Root = fs.mkdtempSync(path.join(os.tmpdir(), 'h5-'));
const storageRoot = path.join(h5Root, 'data', 'mindspace');
const userId = USER_ID;
const storageKey = path.posix.join('users', userId, 'assets', 'a1', 'versions', 'v1');
const sourcePath = path.join(storageRoot, storageKey);
fs.mkdirSync(path.dirname(sourcePath), { recursive: true });
fs.writeFileSync(sourcePath, 'col\nval\n');
const workspace = resolveUserWorkspaceRoot(h5Root, { id: userId, username: 'john' });
const pool = {
async query() {
return [
[{ original_filename: '2025-12-06T13-34_export.csv', category_code: 'oa', storage_key: storageKey }],
];
},
};
const result = await syncUserZonesFromAssets(pool, storageRoot, userId, workspace);
assert.equal(result.mirrored, 1);
assert.ok(
fs.existsSync(path.join(workspace, 'oa', '2025-12-06T13-34_export.csv')),
);
});
test('user space publishing guidance points to sandbox file tools', () => {
const workspaceRoot = `/var/h5/MindSpace/${USER_ID}`;
const hints = renderUserSpaceHints({
username: 'john',
displayName: 'John',
slug: USER_ID,
workspaceRoot,
});
const constraints = buildUserSpaceConstraints({
username: 'john',
displayName: 'John',
slug: USER_ID,
workspaceRoot,
publicBaseUrl: 'https://m.tkmind.cn',
});
assert.match(hints, /write_file/);
assert.match(hints, /edit_file/);
assert.doesNotMatch(hints, /再使用 \\`write\\` 创建/);
assert.match(constraints, /write_file/);
assert.match(constraints, /edit_file/);
assert.doesNotMatch(constraints, /再用 `write` 写入/);
});