Files
memind/mindspace-config.test.mjs
T
john 4e789663a1
Memind CI / Test, build, and release guards (push) Failing after 5m19s
feat(seo): index public online pages without confirmation
Drop the user_confirmed_at gate so public, online, unexpired pages can enter sitemap/llms and receive SEO/GEO tags. Defaults now enable all discovery switches; stored all-off config is still preserved until admin saves.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-13 15:51:48 +08:00

162 lines
5.4 KiB
JavaScript

import assert from 'node:assert/strict';
import test from 'node:test';
import {
defaultMindSpaceConfig,
defaultSeoGeoConfig,
ensureMindSpaceConfig,
loadMindSpaceConfig,
normalizeSeoGeoConfig,
updateMindSpaceConfig,
} from './mindspace-config.mjs';
test('defaultSeoGeoConfig enables all discovery switches', () => {
const config = defaultSeoGeoConfig();
assert.equal(config.enabled, true);
assert.equal(config.seo.enabled, true);
assert.equal(config.seo.sitemap, true);
assert.equal(config.seo.robotsTxt, true);
assert.equal(config.seo.baiduPush, true);
assert.equal(config.geo.enabled, true);
assert.equal(config.geo.jsonLd, true);
assert.equal(config.geo.llmsTxt, true);
});
test('defaultMindSpaceConfig falls back to env or 5', () => {
assert.equal(defaultMindSpaceConfig({ MINDSPACE_FREE_PUBLIC_PAGE_LIMIT: '8' }).publicPageLimit, 8);
assert.equal(defaultMindSpaceConfig({ MINDSPACE_FREE_PUBLIC_PAGE_LIMIT: '0' }).publicPageLimit, 5);
assert.deepEqual(defaultMindSpaceConfig().seoGeo, defaultSeoGeoConfig());
});
test('normalizeSeoGeoConfig merges nested switches', () => {
const config = normalizeSeoGeoConfig({
enabled: true,
seo: { enabled: true, sitemap: true },
geo: { enabled: true, llmsTxt: true },
});
assert.equal(config.enabled, true);
assert.equal(config.seo.sitemap, true);
assert.equal(config.geo.llmsTxt, true);
assert.equal(config.seo.baiduPush, true);
});
test('ensureMindSpaceConfig seeds the default row only when empty', async () => {
const calls = [];
const pool = {
async query(sql, params) {
calls.push({ sql, params });
if (sql.includes('COUNT(*) AS count')) return [[{ count: 0 }]];
return [[]];
},
};
await ensureMindSpaceConfig(pool, { env: { MINDSPACE_FREE_PUBLIC_PAGE_LIMIT: '9' } });
assert.equal(calls.length, 3);
assert.match(calls[0].sql, /CREATE TABLE IF NOT EXISTS mindspace_config/);
assert.match(calls[2].sql, /INSERT INTO mindspace_config/);
assert.deepEqual(calls[2].params.slice(0, 3), ['public_page_limit', '9', '公开页面数量上限']);
});
test('loadMindSpaceConfig keeps stored all-off seoGeo instead of new defaults', async () => {
const pool = {
async query(sql) {
if (sql.includes('FROM mindspace_config')) {
return [[
{
key: 'seo_geo_config',
value: JSON.stringify({
enabled: false,
seo: { enabled: false, canonical: true, sitemap: false, robotsTxt: false, baiduPush: false },
geo: { enabled: false, jsonLd: false, llmsTxt: false },
}),
},
]];
}
return [[]];
},
};
const config = await loadMindSpaceConfig(pool);
assert.equal(config.seoGeo.enabled, false);
assert.equal(config.seoGeo.seo.sitemap, false);
assert.equal(config.seoGeo.geo.jsonLd, false);
});
test('loadMindSpaceConfig merges stored config with fallback', async () => {
const pool = {
async query(sql) {
if (sql.includes('FROM mindspace_config')) {
return [[
{ key: 'public_page_limit', value: '12' },
{
key: 'seo_geo_config',
value: JSON.stringify({
enabled: true,
seo: { enabled: true, sitemap: true },
geo: { enabled: true, jsonLd: true },
}),
},
{ key: 'ignored', value: '99' },
]];
}
return [[]];
},
};
const config = await loadMindSpaceConfig(pool, { env: { MINDSPACE_FREE_PUBLIC_PAGE_LIMIT: '7' } });
assert.equal(config.publicPageLimit, 12);
assert.equal(config.seoGeo.enabled, true);
assert.equal(config.seoGeo.seo.sitemap, true);
assert.equal(config.seoGeo.geo.jsonLd, true);
});
test('updateMindSpaceConfig persists a positive integer limit', async () => {
const calls = [];
const pool = {
async query(sql, params) {
calls.push({ sql, params });
if (sql.includes('CREATE TABLE IF NOT EXISTS mindspace_config')) return [[]];
if (sql.includes('FROM mindspace_config')) {
return [[{ key: 'public_page_limit', value: '15' }]];
}
return [[]];
},
};
const config = await updateMindSpaceConfig(pool, { publicPageLimit: 15 });
assert.equal(config.publicPageLimit, 15);
assert.equal(calls.some(({ sql }) => sql.includes('ON DUPLICATE KEY UPDATE')), true);
});
test('analytics settings encrypt the id secret and only reveal it on internal loads', async () => {
const rows = new Map();
const pool = {
async query(sql, params = []) {
if (sql.includes('FROM mindspace_config')) {
return [[...rows].map(([key, value]) => ({ key, value }))];
}
if (sql.includes('ON DUPLICATE KEY UPDATE')) rows.set(params[0], params[1]);
return [[]];
},
};
const env = { TKMIND_SERVER__SECRET_KEY: 'test-server-secret' };
const publicConfig = await updateMindSpaceConfig(pool, {
analytics: {
enabled: true,
websiteId: 'website-1',
analyticsUrl: 'http://127.0.0.1:3200',
domains: 'localhost',
idSecret: 'analytics-secret',
},
}, { env });
assert.equal(publicConfig.analytics.enabled, true);
assert.equal(publicConfig.analytics.idSecretConfigured, true);
assert.equal('idSecret' in publicConfig.analytics, false);
assert.doesNotMatch(rows.get('analytics_id_secret'), /analytics-secret/);
const internalConfig = await loadMindSpaceConfig(pool, { env, includeAnalyticsSecret: true });
assert.equal(internalConfig.analytics.idSecret, 'analytics-secret');
});