144 lines
4.5 KiB
TypeScript
144 lines
4.5 KiB
TypeScript
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.']);
|
|
});
|
|
});
|