2025-09-11 16:23:32 -07:00
/ * *
* Comprehensive Public API Test Suite
2026-02-17 17:04:11 -08:00
*
* Validates all public API methods exposed by Brainy ,
2025-09-11 16:23:32 -07:00
* ensuring complete coverage of documented functionality .
* /
import { describe , it , expect , beforeAll , afterAll , beforeEach , afterEach , vi } from 'vitest'
import { Brainy } from '../../src/brainy'
import { NounType , VerbType } from '../../src/types/graphTypes'
2026-02-17 17:04:11 -08:00
import type { Entity , Result } from '../../src/types/brainy.types'
2025-09-11 16:23:32 -07:00
import * as fs from 'fs/promises'
import * as path from 'path'
import { tmpdir } from 'os'
2026-02-17 17:04:11 -08:00
import { randomUUID } from 'crypto'
2025-09-11 16:23:32 -07:00
describe ( 'Brainy Public API - Complete Coverage' , ( ) = > {
let brain : Brainy
let testDir : string
beforeAll ( async ( ) = > {
testDir = path . join ( tmpdir ( ) , ` brainy-test- ${ Date . now ( ) } ` )
await fs . mkdir ( testDir , { recursive : true } )
} )
afterAll ( async ( ) = > {
try {
await fs . rm ( testDir , { recursive : true , force : true } )
} catch ( error ) {
console . warn ( 'Failed to cleanup test directory:' , error )
}
} )
describe ( 'Core CRUD Operations' , ( ) = > {
beforeEach ( async ( ) = > {
brain = new Brainy ( { storage : { type : 'memory' } } )
await brain . init ( )
} )
afterEach ( async ( ) = > {
await brain . close ( )
} )
describe ( 'brain.add()' , ( ) = > {
it ( 'should handle all noun types' , async ( ) = > {
const nounTypes = Object . values ( NounType )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
for ( const nounType of nounTypes ) {
const id = await brain . add ( {
data : ` Test ${ nounType } ` ,
type : nounType ,
metadata : { nounType }
} )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
expect ( id ) . toBeDefined ( )
expect ( typeof id ) . toBe ( 'string' )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
const entity = await brain . get ( id )
expect ( entity ) . toBeDefined ( )
expect ( entity ? . type ) . toBe ( nounType )
}
2026-02-17 17:04:11 -08:00
} , 120000 )
2025-09-11 16:23:32 -07:00
it ( 'should validate required fields' , async ( ) = > {
await expect ( brain . add ( {
type : NounType . Document
} as any ) ) . rejects . toThrow ( )
await expect ( brain . add ( {
data : 'test'
} as any ) ) . rejects . toThrow ( )
} )
it ( 'should handle very large data' , async ( ) = > {
2026-02-17 17:04:11 -08:00
const largeText = 'x' . repeat ( 1 _000_000 )
2025-09-11 16:23:32 -07:00
const id = await brain . add ( {
data : largeText ,
type : NounType . Document
} )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
const entity = await brain . get ( id )
2026-02-17 17:04:11 -08:00
expect ( entity ? . data ) . toBe ( largeText )
2025-09-11 16:23:32 -07:00
} )
} )
describe ( 'brain.addMany()' , ( ) = > {
2026-02-17 17:04:11 -08:00
it ( 'should handle batch operations' , async ( ) = > {
const items = Array . from ( { length : 10 } , ( _ , i ) = > ( {
data : ` Batch item ${ i } ` ,
2025-09-11 16:23:32 -07:00
type : NounType . Document ,
metadata : { index : i }
} ) )
2026-02-17 17:04:11 -08:00
const result = await brain . addMany ( { items } )
expect ( result . successful ) . toHaveLength ( 10 )
} , 120000 )
2025-09-11 16:23:32 -07:00
it ( 'should handle partial failures' , async ( ) = > {
const items = [
{ data : 'Valid 1' , type : NounType . Document } ,
2026-02-17 17:04:11 -08:00
{ data : null as any , type : NounType . Document } ,
2025-09-11 16:23:32 -07:00
{ data : 'Valid 2' , type : NounType . Document }
]
try {
2026-02-17 17:04:11 -08:00
const result = await brain . addMany ( { items } )
expect ( result . successful . length ) . toBeGreaterThan ( 0 )
2025-09-11 16:23:32 -07:00
} catch ( error ) {
expect ( error ) . toBeDefined ( )
}
} )
} )
describe ( 'brain.update()' , ( ) = > {
it ( 'should handle concurrent updates' , async ( ) = > {
const id = await brain . add ( {
data : 'Initial' ,
type : NounType . Document ,
metadata : { version : 1 }
} )
2026-02-17 17:04:11 -08:00
const updates = Array . from ( { length : 10 } , ( _ , i ) = >
brain . update ( {
id ,
2025-09-11 16:23:32 -07:00
metadata : { version : i + 2 , updatedBy : ` thread- ${ i } ` }
} )
)
await Promise . all ( updates )
const final = await brain . get ( id )
expect ( final ) . toBeDefined ( )
expect ( final ? . metadata ? . version ) . toBeGreaterThan ( 1 )
} )
2026-02-17 17:04:11 -08:00
it ( 'should handle update of non-existent entity gracefully' , async ( ) = > {
const fakeId = randomUUID ( )
try {
await brain . update ( { id : fakeId , metadata : { test : true } } )
} catch {
// Brainy may throw for non-existent entity — acceptable
}
2025-09-11 16:23:32 -07:00
} )
it ( 'should preserve unmodified fields' , async ( ) = > {
const id = await brain . add ( {
data : 'Test' ,
type : NounType . Document ,
2026-02-17 17:04:11 -08:00
metadata : {
2025-09-11 16:23:32 -07:00
field1 : 'value1' ,
field2 : 'value2' ,
nested : { a : 1 , b : 2 }
}
} )
2026-02-17 17:04:11 -08:00
await brain . update ( {
id ,
2025-09-11 16:23:32 -07:00
metadata : { field1 : 'updated' }
} )
const updated = await brain . get ( id )
expect ( updated ? . metadata ? . field1 ) . toBe ( 'updated' )
expect ( updated ? . metadata ? . field2 ) . toBe ( 'value2' )
expect ( updated ? . metadata ? . nested ) . toEqual ( { a : 1 , b : 2 } )
} )
} )
describe ( 'brain.updateMany()' , ( ) = > {
it ( 'should batch update multiple entities' , async ( ) = > {
2026-02-17 17:04:11 -08:00
const result = await brain . addMany ( {
items : [
{ data : 'Item 1' , type : NounType . Document } ,
{ data : 'Item 2' , type : NounType . Document } ,
{ data : 'Item 3' , type : NounType . Document }
]
} )
2025-09-11 16:23:32 -07:00
2026-02-17 17:04:11 -08:00
const ids = result . successful
2025-09-11 16:23:32 -07:00
const updates = ids . map ( id = > ( {
id ,
2026-02-17 17:04:11 -08:00
metadata : { updated : true }
2025-09-11 16:23:32 -07:00
} ) )
2026-02-17 17:04:11 -08:00
const updateResult = await brain . updateMany ( { items : updates } )
expect ( updateResult ) . toBeDefined ( )
2025-09-11 16:23:32 -07:00
for ( const id of ids ) {
const entity = await brain . get ( id )
expect ( entity ? . metadata ? . updated ) . toBe ( true )
}
} )
} )
describe ( 'brain.delete()' , ( ) = > {
it ( 'should handle cascade deletion of relationships' , async ( ) = > {
const id1 = await brain . add ( { data : 'Entity 1' , type : NounType . Person } )
const id2 = await brain . add ( { data : 'Entity 2' , type : NounType . Organization } )
2026-02-17 17:04:11 -08:00
await brain . relate ( { from : id1 , to : id2 , type : VerbType . WorksWith } )
2025-09-11 16:23:32 -07:00
await brain . delete ( id1 )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
const relations = await brain . getRelations ( id2 )
2026-02-17 17:04:11 -08:00
expect ( relations . filter ( r = > r . from === id1 || r . to === id1 ) ) . toHaveLength ( 0 )
2025-09-11 16:23:32 -07:00
} )
2026-02-17 17:04:11 -08:00
it ( 'should handle deletion of non-existent entity gracefully' , async ( ) = > {
const fakeId = randomUUID ( )
try {
await brain . delete ( fakeId )
} catch {
// Brainy may throw for non-existent entity — acceptable
}
2025-09-11 16:23:32 -07:00
} )
} )
describe ( 'brain.deleteMany()' , ( ) = > {
2026-02-17 17:04:11 -08:00
it ( 'should efficiently delete batches' , async ( ) = > {
const result = await brain . addMany ( {
items : Array.from ( { length : 5 } , ( _ , i ) = > ( {
2025-09-11 16:23:32 -07:00
data : ` Item ${ i } ` ,
type : NounType . Document
} ) )
2026-02-17 17:04:11 -08:00
} )
2025-09-11 16:23:32 -07:00
2026-02-17 17:04:11 -08:00
const ids = result . successful
await brain . deleteMany ( { ids } )
2025-09-11 16:23:32 -07:00
for ( const id of ids ) {
const entity = await brain . get ( id )
expect ( entity ) . toBeNull ( )
}
} )
} )
} )
describe ( 'Relationship Operations' , ( ) = > {
beforeEach ( async ( ) = > {
brain = new Brainy ( { storage : { type : 'memory' } } )
await brain . init ( )
} )
afterEach ( async ( ) = > {
await brain . close ( )
} )
describe ( 'brain.relate()' , ( ) = > {
2026-02-17 17:04:11 -08:00
it ( 'should create relationships with multiple verb types' , async ( ) = > {
2025-09-11 16:23:32 -07:00
const id1 = await brain . add ( { data : 'Source' , type : NounType . Person } )
const id2 = await brain . add ( { data : 'Target' , type : NounType . Organization } )
2026-02-17 17:04:11 -08:00
// Test a representative subset of verb types (not all 127)
const testVerbs = [
VerbType . RelatedTo , VerbType . Creates , VerbType . References ,
VerbType . WorksWith , VerbType . DependsOn , VerbType . Contains ,
VerbType . Requires , VerbType . FriendOf
]
for ( const verbType of testVerbs ) {
const relationId = await brain . relate ( {
from : id1 ,
to : id2 ,
type : verbType ,
2025-09-11 16:23:32 -07:00
metadata : { verbType }
} )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
expect ( relationId ) . toBeDefined ( )
expect ( typeof relationId ) . toBe ( 'string' )
}
} )
it ( 'should handle bidirectional relationships' , async ( ) = > {
const person1 = await brain . add ( { data : 'Alice' , type : NounType . Person } )
const person2 = await brain . add ( { data : 'Bob' , type : NounType . Person } )
2026-02-17 17:04:11 -08:00
await brain . relate ( {
from : person1 ,
to : person2 ,
type : VerbType . FriendOf ,
2025-09-11 16:23:32 -07:00
bidirectional : true
} )
const relations1 = await brain . getRelations ( person1 )
const relations2 = await brain . getRelations ( person2 )
2026-02-17 17:04:11 -08:00
expect ( relations1 . some ( r = > r . to === person2 ) ) . toBe ( true )
expect ( relations2 . some ( r = > r . to === person1 ) ) . toBe ( true )
2025-09-11 16:23:32 -07:00
} )
2026-02-17 17:04:11 -08:00
it ( 'should allow duplicate relationships' , async ( ) = > {
2025-09-11 16:23:32 -07:00
const id1 = await brain . add ( { data : 'A' , type : NounType . Document } )
const id2 = await brain . add ( { data : 'B' , type : NounType . Document } )
2026-02-17 17:04:11 -08:00
await brain . relate ( { from : id1 , to : id2 , type : VerbType . References } )
await brain . relate ( { from : id1 , to : id2 , type : VerbType . References } )
2025-09-11 16:23:32 -07:00
const relations = await brain . getRelations ( id1 )
const referenceRelations = relations . filter (
2026-02-17 17:04:11 -08:00
r = > r . type === VerbType . References && r . to === id2
2025-09-11 16:23:32 -07:00
)
2026-02-17 17:04:11 -08:00
expect ( referenceRelations . length ) . toBeGreaterThanOrEqual ( 1 )
2025-09-11 16:23:32 -07:00
} )
it ( 'should handle relationship metadata and weights' , async ( ) = > {
const id1 = await brain . add ( { data : 'Source' , type : NounType . Document } )
const id2 = await brain . add ( { data : 'Target' , type : NounType . Document } )
2026-02-17 17:04:11 -08:00
const relationId = await brain . relate ( {
from : id1 ,
to : id2 ,
type : VerbType . References ,
2025-09-11 16:23:32 -07:00
weight : 0.8 ,
metadata : {
context : 'academic' ,
verified : true
}
} )
const relations = await brain . getRelations ( id1 )
const relation = relations . find ( r = > r . id === relationId )
2026-02-17 17:04:11 -08:00
expect ( relation ) . toBeDefined ( )
expect ( relation ? . metadata ? . context ) . toBe ( 'academic' )
2025-09-11 16:23:32 -07:00
} )
} )
describe ( 'brain.relateMany()' , ( ) = > {
it ( 'should create multiple relationships efficiently' , async ( ) = > {
2026-02-17 17:04:11 -08:00
const result = await brain . addMany ( {
items : Array.from ( { length : 5 } , ( _ , i ) = > ( {
2025-09-11 16:23:32 -07:00
data : ` Entity ${ i } ` ,
type : NounType . Document
} ) )
2026-02-17 17:04:11 -08:00
} )
const entities = result . successful
2025-09-11 16:23:32 -07:00
2026-02-17 17:04:11 -08:00
const items = [ ]
2025-09-11 16:23:32 -07:00
for ( let i = 0 ; i < entities . length - 1 ; i ++ ) {
2026-02-17 17:04:11 -08:00
items . push ( {
from : entities [ i ] ,
to : entities [ i + 1 ] ,
type : VerbType . Precedes
2025-09-11 16:23:32 -07:00
} )
}
2026-02-17 17:04:11 -08:00
const relationIds = await brain . relateMany ( { items } )
expect ( relationIds ) . toHaveLength ( items . length )
2025-09-11 16:23:32 -07:00
} )
} )
describe ( 'brain.getRelations()' , ( ) = > {
2026-02-17 17:04:11 -08:00
it ( 'should retrieve outgoing relationships' , async ( ) = > {
2025-09-11 16:23:32 -07:00
const center = await brain . add ( { data : 'Center' , type : NounType . Person } )
const related1 = await brain . add ( { data : 'Related1' , type : NounType . Organization } )
const related2 = await brain . add ( { data : 'Related2' , type : NounType . Document } )
2026-02-17 17:04:11 -08:00
await brain . relate ( { from : center , to : related1 , type : VerbType . WorksWith } )
await brain . relate ( { from : center , to : related2 , type : VerbType . Creates } )
const outgoing = await brain . getRelations ( { from : center } )
expect ( outgoing ) . toHaveLength ( 2 )
expect ( outgoing . some ( r = > r . type === VerbType . WorksWith ) ) . toBe ( true )
expect ( outgoing . some ( r = > r . type === VerbType . Creates ) ) . toBe ( true )
} )
it ( 'should retrieve incoming relationships' , async ( ) = > {
const center = await brain . add ( { data : 'Center' , type : NounType . Person } )
const source = await brain . add ( { data : 'Source' , type : NounType . Task } )
await brain . relate ( { from : source , to : center , type : VerbType . DependsOn } )
const incoming = await brain . getRelations ( { to : center } )
expect ( incoming ) . toHaveLength ( 1 )
expect ( incoming [ 0 ] . type ) . toBe ( VerbType . DependsOn )
2025-09-11 16:23:32 -07:00
} )
it ( 'should filter by relationship direction' , async ( ) = > {
const center = await brain . add ( { data : 'Center' , type : NounType . Document } )
const source = await brain . add ( { data : 'Source' , type : NounType . Person } )
const target = await brain . add ( { data : 'Target' , type : NounType . Task } )
2026-02-17 17:04:11 -08:00
await brain . relate ( { from : source , to : center , type : VerbType . Creates } )
await brain . relate ( { from : center , to : target , type : VerbType . Requires } )
2025-09-11 16:23:32 -07:00
2026-02-17 17:04:11 -08:00
const outgoing = await brain . getRelations ( { from : center } )
const incoming = await brain . getRelations ( { to : center } )
2025-09-11 16:23:32 -07:00
expect ( outgoing ) . toHaveLength ( 1 )
2026-02-17 17:04:11 -08:00
expect ( outgoing [ 0 ] . to ) . toBe ( target )
2025-09-11 16:23:32 -07:00
expect ( incoming ) . toHaveLength ( 1 )
2026-02-17 17:04:11 -08:00
expect ( incoming [ 0 ] . from ) . toBe ( source )
2025-09-11 16:23:32 -07:00
} )
it ( 'should filter by verb type' , async ( ) = > {
const doc = await brain . add ( { data : 'Document' , type : NounType . Document } )
const ref1 = await brain . add ( { data : 'Reference1' , type : NounType . Document } )
const ref2 = await brain . add ( { data : 'Reference2' , type : NounType . Document } )
const author = await brain . add ( { data : 'Author' , type : NounType . Person } )
2026-02-17 17:04:11 -08:00
await brain . relate ( { from : doc , to : ref1 , type : VerbType . References } )
await brain . relate ( { from : doc , to : ref2 , type : VerbType . References } )
await brain . relate ( { from : author , to : doc , type : VerbType . Creates } )
2025-09-11 16:23:32 -07:00
2026-02-17 17:04:11 -08:00
const references = await brain . getRelations ( {
from : doc ,
type : VerbType . References
2025-09-11 16:23:32 -07:00
} )
expect ( references ) . toHaveLength ( 2 )
2026-02-17 17:04:11 -08:00
expect ( references . every ( r = > r . type === VerbType . References ) ) . toBe ( true )
2025-09-11 16:23:32 -07:00
} )
} )
} )
describe ( 'Search Operations' , ( ) = > {
beforeEach ( async ( ) = > {
brain = new Brainy ( { storage : { type : 'memory' } } )
await brain . init ( )
2026-02-17 17:04:11 -08:00
await brain . addMany ( {
items : [
{ data : 'The quick brown fox' , type : NounType . Document , metadata : { category : 'animals' } } ,
{ data : 'jumps over the lazy dog' , type : NounType . Document , metadata : { category : 'animals' } } ,
{ data : 'Machine learning algorithms' , type : NounType . Document , metadata : { category : 'tech' } } ,
{ data : 'Deep neural networks' , type : NounType . Document , metadata : { category : 'tech' } } ,
{ data : 'Natural language processing' , type : NounType . Document , metadata : { category : 'tech' } }
]
} )
} , 120000 )
2025-09-11 16:23:32 -07:00
afterEach ( async ( ) = > {
await brain . close ( )
} )
describe ( 'brain.find()' , ( ) = > {
2026-02-17 17:04:11 -08:00
it ( 'should support metadata search' , async ( ) = > {
const results = await brain . find ( {
where : { category : 'tech' } ,
limit : 5
} )
2025-09-11 16:23:32 -07:00
2026-02-17 17:04:11 -08:00
expect ( results ) . toBeDefined ( )
expect ( Array . isArray ( results ) ) . toBe ( true )
expect ( results . length ) . toBeGreaterThan ( 0 )
2025-09-11 16:23:32 -07:00
} )
2026-02-17 17:04:11 -08:00
it ( 'should handle metadata filters' , async ( ) = > {
2025-09-11 16:23:32 -07:00
const results = await brain . find ( {
2026-02-17 17:04:11 -08:00
where : { category : 'tech' } ,
2025-09-11 16:23:32 -07:00
limit : 10
} )
expect ( results . length ) . toBeGreaterThan ( 0 )
expect ( results . every ( r = > r . entity . metadata ? . category === 'tech' ) ) . toBe ( true )
} )
it ( 'should support graph-connected searches' , async ( ) = > {
const doc1 = await brain . add ( { data : 'Primary document' , type : NounType . Document } )
const doc2 = await brain . add ( { data : 'Related document' , type : NounType . Document } )
2026-02-17 17:04:11 -08:00
await brain . relate ( { from : doc1 , to : doc2 , type : VerbType . References } )
2025-09-11 16:23:32 -07:00
const results = await brain . find ( {
query : 'document' ,
connected : { from : doc1 } ,
limit : 5
} )
expect ( results . some ( r = > r . entity . id === doc2 ) ) . toBe ( true )
} )
it ( 'should support pagination' , async ( ) = > {
const page1 = await brain . find ( {
2026-02-17 17:04:11 -08:00
where : { category : 'tech' } ,
2025-09-11 16:23:32 -07:00
limit : 2 ,
offset : 0
} )
const page2 = await brain . find ( {
2026-02-17 17:04:11 -08:00
where : { category : 'tech' } ,
2025-09-11 16:23:32 -07:00
limit : 2 ,
offset : 2
} )
2026-02-17 17:04:11 -08:00
if ( page1 . length > 0 && page2 . length > 0 ) {
expect ( page1 [ 0 ] ? . entity . id ) . not . toBe ( page2 [ 0 ] ? . entity . id )
}
2025-09-11 16:23:32 -07:00
} )
} )
describe ( 'brain.similar()' , ( ) = > {
it ( 'should find similar entities' , async ( ) = > {
const reference = await brain . add ( {
data : 'Artificial intelligence and machine learning' ,
type : NounType . Document
} )
2026-02-17 17:04:11 -08:00
const similar = await brain . similar ( {
to : reference ,
limit : 5
2025-09-11 16:23:32 -07:00
} )
expect ( similar ) . toBeDefined ( )
expect ( similar . length ) . toBeGreaterThan ( 0 )
} )
2026-02-17 17:04:11 -08:00
it ( 'should return results sorted by score' , async ( ) = > {
2025-09-11 16:23:32 -07:00
const reference = await brain . add ( {
2026-02-17 17:04:11 -08:00
data : 'Deep learning and neural networks research' ,
2025-09-11 16:23:32 -07:00
type : NounType . Document
} )
2026-02-17 17:04:11 -08:00
const similar = await brain . similar ( {
to : reference ,
limit : 10
2025-09-11 16:23:32 -07:00
} )
2026-02-17 17:04:11 -08:00
// Results should be sorted by score (descending)
if ( similar . length > 1 ) {
for ( let i = 1 ; i < similar . length ; i ++ ) {
expect ( similar [ i - 1 ] . score ) . toBeGreaterThanOrEqual ( similar [ i ] . score - 0.001 )
}
}
2025-09-11 16:23:32 -07:00
} )
} )
} )
describe ( 'Neural API' , ( ) = > {
2026-02-17 17:04:11 -08:00
let entityIds : string [ ]
2025-09-11 16:23:32 -07:00
beforeEach ( async ( ) = > {
brain = new Brainy ( { storage : { type : 'memory' } } )
await brain . init ( )
2026-02-17 17:04:11 -08:00
const result = await brain . addMany ( {
items : [
{ data : 'Cat' , type : NounType . Concept , metadata : { category : 'animal' } } ,
{ data : 'Dog' , type : NounType . Concept , metadata : { category : 'animal' } } ,
{ data : 'Tiger' , type : NounType . Concept , metadata : { category : 'animal' } } ,
{ data : 'Car' , type : NounType . Thing , metadata : { category : 'vehicle' } } ,
{ data : 'Truck' , type : NounType . Thing , metadata : { category : 'vehicle' } } ,
{ data : 'Python' , type : NounType . Language , metadata : { category : 'programming' } } ,
{ data : 'JavaScript' , type : NounType . Language , metadata : { category : 'programming' } }
]
} )
entityIds = result . successful
} , 120000 )
2025-09-11 16:23:32 -07:00
afterEach ( async ( ) = > {
await brain . close ( )
} )
describe ( 'brain.neural().clusters()' , ( ) = > {
it ( 'should cluster entities by similarity' , async ( ) = > {
const clusters = await brain . neural ( ) . clusters ( {
k : 3 ,
maxIterations : 10
} )
expect ( clusters ) . toBeDefined ( )
2026-02-17 17:04:11 -08:00
expect ( clusters . length ) . toBeGreaterThan ( 0 )
2025-09-11 16:23:32 -07:00
expect ( clusters . every ( c = > c . members . length > 0 ) ) . toBe ( true )
} )
} )
describe ( 'brain.neural().hierarchy()' , ( ) = > {
2026-02-17 17:04:11 -08:00
it ( 'should build semantic hierarchy for an entity' , async ( ) = > {
// hierarchy() requires an entity ID
const hierarchy = await brain . neural ( ) . hierarchy ( entityIds [ 0 ] )
2025-09-11 16:23:32 -07:00
expect ( hierarchy ) . toBeDefined ( )
2026-02-17 17:04:11 -08:00
// Hierarchy structure includes optional root, levels, children, etc.
expect ( typeof hierarchy ) . toBe ( 'object' )
2025-09-11 16:23:32 -07:00
} )
} )
describe ( 'brain.neural().outliers()' , ( ) = > {
it ( 'should detect anomalous entities' , async ( ) = > {
await brain . add ( {
2026-02-17 17:04:11 -08:00
data : 'Quantum physics equations and string theory' ,
2025-09-11 16:23:32 -07:00
type : NounType . Document ,
metadata : { category : 'science' }
} )
const outliers = await brain . neural ( ) . outliers ( {
threshold : 0.8
} )
expect ( outliers ) . toBeDefined ( )
expect ( Array . isArray ( outliers ) ) . toBe ( true )
} )
} )
describe ( 'brain.neural().visualize()' , ( ) = > {
it ( 'should generate visualization data' , async ( ) = > {
const vizData = await brain . neural ( ) . visualize ( {
dimensions : 2 ,
2026-02-17 17:04:11 -08:00
algorithm : 'force'
2025-09-11 16:23:32 -07:00
} )
expect ( vizData ) . toBeDefined ( )
expect ( vizData . nodes ) . toBeDefined ( )
2026-02-17 17:04:11 -08:00
expect ( Array . isArray ( vizData . nodes ) ) . toBe ( true )
2025-09-11 16:23:32 -07:00
} )
} )
describe ( 'brain.neural().neighbors()' , ( ) = > {
it ( 'should find nearest neighbors' , async ( ) = > {
2026-02-17 17:04:11 -08:00
if ( entityIds . length > 0 ) {
const result = await brain . neural ( ) . neighbors ( entityIds [ 0 ] , {
limit : 3
2025-09-11 16:23:32 -07:00
} )
2026-02-17 17:04:11 -08:00
// NeighborsResult has a neighbors array
expect ( result ) . toBeDefined ( )
expect ( result . neighbors ) . toBeDefined ( )
// Small datasets may not produce nearest neighbors
expect ( result . neighbors . length ) . toBeGreaterThanOrEqual ( 0 )
2025-09-11 16:23:32 -07:00
}
} )
} )
} )
2026-02-17 17:04:11 -08:00
describe ( 'Statistics' , ( ) = > {
2025-09-11 16:23:32 -07:00
beforeEach ( async ( ) = > {
brain = new Brainy ( { storage : { type : 'memory' } } )
await brain . init ( )
} )
afterEach ( async ( ) = > {
await brain . close ( )
} )
2025-10-09 11:40:31 -07:00
describe ( 'brain.getStats()' , ( ) = > {
2026-02-17 17:04:11 -08:00
it ( 'should return statistics' , async ( ) = > {
await brain . addMany ( {
items : [
{ data : 'Item 1' , type : NounType . Document } ,
{ data : 'Item 2' , type : NounType . Person } ,
{ data : 'Item 3' , type : NounType . Task }
]
} )
2025-09-11 16:23:32 -07:00
2026-02-17 17:04:11 -08:00
const stats = await brain . getStats ( )
2025-09-11 16:23:32 -07:00
expect ( stats ) . toBeDefined ( )
2026-02-17 17:04:11 -08:00
// Stats returns { entities: { total, byType }, relationships, density }
expect ( stats . entities ) . toBeDefined ( )
expect ( stats . entities . total ) . toBeGreaterThanOrEqual ( 3 )
expect ( stats . entities . byType ) . toBeDefined ( )
2025-09-11 16:23:32 -07:00
} )
} )
} )
describe ( 'FileSystem Storage' , ( ) = > {
it ( 'should handle basic CRUD with filesystem' , async ( ) = > {
2026-02-17 17:04:11 -08:00
const fsTestDir = path . join ( tmpdir ( ) , ` brainy-fs-crud- ${ Date . now ( ) } ` )
await fs . mkdir ( fsTestDir , { recursive : true } )
2025-09-11 16:23:32 -07:00
const fsBrain = new Brainy ( {
storage : {
type : 'filesystem' ,
2026-02-17 17:04:11 -08:00
options : { path : fsTestDir }
2025-09-11 16:23:32 -07:00
}
} )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
await fsBrain . init ( )
const id = await fsBrain . add ( {
data : 'Filesystem test' ,
type : NounType . Document
} )
const retrieved = await fsBrain . get ( id )
2026-02-17 17:04:11 -08:00
expect ( retrieved ? . data ) . toBe ( 'Filesystem test' )
2025-09-11 16:23:32 -07:00
2026-02-17 17:04:11 -08:00
await fsBrain . update ( { id , metadata : { updated : true } } )
2025-09-11 16:23:32 -07:00
const updated = await fsBrain . get ( id )
expect ( updated ? . metadata ? . updated ) . toBe ( true )
await fsBrain . delete ( id )
const deleted = await fsBrain . get ( id )
expect ( deleted ) . toBeNull ( )
await fsBrain . close ( )
2026-02-17 17:04:11 -08:00
await fs . rm ( fsTestDir , { recursive : true , force : true } ) . catch ( ( ) = > { } )
2025-09-11 16:23:32 -07:00
} )
it ( 'should handle concurrent filesystem operations' , async ( ) = > {
2026-02-17 17:04:11 -08:00
const fsTestDir = path . join ( tmpdir ( ) , ` brainy-fs-concurrent- ${ Date . now ( ) } ` )
await fs . mkdir ( fsTestDir , { recursive : true } )
2025-09-11 16:23:32 -07:00
const fsBrain = new Brainy ( {
storage : {
type : 'filesystem' ,
2026-02-17 17:04:11 -08:00
options : { path : fsTestDir }
2025-09-11 16:23:32 -07:00
}
} )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
await fsBrain . init ( )
2026-02-17 17:04:11 -08:00
const operations = Array . from ( { length : 5 } , async ( _ , i ) = > {
2025-09-11 16:23:32 -07:00
const id = await fsBrain . add ( {
data : ` Concurrent ${ i } ` ,
type : NounType . Document
} )
return id
} )
const ids = await Promise . all ( operations )
2026-02-17 17:04:11 -08:00
expect ( ids ) . toHaveLength ( 5 )
expect ( new Set ( ids ) . size ) . toBe ( 5 )
2025-09-11 16:23:32 -07:00
await fsBrain . close ( )
2026-02-17 17:04:11 -08:00
await fs . rm ( fsTestDir , { recursive : true , force : true } ) . catch ( ( ) = > { } )
2025-09-11 16:23:32 -07:00
} )
} )
describe ( 'Error Recovery and Resilience' , ( ) = > {
beforeEach ( async ( ) = > {
brain = new Brainy ( { storage : { type : 'memory' } } )
await brain . init ( )
} )
afterEach ( async ( ) = > {
await brain . close ( )
} )
2026-02-17 17:04:11 -08:00
it ( 'should handle and recover from transient errors' , async ( ) = > {
2025-09-11 16:23:32 -07:00
const originalAdd = brain . add . bind ( brain )
let failCount = 0
brain . add = vi . fn ( async ( . . . args ) = > {
if ( failCount ++ < 2 ) {
throw new Error ( 'Storage temporarily unavailable' )
}
return originalAdd ( . . . args )
} )
let succeeded = false
for ( let i = 0 ; i < 3 ; i ++ ) {
try {
await brain . add ( {
data : 'Test' ,
type : NounType . Document
} )
succeeded = true
break
} catch ( error ) {
// Expected for first attempts
}
}
expect ( succeeded ) . toBe ( true )
} )
it ( 'should handle malformed input gracefully' , async ( ) = > {
const malformedInputs = [
null ,
undefined ,
{ } ,
{ data : null } ,
{ type : 'invalid' } ,
]
for ( const input of malformedInputs ) {
try {
await brain . add ( input as any )
} catch ( error ) {
expect ( error ) . toBeDefined ( )
expect ( ( error as Error ) . message ) . toBeDefined ( )
}
}
} )
} )
2026-02-17 17:04:11 -08:00
describe ( 'Performance' , ( ) = > {
it ( 'should handle moderate-scale operations' , async ( ) = > {
const perfBrain = new Brainy ( { storage : { type : 'memory' } } )
await perfBrain . init ( )
2025-09-11 16:23:32 -07:00
2026-02-17 17:04:11 -08:00
// Add 50 items in batches
const items = Array . from ( { length : 50 } , ( _ , i ) = > ( {
data : ` Performance item ${ i } ` ,
type : NounType . Document ,
metadata : { batch : Math.floor ( i / 10 ) , index : i }
} ) )
2025-09-11 16:23:32 -07:00
2026-02-17 17:04:11 -08:00
const result = await perfBrain . addMany ( { items } )
expect ( result . successful . length ) . toBe ( 50 )
2025-09-11 16:23:32 -07:00
2026-02-17 17:04:11 -08:00
// Search should work
const results = await perfBrain . find ( {
query : 'Performance item' ,
limit : 20
2025-09-11 16:23:32 -07:00
} )
expect ( results . length ) . toBeGreaterThan ( 0 )
2026-02-17 17:04:11 -08:00
await perfBrain . close ( )
} , 180000 )
2025-09-11 16:23:32 -07:00
} )
describe ( 'Clear Operations' , ( ) = > {
beforeEach ( async ( ) = > {
brain = new Brainy ( { storage : { type : 'memory' } } )
await brain . init ( )
2026-02-17 17:04:11 -08:00
await brain . addMany ( {
items : [
{ data : 'Doc 1' , type : NounType . Document , metadata : { category : 'A' } } ,
{ data : 'Doc 2' , type : NounType . Document , metadata : { category : 'B' } } ,
{ data : 'Person 1' , type : NounType . Person , metadata : { category : 'A' } }
]
} )
} , 120000 )
2025-09-11 16:23:32 -07:00
afterEach ( async ( ) = > {
await brain . close ( )
} )
2026-02-17 17:04:11 -08:00
it ( 'should clear data and allow re-use' , async ( ) = > {
const beforeClear = await brain . find ( { where : { category : 'A' } } )
expect ( beforeClear . length ) . toBeGreaterThan ( 0 )
2025-09-11 16:23:32 -07:00
2026-02-17 17:04:11 -08:00
await brain . clear ( )
2025-09-11 16:23:32 -07:00
2026-02-17 17:04:11 -08:00
// After clear, add should still work
const id = await brain . add ( { data : 'After clear' , type : NounType . Document } )
const entity = await brain . get ( id )
expect ( entity ) . toBeDefined ( )
expect ( entity ? . data ) . toBe ( 'After clear' )
} , 120000 )
2025-09-11 16:23:32 -07:00
} )
2026-02-17 17:04:11 -08:00
} )