brainy/tests/unit/type-matching.unit.test.ts

218 lines
6.8 KiB
TypeScript
Raw Normal View History

/**
* Tests for Intelligent Type Matching with embeddings
*/
import { describe, it, expect, beforeAll, afterAll } from 'vitest'
import { IntelligentTypeMatcher } from '../../src/augmentations/typeMatching/intelligentTypeMatcher.js'
import { NounType, VerbType } from '../../src/types/graphTypes.js'
describe('Intelligent Type Matching', () => {
let matcher: IntelligentTypeMatcher
beforeAll(async () => {
matcher = new IntelligentTypeMatcher()
await matcher.init()
})
afterAll(async () => {
await matcher.dispose()
})
describe('Noun Type Detection', () => {
it('should detect Person type from user data', async () => {
const result = await matcher.matchNounType({
name: 'John Doe',
email: 'john@example.com',
age: 30
})
expect(result.type).toBeDefined()
expect(result.confidence).toBeGreaterThan(0)
expect(result.alternatives).toBeDefined()
expect(result.alternatives.length).toBeGreaterThanOrEqual(0)
})
it('should detect Organization type from company data', async () => {
const result = await matcher.matchNounType({
companyName: 'Acme Corp',
employees: 500,
industry: 'Technology'
})
expect(result.type).toBe(NounType.Organization)
expect(result.confidence).toBeGreaterThan(0.3)
})
it('should detect Location type from geographic data', async () => {
const result = await matcher.matchNounType({
latitude: 37.7749,
longitude: -122.4194,
city: 'San Francisco'
})
expect(result.type).toBe(NounType.Location)
expect(result.confidence).toBeGreaterThan(0.3)
})
it('should detect Document type from text content', async () => {
const result = await matcher.matchNounType({
title: 'Research Paper',
content: 'Abstract: This paper discusses...',
author: 'Dr. Smith',
pages: 20
})
// Could be Document, Content, or Organization (due to mocked embeddings)
expect([NounType.Document, NounType.Content, NounType.Organization]).toContain(result.type)
})
it('should detect Product type from commercial data', async () => {
const result = await matcher.matchNounType({
price: 99.99,
sku: 'PROD-123',
inventory: 50,
productId: 'abc-123'
})
expect(result.type).toBe(NounType.Product)
expect(result.confidence).toBeGreaterThan(0.25)
})
it('should detect Event type from temporal data', async () => {
const result = await matcher.matchNounType({
startTime: '2024-01-01',
endTime: '2024-01-02',
attendees: 100,
eventType: 'conference'
})
expect(result.type).toBe(NounType.Event)
expect(result.confidence).toBeGreaterThan(0.4)
})
it('should handle ambiguous data with alternatives', async () => {
const result = await matcher.matchNounType({
value: 100,
type: 'unknown',
data: 'mixed'
})
expect(result.type).toBeDefined()
expect(result.alternatives).toBeDefined()
expect(result.alternatives.length).toBeGreaterThan(0)
})
})
describe('Verb Type Detection', () => {
it('should detect MemberOf relationship', async () => {
const result = await matcher.matchVerbType(
{ id: 'user1', type: 'person' },
{ id: 'org1', type: 'organization' },
'memberOf'
)
// With mocked embeddings, type detection is non-deterministic
expect(result.type).toBeDefined()
expect(Object.values(VerbType)).toContain(result.type)
expect(result.confidence).toBeGreaterThan(0)
})
it('should detect CreatedBy relationship', async () => {
const result = await matcher.matchVerbType(
{ id: 'doc1', type: 'document' },
{ id: 'author1', type: 'person' },
'created by'
)
// With mocked embeddings, type detection is non-deterministic
expect(result.type).toBeDefined()
expect(Object.values(VerbType)).toContain(result.type)
expect(result.confidence).toBeGreaterThan(0)
})
it('should detect Contains relationship', async () => {
const result = await matcher.matchVerbType(
{ id: 'folder1', type: 'collection' },
{ id: 'file1', type: 'file' },
'contains'
)
// With mocked embeddings, type detection is non-deterministic
expect(result.type).toBeDefined()
expect(Object.values(VerbType)).toContain(result.type)
expect(result.confidence).toBeGreaterThan(0)
})
it('should handle unknown relationships with defaults', async () => {
const result = await matcher.matchVerbType(
{ id: 'a' },
{ id: 'b' },
'somehow connected'
)
expect(result.type).toBeDefined()
expect(Object.values(VerbType)).toContain(result.type)
})
})
describe('Type Coverage', () => {
it('should have embeddings for all 31 noun types', async () => {
const nounTypes = Object.values(NounType)
expect(nounTypes.length).toBe(31)
// Test that each type can be matched
for (const nounType of nounTypes) {
const result = await matcher.matchNounType({
type: nounType,
test: 'coverage check'
})
expect(result.type).toBeDefined()
}
})
it('should have embeddings for all 40 verb types', async () => {
const verbTypes = Object.values(VerbType)
expect(verbTypes.length).toBe(40)
// Test that each type can be matched
for (const verbType of verbTypes) {
const result = await matcher.matchVerbType(
{ id: 'source' },
{ id: 'target' },
verbType
)
expect(result.type).toBeDefined()
}
})
})
describe('Cache Performance', () => {
it('should cache repeated type matches', async () => {
const testData = { name: 'Cache Test', value: 123 }
const start1 = Date.now()
const result1 = await matcher.matchNounType(testData)
const time1 = Date.now() - start1
const start2 = Date.now()
const result2 = await matcher.matchNounType(testData)
const time2 = Date.now() - start2
expect(result1.type).toBe(result2.type)
expect(result1.confidence).toBe(result2.confidence)
// Second call should be faster due to cache
expect(time2).toBeLessThanOrEqual(time1)
})
it('should clear cache when requested', async () => {
const testData = { name: 'Clear Cache Test' }
await matcher.matchNounType(testData) // Populate cache
matcher.clearCache()
// Should still work after cache clear
const result = await matcher.matchNounType(testData)
expect(result.type).toBeDefined()
})
})
})