brainy/tests/type-enforcement.test.ts
David Snelling 6c62bc4e9d feat: implement comprehensive type safety system with BrainyTypes API
Major enhancements for type safety and developer experience:

- Add BrainyTypes static API for type management and AI-powered suggestions
- Implement strict type validation for all 31 NounType categories
- Remove dangerous generic add() method that bypassed type safety
- Add intelligent type inference with confidence scoring
- Provide helpful error messages with typo suggestions using Levenshtein distance
- Update all internal code, examples, and documentation to use typed methods
- Enhance CLI with new type management commands (types, suggest, validate)

Breaking changes:
- Remove deprecated add() method - use addNoun() with explicit type parameter
- All addNoun() calls now require explicit type as second parameter

This release significantly improves type safety across the entire system while
maintaining backward compatibility for properly typed method calls.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-01 09:37:36 -07:00

103 lines
No EOL
3.6 KiB
TypeScript

import { describe, it, expect, beforeEach } from 'vitest'
import { BrainyData } from '../src/brainyData.js'
import { NounType, VerbType } from '../src/types/graphTypes.js'
import { validateNounType, validateVerbType } from '../src/utils/typeValidation.js'
describe('Type Enforcement System', () => {
describe('Type Validation Module', () => {
it('should validate correct noun types', () => {
expect(validateNounType(NounType.Person)).toBe('person')
expect(validateNounType('organization')).toBe('organization')
expect(validateNounType(NounType.Document)).toBe('document')
})
it('should reject invalid noun types with helpful errors', () => {
expect(() => validateNounType('invalid')).toThrow('Invalid noun type')
expect(() => validateNounType('')).toThrow('Invalid noun type')
expect(() => validateNounType(null)).toThrow('Invalid noun type')
expect(() => validateNounType(undefined)).toThrow('Invalid noun type')
})
it('should provide helpful suggestions for typos', () => {
expect(() => validateNounType('persan')).toThrow(/Did you mean 'person'/)
expect(() => validateNounType('doc')).toThrow(/Did you mean 'document'/)
expect(() => validateNounType('org')).toThrow(/Did you mean 'organization'/)
})
it('should validate correct verb types', () => {
expect(validateVerbType(VerbType.RelatedTo)).toBe('relatedTo')
expect(validateVerbType('contains')).toBe('contains')
expect(validateVerbType(VerbType.Creates)).toBe('creates')
})
})
describe('addNoun with Type Enforcement', () => {
let brain: BrainyData
beforeEach(async () => {
brain = new BrainyData({
storage: { forceMemoryStorage: true },
logging: { verbose: false }
})
await brain.init()
})
it('should require noun type parameter', async () => {
// TypeScript should prevent this, but test runtime validation
await expect(
(brain.addNoun as any)('Test data', { title: 'Test' })
).rejects.toThrow()
})
it('should accept valid noun type', async () => {
const id = await brain.addNoun('John Doe', NounType.Person, { age: 30 })
expect(id).toBeDefined()
const noun = await brain.getNoun(id)
expect(noun.metadata.noun).toBe('person')
expect(noun.metadata.age).toBe(30)
})
it('should accept noun type as string', async () => {
const id = await brain.addNoun('Document content', 'document', {
title: 'Important Doc',
author: 'Jane'
})
expect(id).toBeDefined()
const noun = await brain.getNoun(id)
expect(noun.metadata.noun).toBe('document')
expect(noun.metadata.title).toBe('Important Doc')
})
it('should validate noun type and reject invalid ones', async () => {
await expect(
brain.addNoun('Test', 'invalidType', {})
).rejects.toThrow('Invalid noun type')
})
it('should provide suggestions for typos', async () => {
await expect(
brain.addNoun('Test', 'persan', {})
).rejects.toThrow(/Did you mean 'person'/)
})
})
describe('Type Validation Performance', () => {
it('should validate types quickly (O(1) with Set)', () => {
const start = performance.now()
// Validate 10000 types
for (let i = 0; i < 10000; i++) {
validateNounType(NounType.Person)
validateVerbType(VerbType.Contains)
}
const end = performance.now()
const duration = end - start
// Should complete in less than 50ms (very generous, usually < 5ms)
expect(duration).toBeLessThan(50)
})
})
})