Files
memind/user-publish.test.mjs
T
John 6ee6fd64dd Add MindSpace page live edit, chat skills, and H5 deploy tooling.
Introduce page edit sessions with draft preview and patch API, chat skill picker, user memory profile, h5ApiBase resolution, voice WAV transport, and scripts for 105/g2 deployment and Plaza local dev.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-15 22:09:38 -07:00

115 lines
4.6 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import {
buildPublicUrl,
buildPublicZonePageUrl,
buildPublishConstraints,
buildSandboxSessionConstraints,
ensureUserPublishLayout,
isPathInsidePublishDir,
migrateUserPublishDir,
PUBLISH_ROOT_DIR,
PUBLIC_ZONE_DIR,
resolveLegacyPublishDir,
} from './user-publish.mjs';
import { syncSkillsToWorkspace } from './skills-registry.mjs';
import { listPlatformSkillCatalog } from './skills-registry.mjs';
const USER_ID = 'a6fb1e97-2b0f-447b-b138-4561d8e5c53e';
test('publish dir and public url use stable user id', () => {
const platformRoot = path.dirname(fileURLToPath(import.meta.url));
const h5Root = fs.mkdtempSync(path.join(os.tmpdir(), 'h5-'));
const layout = ensureUserPublishLayout({
h5Root,
publicBaseUrl: 'https://g2.tkmind.cn',
user: { id: USER_ID, username: 'john' },
});
assert.equal(layout.slug, USER_ID);
assert.equal(layout.username, 'john');
assert.ok(layout.publishDir.endsWith(`${path.sep}${PUBLISH_ROOT_DIR}${path.sep}${USER_ID}`));
assert.equal(layout.publicUrl, `https://g2.tkmind.cn/${PUBLISH_ROOT_DIR}/${USER_ID}/`);
assert.equal(
buildPublicUrl('https://g2.tkmind.cn', USER_ID, 'report.html'),
`https://g2.tkmind.cn/${PUBLISH_ROOT_DIR}/${USER_ID}/report.html`,
);
assert.equal(
buildPublicZonePageUrl('https://g2.tkmind.cn', USER_ID, 'report.html'),
`https://g2.tkmind.cn/${PUBLISH_ROOT_DIR}/${USER_ID}/${PUBLIC_ZONE_DIR}/report.html`,
);
assert.equal(
buildPublicZonePageUrl('https://g2.tkmind.cn', USER_ID, `${PUBLIC_ZONE_DIR}/report.html`),
`https://g2.tkmind.cn/${PUBLISH_ROOT_DIR}/${USER_ID}/${PUBLIC_ZONE_DIR}/report.html`,
);
const catalog = listPlatformSkillCatalog(platformRoot);
syncSkillsToWorkspace({
h5Root: platformRoot,
publishDir: layout.publishDir,
skillMap: { 'static-page-publish': true },
catalog,
user: { id: USER_ID, username: 'john' },
publicBaseUrl: 'https://g2.tkmind.cn',
});
const skillPath = path.join(layout.publishDir, '.agents', 'skills', 'static-page-publish', 'SKILL.md');
assert.ok(fs.existsSync(skillPath));
const skillText = fs.readFileSync(skillPath, 'utf8');
assert.match(skillText, new RegExp(`g2\\.tkmind\\.cn/${PUBLISH_ROOT_DIR}/${USER_ID}/${PUBLIC_ZONE_DIR}/`));
assert.match(skillText, /public\/report\.html/);
assert.match(skillText, /\[.*\]\(.*\)/);
assert.match(skillText, /mindspace-cover/);
assert.match(skillText, /\.thumbnail\.svg/);
});
test('migrateUserPublishDir merges legacy username directory', () => {
const h5Root = fs.mkdtempSync(path.join(os.tmpdir(), 'h5-'));
const legacyDir = resolveLegacyPublishDir(h5Root, { username: 'john' });
fs.mkdirSync(legacyDir, { recursive: true });
fs.writeFileSync(path.join(legacyDir, 'legacy.html'), '<html></html>');
const layout = ensureUserPublishLayout({
h5Root,
publicBaseUrl: 'https://g2.tkmind.cn',
user: { id: USER_ID, username: 'john' },
});
assert.ok(fs.existsSync(path.join(layout.publishDir, 'legacy.html')));
});
test('buildPublishConstraints scopes default search to user workspace', () => {
const publishDir = `/var/h5/${PUBLISH_ROOT_DIR}/${USER_ID}`;
const constraints = buildPublishConstraints({
slug: USER_ID,
username: 'john',
displayName: 'John',
publicBaseUrl: 'https://g2.tkmind.cn',
publishDir,
});
assert.match(constraints, /唯一文件根目录/);
assert.match(constraints, /禁止把用户叫作 TKMind/);
assert.match(constraints, /\*\*John\*\*/);
assert.doesNotMatch(constraints, /对用户统一称 \*\*TKMind\*\*/);
assert.match(constraints, /禁止用公网 URL 列目录/);
assert.match(constraints, /public\/页面\.html/);
assert.match(constraints, /\/public\//);
});
test('buildSandboxSessionConstraints documents shell and forbids public url browsing', () => {
const text = buildSandboxSessionConstraints({
baseConstraints: 'base',
developerTools: ['write', 'edit', 'shell', 'tree'],
});
assert.match(text, /shell 已开启/);
assert.match(text, /禁止.*curl/);
assert.match(text, /tree 已开启/);
assert.match(text, /public\/xxx\.html/);
assert.match(text, /\/public\//);
});
test('isPathInsidePublishDir blocks escape', () => {
const publishDir = `/var/h5/${PUBLISH_ROOT_DIR}/${USER_ID}`;
assert.equal(isPathInsidePublishDir(publishDir, `/var/h5/${PUBLISH_ROOT_DIR}/${USER_ID}/report.html`), true);
assert.equal(isPathInsidePublishDir(publishDir, `/var/h5/${PUBLISH_ROOT_DIR}/other-id/x.html`), false);
});