4e21ca937a
Deploy Documentation / deploy (push) Has been cancelled
Canary / Prepare Version (push) Has been cancelled
Canary / build-cli (push) Has been cancelled
Canary / Upload Install Script (push) Has been cancelled
Canary / bundle-desktop (push) Has been cancelled
Canary / bundle-desktop-intel (push) Has been cancelled
Canary / bundle-desktop-linux (push) Has been cancelled
Canary / bundle-desktop-windows (push) Has been cancelled
Canary / bundle-desktop-windows-cuda (push) Has been cancelled
Canary / Release (push) Has been cancelled
Unused Dependencies / machete (push) Has been cancelled
CI / changes (push) Has been cancelled
CI / Check Rust Code Format (push) Has been cancelled
CI / Build and Test Rust Project (push) Has been cancelled
CI / Build Rust Project on Windows (push) Has been cancelled
CI / Check MSRV (push) Has been cancelled
CI / Lint Rust Code (push) Has been cancelled
CI / Check Generated Schemas are Up-to-Date (push) Has been cancelled
CI / Test and Lint Electron Desktop App (push) Has been cancelled
CI / H5 Plaza Tests and Build (push) Has been cancelled
Live Provider Tests / check-fork (push) Has been cancelled
Live Provider Tests / changes (push) Has been cancelled
Live Provider Tests / Build Binary (push) Has been cancelled
Live Provider Tests / Smoke Tests (push) Has been cancelled
Live Provider Tests / Smoke Tests (Code Execution) (push) Has been cancelled
Live Provider Tests / Compaction Tests (push) Has been cancelled
Live Provider Tests / goose server HTTP integration tests (push) Has been cancelled
Publish Ask AI Bot Docker Image / docker (push) Has been cancelled
Publish Docker Image / docker (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
Fork goose with custom MCP widgets, platform extensions (aider, git, web, search), MindSpace H5 backend/frontend, Plaza/Ops UIs, and deploy scripts for tkmind.cn. Co-authored-by: Cursor <cursoragent@cursor.com>
106 lines
3.7 KiB
JavaScript
106 lines
3.7 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
import { pageInternals } from './mindspace-pages.mjs';
|
|
|
|
test('normalizePageInput trims values and constrains templates', () => {
|
|
const result = pageInternals.normalizePageInput({
|
|
title: ' 页面标题 ',
|
|
content: ' 页面正文 ',
|
|
templateId: 'unknown-template',
|
|
});
|
|
|
|
assert.equal(result.title, '页面标题');
|
|
assert.equal(result.content, '页面正文');
|
|
assert.equal(result.templateId, 'editorial');
|
|
assert.equal(result.contentBytes, Buffer.byteLength('页面正文'));
|
|
});
|
|
|
|
test('normalizePageInput rejects empty and oversized page content', () => {
|
|
assert.throws(
|
|
() => pageInternals.normalizePageInput({ title: '', content: '正文' }),
|
|
{ code: 'invalid_page_input' },
|
|
);
|
|
assert.throws(
|
|
() =>
|
|
pageInternals.normalizePageInput({
|
|
title: '页面',
|
|
content: '文'.repeat(400_000),
|
|
}),
|
|
{ code: 'page_content_too_large' },
|
|
);
|
|
});
|
|
|
|
test('normalizePageInput maps html content to static-html template', () => {
|
|
const result = pageInternals.normalizePageInput({
|
|
title: '页面',
|
|
content: '<!doctype html><html><body>Hi</body></html>',
|
|
contentFormat: 'html',
|
|
});
|
|
assert.equal(result.contentFormat, 'html');
|
|
assert.equal(result.templateId, 'static-html');
|
|
assert.equal(result.pageType, 'html');
|
|
});
|
|
|
|
test('renderHtmlPreview injects restrictive CSP', () => {
|
|
const html = pageInternals.renderHtmlPreview(
|
|
'<!doctype html><html><head></head><body><h1>Hi</h1></body></html>',
|
|
);
|
|
assert.match(html, /Content-Security-Policy/);
|
|
assert.match(html, /script-src 'none'/);
|
|
});
|
|
|
|
test('renderPublicationHtml serves html pages without escaping markup', () => {
|
|
const html = pageInternals.renderPublicationHtml({
|
|
page_type: 'html',
|
|
title: '麻婆豆腐',
|
|
summary: '川菜',
|
|
template_id: 'static-html',
|
|
version_no: 1,
|
|
content: '<!doctype html><html><head><title>麻婆豆腐</title></head><body><h1>麻婆豆腐</h1></body></html>',
|
|
});
|
|
assert.match(html, /<h1>麻婆豆腐<\/h1>/);
|
|
assert.doesNotMatch(html, /<h1>/);
|
|
assert.doesNotMatch(html, /MINDSPACE/);
|
|
});
|
|
|
|
test('preview rendering escapes active HTML and emits a restrictive CSP', () => {
|
|
const html = pageInternals.renderPreviewHtml({
|
|
title: '<script>alert(1)</script>',
|
|
summary: '<img src=x onerror=alert(1)>',
|
|
content: '# 标题\n\n<script>alert(2)</script>',
|
|
templateId: 'report',
|
|
versionNo: 2,
|
|
});
|
|
|
|
assert.match(html, /Content-Security-Policy/);
|
|
assert.match(html, /default-src 'none'/);
|
|
assert.doesNotMatch(html, /<script>alert/);
|
|
assert.match(html, /<script>alert/);
|
|
assert.match(html, /DRAFT · V2/);
|
|
});
|
|
|
|
test('previewContentSecurityPolicy allows external assets for html pages', () => {
|
|
const htmlCsp = pageInternals.previewContentSecurityPolicy('html');
|
|
assert.match(htmlCsp, /style-src 'unsafe-inline' https:/);
|
|
assert.match(htmlCsp, /img-src data: https:/);
|
|
|
|
const markdownCsp = pageInternals.previewContentSecurityPolicy('markdown');
|
|
assert.match(markdownCsp, /style-src 'unsafe-inline'/);
|
|
assert.doesNotMatch(markdownCsp, /https:/);
|
|
});
|
|
|
|
test('buildPageDeleteSummary lists cascade delete impact', () => {
|
|
const lines = pageInternals.buildPageDeleteSummary({
|
|
page: { title: '麻婆豆腐', versionCount: 2 },
|
|
onlinePublication: { publicUrl: '/u/john/pages/mapo' },
|
|
offlinePublicationCount: 1,
|
|
linkedAssets: [{ id: 'a1' }, { id: 'a2' }],
|
|
linkedAssetBytes: 2048,
|
|
linkedAgentJobCount: 1,
|
|
preservesSourceAsset: true,
|
|
});
|
|
assert.match(lines[0], /麻婆豆腐/);
|
|
assert.ok(lines.some((line) => line.includes('在线公开链接')));
|
|
assert.ok(lines.some((line) => line.includes('原始上传资料不会被删除')));
|
|
});
|