test: specify memory graph query APIs
This commit is contained in:
54
tests/identity-db.test.ts
Normal file
54
tests/identity-db.test.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
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('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.');
|
||||
});
|
||||
});
|
||||
84
tests/queries.test.ts
Normal file
84
tests/queries.test.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
||||
|
||||
import { IdentityDB } from '../src/core/identity-db';
|
||||
|
||||
async function seedMemoryGraph(db: IdentityDB): Promise<void> {
|
||||
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' },
|
||||
],
|
||||
});
|
||||
|
||||
await db.addFact({
|
||||
statement: 'TypeScript is a programming language.',
|
||||
topics: [
|
||||
{ name: 'TypeScript', category: 'entity', granularity: 'concrete', role: 'subject' },
|
||||
{ name: 'programming language', category: 'concept', granularity: 'abstract', role: 'classification' },
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
describe('IdentityDB queries', () => {
|
||||
let db: IdentityDB;
|
||||
|
||||
beforeEach(async () => {
|
||||
db = await IdentityDB.connect({ client: 'sqlite', filename: ':memory:' });
|
||||
await db.initialize();
|
||||
await seedMemoryGraph(db);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await db.close();
|
||||
});
|
||||
|
||||
it('gets a topic with its facts', async () => {
|
||||
const topic = await db.getTopicByName('TypeScript', { includeFacts: true });
|
||||
|
||||
expect(topic).not.toBeNull();
|
||||
expect(topic?.name).toBe('TypeScript');
|
||||
expect(topic?.facts).toHaveLength(2);
|
||||
expect(topic?.facts.map((fact) => fact.statement)).toEqual([
|
||||
'I have worked with TypeScript since 2025.',
|
||||
'TypeScript is a programming language.',
|
||||
]);
|
||||
});
|
||||
|
||||
it('gets only the facts linked to another topic', async () => {
|
||||
const facts = await db.getTopicFactsLinkedTo('TypeScript', '2025');
|
||||
|
||||
expect(facts).toHaveLength(1);
|
||||
expect(facts[0]?.statement).toBe('I have worked with TypeScript since 2025.');
|
||||
});
|
||||
|
||||
it('lists topics without expanding facts', async () => {
|
||||
const topics = await db.listTopics({ includeFacts: false });
|
||||
|
||||
expect(topics.map((topic) => topic.name)).toEqual([
|
||||
'2025',
|
||||
'I',
|
||||
'programming language',
|
||||
'TypeScript',
|
||||
]);
|
||||
expect('facts' in topics[0]!).toBe(false);
|
||||
});
|
||||
|
||||
it('finds connected topics with shared fact counts', async () => {
|
||||
const connectedTopics = await db.findConnectedTopics('TypeScript');
|
||||
|
||||
expect(connectedTopics).toEqual([
|
||||
expect.objectContaining({ name: '2025', sharedFactCount: 1 }),
|
||||
expect.objectContaining({ name: 'I', sharedFactCount: 1 }),
|
||||
expect.objectContaining({ name: 'programming language', sharedFactCount: 1 }),
|
||||
]);
|
||||
});
|
||||
|
||||
it('finds facts that connect all requested topics', async () => {
|
||||
const facts = await db.findFactsConnectingTopics(['I', 'TypeScript', '2025']);
|
||||
|
||||
expect(facts).toHaveLength(1);
|
||||
expect(facts[0]?.statement).toBe('I have worked with TypeScript since 2025.');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user