/** * Integration guide module — 7-tier tests (unit through security). */ import { describe, it } from 'node:test'; import assert from 'node:assert/strict'; import { readFileSync } from 'node:fs'; import { fileURLToPath } from 'node:url'; import { dirname, join } from 'node:path'; import { INTEGRATION_GUIDES, getIntegrationGuide, listIntegrationGuideIds, renderIntegrationGuideHtml, escapeHtml, wireIntegrationTiles, } from '../web/hub/hub-integration-guides.mjs'; const root = join(dirname(fileURLToPath(import.meta.url)), '..'); const hubIndex = readFileSync(join(root, 'web/hub/index.html'), 'utf8'); const hubJs = readFileSync(join(root, 'web/hub/hub.js'), 'utf8'); describe('hub-integration-guides — unit', () => { it('lists every expected capture and import tile id', () => { const ids = listIntegrationGuideIds(); for (const id of [ 'slack', 'discord', 'telegram', 'whatsapp', 'chatgpt-export', 'claude-export', 'openclaw', 'hermes', 'imports', ]) { assert.ok(ids.includes(id), `missing guide: ${id}`); } }); it('getIntegrationGuide returns null for unknown ids', () => { assert.equal(getIntegrationGuide(''), null); assert.equal(getIntegrationGuide('not-a-source'), null); }); it('hermes guide includes export and markdown import commands', () => { const g = getIntegrationGuide('hermes'); assert.ok(g); const code = g.sections.filter((s) => s.type === 'code').map((s) => s.code).join('\n'); assert.match(code, /hermes memory export/); assert.match(code, /knowtation import markdown/); assert.match(code, /MEMORY\.md/); }); it('imports guide merges local and team paths', () => { const g = getIntegrationGuide('imports'); assert.ok(g); assert.equal(g.name, 'Imports'); const text = g.sections.filter((s) => s.type === 'text').map((s) => s.html).join(' '); assert.match(text, /Local/i); assert.match(text, /Team/i); }); it('escapeHtml neutralizes script injection in code blocks', () => { const out = escapeHtml(''); assert.equal(out, '<script>alert(1)</script>'); }); it('renderIntegrationGuideHtml escapes code but preserves author text html', () => { const g = getIntegrationGuide('slack'); assert.ok(g); const html = renderIntegrationGuideHtml(g); assert.match(html, /integ-guide-code-block/); assert.doesNotMatch(html, /