Files
memind/server/portal-domain-services-bootstrap.test.mjs
T

419 lines
11 KiB
JavaScript

import assert from 'node:assert/strict';
import test from 'node:test';
import { bootstrapPortalDomainServices } from './portal-domain-services-bootstrap.mjs';
function createBootstrapSetup(overrides = {}) {
const calls = [];
const pool = {
async query(sql, params) {
calls.push({ kind: 'query', sql, params });
if (sql.includes('agent_session_id')) {
return [[{ user_id: 'agent-user' }]];
}
if (sql.includes('username')) {
return [[{ id: 'named-user' }]];
}
return [[]];
},
};
const pageService = {
findPageByRelativePath() {},
};
const adapter = {
serviceFacade: { id: 'facade' },
conversationPackageRegistry: { id: 'registry' },
assetService: { id: 'assets' },
pageService,
pageSyncService: { id: 'page-sync' },
pageLiveEditService: { id: 'live-edit' },
assetAgentService: { id: 'asset-agent' },
publicationService: { id: 'publications' },
cleanupService: { id: 'cleanup' },
assertReady() {
calls.push({ kind: 'adapter-ready' });
},
};
const plazaRedis = {
enabled: true,
invalidateFeedCaches() {
calls.push({ kind: 'invalidate-feed' });
},
};
let adapterOptions = null;
let pageDataOptions = null;
let pageDataPublicOptions = null;
let workspaceDeliverOptions = null;
let plazaPostOptions = null;
let plazaOpsOptions = null;
const dependencies = {
pool,
h5Root: '/workspace',
env: {
H5_DEFAULT_TIMEZONE: 'Asia/Singapore',
PLAZA_REDIS_URL: 'redis://plaza',
},
runtime: {
maxFileBytes: 100,
aiDailyLimit: 2,
publicPageLimit: 3,
monthlyViewLimit: 4,
remote: { enabled: false },
},
analyticsConfig: {
enabled: false,
hostPath: '/old',
},
getUserAuth: () => ({
resolveWorkingDir: (userId) => `/users/${userId}`,
}),
getSessionSnapshotService: () => ({
get: (sessionId) => ({ sessionId }),
}),
onMindSearchSchemaReady({ pool: receivedPool }) {
assert.equal(receivedPool, pool);
calls.push({ kind: 'auth-pool-ready' });
},
registerPublicHtmlArtifactsForConversation() {},
workspaceMaintenanceEnabled: true,
logger: {
log(message) {
calls.push({ kind: 'log', message });
},
},
async initSchemaFn(receivedPool) {
assert.equal(receivedPool, pool);
calls.push({ kind: 'init-schema' });
},
createMindSearchConfigServiceFn(receivedPool) {
assert.equal(receivedPool, pool);
return {
async ensureSchema() {
calls.push({ kind: 'mind-search-schema' });
},
};
},
async ensureMindSpaceConfigFn(receivedPool, options) {
assert.equal(receivedPool, pool);
calls.push({ kind: 'mindspace-config', options });
},
async loadMindSpaceConfigFn() {
calls.push({ kind: 'load-mindspace-config' });
return {
analytics: {
enabled: true,
websiteId: 'website-1',
idSecret: 'secret-1',
},
};
},
createScheduleServiceFn(receivedPool, options) {
calls.push({ kind: 'schedule', receivedPool, options });
return { id: 'schedule' };
},
createPageDataServiceFn(options) {
pageDataOptions = options;
return { id: 'page-data' };
},
createPageDataPublicServiceFn(options) {
pageDataPublicOptions = options;
return { id: 'page-data-public' };
},
createFeedbackServiceFn() {
return { id: 'feedback' };
},
createMindSpaceServiceFn(receivedPool, options) {
calls.push({ kind: 'mindspace', receivedPool, options });
return { id: 'mindspace' };
},
createMindSpaceServerAdapterFn(options) {
adapterOptions = options;
return adapter;
},
assertMindSpaceServerAdapterContractFn(received) {
calls.push({ kind: 'adapter-contract' });
return received;
},
createWorkspacePageDeliverServiceFn(options) {
workspaceDeliverOptions = options;
return { id: 'workspace-deliver' };
},
ensurePageDataHtmlPagesBoundFn() {},
resolveMindSpaceRuntimeConfigFn() {
return { storageRoot: '/storage' };
},
async ensureAlgorithmConfigFn() {
calls.push({ kind: 'algorithm-schema' });
},
async loadAlgorithmConfigFn() {
calls.push({ kind: 'algorithm-load' });
return { version: 1 };
},
async createPlazaRedisFn(url, receivedPool) {
calls.push({ kind: 'redis', url, receivedPool });
return plazaRedis;
},
createPlazaSeoServiceFn() {
return {
notifyPostPublished(postId) {
calls.push({ kind: 'seo-published', postId });
},
};
},
createPlazaInteractionServiceFn(_pool, options) {
calls.push({ kind: 'interactions', options });
return {
async loadViewerReactions(viewerId, postIds) {
calls.push({
kind: 'viewer-reactions',
viewerId,
postIds,
});
return {};
},
};
},
createPlazaEventServiceFn() {
return { id: 'events' };
},
createPlazaRecommendServiceFn(_pool, options) {
calls.push({ kind: 'recommend', options });
return { id: 'recommend' };
},
createPlazaPostServiceFn(_pool, options) {
plazaPostOptions = options;
return {
reviewPost(...args) {
calls.push({ kind: 'review-post', args });
},
};
},
createPlazaOpsServiceFn(_pool, options) {
plazaOpsOptions = options;
return {
async loadActiveFeaturedPosts(viewerId) {
return { viewerId };
},
};
},
startPlazaTasksFn(options) {
calls.push({ kind: 'plaza-tasks', options });
},
recalculateHotScoresFn() {},
writebackPublicationsFn() {},
formatPostRowFn() {},
publishKeyUuid: /^uuid-/,
...overrides,
};
return {
calls,
pool,
adapter,
pageService,
plazaRedis,
dependencies,
captured: {
get adapterOptions() {
return adapterOptions;
},
get pageDataOptions() {
return pageDataOptions;
},
get pageDataPublicOptions() {
return pageDataPublicOptions;
},
get workspaceDeliverOptions() {
return workspaceDeliverOptions;
},
get plazaPostOptions() {
return plazaPostOptions;
},
get plazaOpsOptions() {
return plazaOpsOptions;
},
},
};
}
test('domain bootstrap requires pool, runtime, and artifact registration', async () => {
await assert.rejects(
() => bootstrapPortalDomainServices(),
/requires pool and runtime/,
);
await assert.rejects(
() =>
bootstrapPortalDomainServices({
pool: {},
runtime: {},
}),
/requires artifact registration/,
);
});
test('domain bootstrap preserves schema and service assembly order', async () => {
const setup = createBootstrapSetup();
const result = await bootstrapPortalDomainServices(
setup.dependencies,
);
assert.deepEqual(
setup.calls
.filter((call) =>
[
'mind-search-schema',
'auth-pool-ready',
'init-schema',
'mindspace-config',
'load-mindspace-config',
'adapter-contract',
'adapter-ready',
'algorithm-schema',
'algorithm-load',
'redis',
'plaza-tasks',
].includes(call.kind),
)
.map((call) => call.kind),
[
'mind-search-schema',
'auth-pool-ready',
'init-schema',
'mindspace-config',
'load-mindspace-config',
'adapter-contract',
'adapter-ready',
'algorithm-schema',
'algorithm-load',
'redis',
'plaza-tasks',
],
);
assert.equal(result.mindSpace.id, 'mindspace');
assert.equal(result.mindSpaceAssets.id, 'assets');
assert.equal(result.mindSpacePages, setup.pageService);
assert.equal(result.workspacePageDeliver.id, 'workspace-deliver');
assert.equal(result.mindSpaceCleanup.id, 'cleanup');
assert.equal(result.plazaRedis, setup.plazaRedis);
assert.equal(
result.mindSpaceAnalyticsConfig.enabled,
true,
);
assert.equal(
result.mindSpaceAnalyticsConfig.hostPath,
'/analytics',
);
assert.equal(
result.mindSpaceAnalyticsConfig.scriptPath,
'/analytics/script.js',
);
});
test('domain bootstrap preserves delayed user, snapshot, and Page Data dependencies', async () => {
let activeUserAuth = {
resolveWorkingDir: (userId) => `/first/${userId}`,
};
const snapshot = { id: 'snapshot-1' };
const setup = createBootstrapSetup({
getUserAuth: () => activeUserAuth,
getSessionSnapshotService: () => ({
get: () => snapshot,
}),
});
await bootstrapPortalDomainServices(setup.dependencies);
assert.equal(
await setup.captured.pageDataOptions.resolveWorkspaceRoot({
workspaceRoot: '/explicit',
}),
'/explicit',
);
activeUserAuth = {
resolveWorkingDir: (userId) => `/second/${userId}`,
};
assert.equal(
await setup.captured.pageDataOptions.resolveWorkspaceRoot({
id: 'user-1',
}),
'/second/user-1',
);
assert.equal(
setup.captured.pageDataPublicOptions.getPool(),
setup.pool,
);
assert.equal(
setup.captured.pageDataPublicOptions.resolveH5Root(),
'/workspace',
);
assert.equal(
setup.captured.adapterOptions.resolveWorkspaceRoot(
'user-2',
),
'/second/user-2',
);
assert.equal(
setup.captured.adapterOptions.resolveSessionSnapshot(
'session-1',
),
snapshot,
);
assert.equal(
await setup.captured.adapterOptions.resolveUserIdForAgentSession(
'session-1',
),
'agent-user',
);
assert.equal(
setup.captured.adapterOptions.syncWorkspaceAssetsEnabled,
true,
);
assert.equal(
setup.captured.workspaceDeliverOptions.storageRoot,
'/storage',
);
});
test('domain bootstrap preserves directory and Plaza cross-service callbacks', async () => {
const setup = createBootstrapSetup();
const result = await bootstrapPortalDomainServices(
setup.dependencies,
);
assert.equal(
await result.resolveUserIdByDirKey('uuid-user'),
'uuid-user',
);
assert.equal(
await result.resolveUserIdByDirKey('alice'),
'named-user',
);
assert.deepEqual(
await setup.captured.plazaPostOptions.loadFeaturedPosts(
'viewer-1',
),
{ viewerId: 'viewer-1' },
);
setup.captured.plazaPostOptions.onPostPublished('post-1');
await setup.captured.plazaPostOptions.loadViewerReactions(
'viewer-1',
['post-1'],
);
setup.captured.plazaOpsOptions.reviewPost('post-1');
setup.captured.plazaOpsOptions.invalidateFeedCaches();
assert.deepEqual(
setup.calls
.filter((call) =>
[
'seo-published',
'viewer-reactions',
'review-post',
'invalidate-feed',
].includes(call.kind),
)
.map((call) => call.kind),
[
'seo-published',
'viewer-reactions',
'review-post',
'invalidate-feed',
],
);
});