feat: finalize mindspace service extraction phase a
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
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 {
|
||||
buildMindSpaceCanonicalRedirect,
|
||||
decodeMindSpaceRouteSegment,
|
||||
recoverMisplacedMindSpacePublicHtml,
|
||||
resolveMindSpacePublicRequest,
|
||||
resolveMindSpaceHtmlFallbackRedirect,
|
||||
resolveMindSpacePublishOwnerKey,
|
||||
resolveMindSpacePublicRouteTarget,
|
||||
resolveMindSpaceSimilarHtmlRedirect,
|
||||
} from './mindspace-public-route.mjs';
|
||||
|
||||
test('resolveMindSpacePublishOwnerKey keeps uuid and resolves usernames', async () => {
|
||||
assert.equal(
|
||||
await resolveMindSpacePublishOwnerKey('123e4567-e89b-12d3-a456-426614174000'),
|
||||
'123e4567-e89b-12d3-a456-426614174000',
|
||||
);
|
||||
assert.equal(
|
||||
await resolveMindSpacePublishOwnerKey('John', async (username) => `${username}-id`),
|
||||
'john-id',
|
||||
);
|
||||
assert.equal(await resolveMindSpacePublishOwnerKey('../bad', async () => 'x'), null);
|
||||
});
|
||||
|
||||
test('public route target resolves inside publish root', () => {
|
||||
const result = resolveMindSpacePublicRouteTarget({
|
||||
h5Root: '/tmp/h5',
|
||||
ownerKey: 'user-1',
|
||||
parts: ['public', 'report.html'],
|
||||
});
|
||||
assert.equal(result.targetDir, path.resolve('/tmp/h5/MindSpace/user-1'));
|
||||
assert.equal(result.insideRoot, true);
|
||||
assert.equal(result.resolvedPath, path.resolve('/tmp/h5/MindSpace/user-1/public/report.html'));
|
||||
});
|
||||
|
||||
test('canonical redirect helpers normalize route paths', () => {
|
||||
assert.equal(buildMindSpaceCanonicalRedirect('user-1', ['public', 'a b.html']), '/MindSpace/user-1/public/a%20b.html');
|
||||
assert.equal(resolveMindSpaceSimilarHtmlRedirect({ ownerKey: 'user-1', relativePath: 'public/a b.html' }), '/MindSpace/user-1/public/a%20b.html');
|
||||
});
|
||||
|
||||
test('decodeMindSpaceRouteSegment safely decodes segments', () => {
|
||||
assert.equal(decodeMindSpaceRouteSegment('report%201.html'), 'report 1.html');
|
||||
assert.equal(decodeMindSpaceRouteSegment('%E4%B8%AD%E6%96%87'), '中文');
|
||||
});
|
||||
|
||||
test('resolveMindSpaceHtmlFallbackRedirect points html to public zone sibling', () => {
|
||||
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'ms-public-route-'));
|
||||
const targetDir = path.join(root, 'MindSpace', 'user-1');
|
||||
const publicDir = path.join(targetDir, 'public');
|
||||
fs.mkdirSync(publicDir, { recursive: true });
|
||||
fs.writeFileSync(path.join(publicDir, 'report.html'), 'ok');
|
||||
const redirect = resolveMindSpaceHtmlFallbackRedirect({
|
||||
ownerKey: 'user-1',
|
||||
targetDir,
|
||||
resolvedRoot: path.resolve(targetDir),
|
||||
rest: ['report.html'],
|
||||
});
|
||||
assert.equal(redirect, '/MindSpace/user-1/public/report.html');
|
||||
});
|
||||
|
||||
test('recoverMisplacedMindSpacePublicHtml copies misplaced file into public zone', async () => {
|
||||
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'ms-public-recover-'));
|
||||
const targetDir = path.join(root, 'MindSpace', 'user-1');
|
||||
fs.mkdirSync(path.join(root, 'public'), { recursive: true });
|
||||
fs.mkdirSync(targetDir, { recursive: true });
|
||||
fs.writeFileSync(path.join(root, 'public', 'report.html'), 'demo', { encoding: 'utf8', flag: 'w' });
|
||||
let ensured = null;
|
||||
const recovered = await recoverMisplacedMindSpacePublicHtml({
|
||||
h5Root: root,
|
||||
targetDir,
|
||||
resolvedRoot: path.resolve(targetDir),
|
||||
rest: ['public', 'report.html'],
|
||||
ensureThumbnail: async (...args) => {
|
||||
ensured = args;
|
||||
},
|
||||
logger: { warn() {} },
|
||||
});
|
||||
assert.equal(recovered, path.join(targetDir, 'public', 'report.html'));
|
||||
assert.equal(fs.existsSync(recovered), true);
|
||||
assert.deepEqual(ensured, [targetDir, 'public/report.html']);
|
||||
});
|
||||
|
||||
test('resolveMindSpacePublicRequest coordinates canonical redirect, serve, and not found', async () => {
|
||||
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'ms-public-request-'));
|
||||
const ownerKey = '123e4567-e89b-12d3-a456-426614174000';
|
||||
const targetDir = path.join(root, 'MindSpace', ownerKey);
|
||||
fs.mkdirSync(path.join(targetDir, 'public'), { recursive: true });
|
||||
fs.writeFileSync(path.join(targetDir, 'public', 'report.html'), 'demo');
|
||||
|
||||
const redirected = await resolveMindSpacePublicRequest({
|
||||
h5Root: root,
|
||||
requestPath: '/John/public/report.html',
|
||||
resolveUsernameToUserId: async () => ownerKey,
|
||||
});
|
||||
assert.deepEqual(redirected, {
|
||||
action: 'redirect',
|
||||
status: 301,
|
||||
location: `/MindSpace/${ownerKey}/public/report.html`,
|
||||
ownerKey,
|
||||
});
|
||||
|
||||
const served = await resolveMindSpacePublicRequest({
|
||||
h5Root: root,
|
||||
requestPath: `/${ownerKey}/public/report.html`,
|
||||
});
|
||||
assert.equal(served.action, 'serve');
|
||||
assert.equal(served.filePath, path.join(targetDir, 'public', 'report.html'));
|
||||
|
||||
const missing = await resolveMindSpacePublicRequest({
|
||||
h5Root: root,
|
||||
requestPath: `/${ownerKey}/public/missing.html`,
|
||||
});
|
||||
assert.deepEqual(missing, {
|
||||
action: 'not_found',
|
||||
reason: 'missing_file',
|
||||
ownerKey,
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user