import { afterEach, beforeEach, describe, expect, it } from 'vitest'; import { IdentityDB } from '../src/core/identity-db'; describe('IdentityDB topic and fact writes', () => { let db: IdentityDB; beforeEach(async () => { db = await IdentityDB.connect({ client: 'sqlite', filename: ':memory:' }); await db.initialize(); }); afterEach(async () => { await db.close(); }); it('deduplicates topics by normalized name during upsert', async () => { const first = await db.upsertTopic({ name: 'TypeScript', category: 'entity', granularity: 'concrete', }); const second = await db.upsertTopic({ name: ' typescript ', category: 'entity', granularity: 'concrete', }); expect(second.id).toBe(first.id); expect(second.normalizedName).toBe('typescript'); const topics = await db.listTopics({ includeFacts: false }); expect(topics).toHaveLength(1); }); it('keeps same normalized topic names isolated across spaces', async () => { const alpha = await db.upsertTopic({ name: 'TypeScript', category: 'entity', granularity: 'concrete', spaceName: 'A', }); const beta = await db.upsertTopic({ name: 'TypeScript', category: 'entity', granularity: 'concrete', spaceName: 'B', }); expect(beta.id).not.toBe(alpha.id); const alphaTopics = await db.listTopics({ includeFacts: false, spaceName: 'A' }); const betaTopics = await db.listTopics({ includeFacts: false, spaceName: 'B' }); const defaultTopics = await db.listTopics({ includeFacts: false }); expect(alphaTopics.map((topic) => topic.name)).toEqual(['TypeScript']); expect(betaTopics.map((topic) => topic.name)).toEqual(['TypeScript']); expect(defaultTopics).toHaveLength(0); }); it('keeps alias resolution scoped to the requested space', async () => { await db.upsertTopic({ name: 'TypeScript', category: 'entity', granularity: 'concrete', spaceName: 'A', }); await db.upsertTopic({ name: 'TeamSpeak', category: 'entity', granularity: 'concrete', spaceName: 'B', }); await db.addTopicAlias('TypeScript', 'TS', { spaceName: 'A' }); await db.addTopicAlias('TeamSpeak', 'TS', { spaceName: 'B' }); const alphaResolved = await db.resolveTopic('ts', { spaceName: 'A' }); const betaResolved = await db.resolveTopic('ts', { spaceName: 'B' }); const defaultResolved = await db.resolveTopic('ts'); expect(alphaResolved?.name).toBe('TypeScript'); expect(betaResolved?.name).toBe('TeamSpeak'); expect(defaultResolved).toBeNull(); }); it('adds one fact that links multiple topics', async () => { const fact = await db.addFact({ statement: 'I have worked with TypeScript since 2025.', topics: [ { name: 'I', category: 'entity', granularity: 'concrete', role: 'subject' }, { name: 'TypeScript', category: 'entity', granularity: 'concrete', role: 'object' }, { name: '2025', category: 'temporal', granularity: 'concrete', role: 'time' }, ], }); expect(fact.statement).toBe('I have worked with TypeScript since 2025.'); expect(fact.topics.map((topic) => topic.name)).toEqual(['I', 'TypeScript', '2025']); const typeScriptFacts = await db.getTopicFacts('TypeScript'); expect(typeScriptFacts).toHaveLength(1); expect(typeScriptFacts[0]?.statement).toBe('I have worked with TypeScript since 2025.'); }); it('resolves alias names to a canonical topic', async () => { await db.upsertTopic({ name: 'TypeScript', category: 'entity', granularity: 'concrete', }); await db.addTopicAlias('TypeScript', 'TS'); const resolved = await db.resolveTopic('ts'); const aliases = await db.getTopicAliases('TypeScript'); expect(resolved?.name).toBe('TypeScript'); expect(aliases).toEqual(['TS']); }); it('reuses the canonical topic when a fact is added through an alias', async () => { await db.upsertTopic({ name: 'TypeScript', category: 'entity', granularity: 'concrete', }); await db.addTopicAlias('TypeScript', 'TS'); await db.addFact({ statement: 'TS compiles to JavaScript.', topics: [{ name: 'TS', category: 'entity', granularity: 'concrete' }], }); const topics = await db.listTopics({ includeFacts: false }); const facts = await db.getTopicFacts('TypeScript'); expect(topics.map((topic) => topic.name)).toEqual(['TypeScript']); expect(facts.map((fact) => fact.statement)).toEqual(['TS compiles to JavaScript.']); }); });