Files
memind/mindspace-page-sync-service.test.mjs
john d3239ff292 fix: MindSpace remote sync, thumbnail fallback, and Plaza URL guards
Ensure page sync runs via pageSyncService in remote mode, fall back to
workspace HTML when storage assets are missing, and prevent production
Portal from linking to loopback Plaza URLs baked in at build time.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-05 07:57:04 +08:00

89 lines
2.8 KiB
JavaScript

import assert from 'node:assert/strict';
import fs from 'node:fs/promises';
import os from 'node:os';
import path from 'node:path';
import test from 'node:test';
import { createPageSyncService } from './mindspace-page-sync-service.mjs';
import { PUBLISH_ROOT_DIR } from './user-publish.mjs';
test('syncUserGeneratedPages registers html files from publish public dir', async () => {
const tmp = await fs.mkdtemp(path.join(os.tmpdir(), 'mindspace-page-sync-service-'));
const h5Root = tmp;
const userId = 'user-1';
const publishDir = path.join(h5Root, PUBLISH_ROOT_DIR, userId);
const html =
'<!doctype html><html><head><title>Sync Demo</title></head><body><h1>Hi</h1></body></html>';
await fs.mkdir(path.join(publishDir, 'public'), { recursive: true });
await fs.writeFile(path.join(publishDir, 'public/index.html'), html);
const calls = [];
const pageService = {
createFromChat: async (_userId, input, source) => {
calls.push({ input, source });
return { id: 'page-1' };
},
updatePage: async () => assert.fail('should create, not update'),
};
const pool = {
query: async (sql) => {
if (String(sql).includes('FROM h5_page_records')) return [[]];
return [[]];
},
};
const pageSyncService = createPageSyncService({
pool,
pageService,
assetService: null,
h5Root,
});
const result = await pageSyncService.syncUserGeneratedPages(userId);
assert.equal(result.created, 1);
assert.equal(calls.length, 1);
assert.equal(calls[0].input.title, 'Sync Demo');
assert.equal(calls[0].source.snapshot.relative_path, 'public/index.html');
});
test('syncUserGeneratedPages deduplicates concurrent sync for the same user', async () => {
const tmp = await fs.mkdtemp(path.join(os.tmpdir(), 'mindspace-page-sync-dedupe-'));
const h5Root = tmp;
const userId = 'user-1';
const publishDir = path.join(h5Root, PUBLISH_ROOT_DIR, userId);
await fs.mkdir(path.join(publishDir, 'public'), { recursive: true });
await fs.writeFile(
path.join(publishDir, 'public/index.html'),
'<html><head><title>Dedupe</title></head><body>Hi</body></html>',
);
let active = 0;
let maxActive = 0;
const pageService = {
createFromChat: async () => {
active += 1;
maxActive = Math.max(maxActive, active);
await new Promise((resolve) => setTimeout(resolve, 20));
active -= 1;
return { id: 'page-1' };
},
};
const pool = {
query: async (sql) => {
if (String(sql).includes('FROM h5_page_records')) return [[]];
return [[]];
},
};
const pageSyncService = createPageSyncService({
pool,
pageService,
h5Root,
});
await Promise.all([
pageSyncService.syncUserGeneratedPages(userId),
pageSyncService.syncUserGeneratedPages(userId),
]);
assert.equal(maxActive, 1);
});