feat(tests): add robust mock implementations and expand test coverage for S3 and OPFS storage
- Introduced comprehensive mock for the Origin Private File System (OPFS) in `tests/mocks/opfs-mock.ts`, simulating environment for detailed storage testing.
- Added `tests/opfs-storage.test.ts`, containing extensive test cases for `OPFSStorage` operations including metadata, nouns, verbs, and storage status.
- Improved S3 mock implementation in `tests/mocks/s3-mock.ts` with better object persistence, validation, and logging to emulate real S3 behavior.
- Resolved issues related to metadata, nouns, verbs, and storage usage inconsistencies in mock storage adapters.
- Enhanced logging and error handling to aid in debugging and test reliability.
Purpose: Improve test completeness and reliability by introducing detailed mocks and extended test cases for S3 and OPFS storage systems.
2025-07-21 13:42:10 -07:00
/ * *
* S3 Compatible Storage Tests
* Tests for the S3 compatible storage adapter using a simulated S3 environment
* /
import { describe , it , expect , beforeEach , afterEach , vi } from 'vitest'
import { setupS3Mock , cleanupS3Mock , S3Commands } from './mocks/s3-mock'
import { Vector } from '../src/coreTypes'
// Setup S3 mock environment at the top level
console . log ( 'Setting up S3 mock environment at the top level' )
const s3MockSetup = setupS3Mock ( )
// Mock AWS SDK imports at the top level
vi . mock ( '@aws-sdk/client-s3' , ( ) = > {
console . log ( 'Mocking AWS SDK imports' )
return {
S3Client : class MockS3Client {
send = s3MockSetup . mockS3Client . send
} ,
. . . S3Commands
}
} )
describe ( 'S3CompatibleStorage' , ( ) = > {
// Import modules inside tests to avoid issues with dynamic imports
let S3CompatibleStorage : any
let R2Storage : any
let s3Mock : any
beforeEach ( async ( ) = > {
console . log ( '==== TEST SETUP START ====' )
// Store the mock setup for use in tests
s3Mock = s3MockSetup
// Reset the mock storage before each test
s3Mock . reset ( )
// Import storage factory
console . log ( 'Importing storage factory' )
const storageFactory = await import ( '../src/storage/storageFactory.js' )
S3CompatibleStorage = storageFactory . S3CompatibleStorage
R2Storage = storageFactory . R2Storage
console . log ( '==== TEST SETUP COMPLETE ====' )
} )
afterEach ( ( ) = > {
console . log ( '==== TEST CLEANUP START ====' )
// Clean up S3 mock environment
cleanupS3Mock ( )
// Reset mocks
vi . resetAllMocks ( )
vi . clearAllMocks ( )
console . log ( '==== TEST CLEANUP COMPLETE ====' )
} )
it ( 'should initialize S3CompatibleStorage correctly' , async ( ) = > {
// Create the bucket first using our mock
const createBucketCommand = new S3Commands . CreateBucketCommand ( {
Bucket : 'test-bucket'
} )
await s3Mock . mockS3Client . send ( createBucketCommand )
// Create a new instance with our mocked environment
const s3Storage = new S3CompatibleStorage ( {
bucketName : 'test-bucket' ,
region : 'us-east-1' ,
accessKeyId : 'test-access-key' ,
secretAccessKey : 'test-secret-key' ,
serviceType : 's3'
} )
// Initialize the storage
await s3Storage . init ( )
// Verify the storage was initialized correctly
expect ( s3Storage ) . toBeDefined ( )
// Clean up
await s3Storage . clear ( )
} )
it ( 'should initialize R2Storage correctly' , async ( ) = > {
// Create the bucket first using our mock
const createBucketCommand = new S3Commands . CreateBucketCommand ( {
Bucket : 'test-bucket'
} )
await s3Mock . mockS3Client . send ( createBucketCommand )
// Create a new instance with our mocked environment
const r2Storage = new R2Storage ( {
bucketName : 'test-bucket' ,
accountId : 'test-account' ,
accessKeyId : 'test-access-key' ,
secretAccessKey : 'test-secret-key'
} )
// Initialize the storage
await r2Storage . init ( )
// Verify the storage was initialized correctly
expect ( r2Storage ) . toBeDefined ( )
// Clean up
await r2Storage . clear ( )
} )
it ( 'should perform basic metadata operations with S3 storage' , async ( ) = > {
// Create the bucket first using our mock
const createBucketCommand = new S3Commands . CreateBucketCommand ( {
Bucket : 'test-bucket'
} )
await s3Mock . mockS3Client . send ( createBucketCommand )
// Create a new instance with our mocked environment
const s3Storage = new S3CompatibleStorage ( {
bucketName : 'test-bucket' ,
region : 'us-east-1' ,
accessKeyId : 'test-access-key' ,
secretAccessKey : 'test-secret-key' ,
serviceType : 's3'
} )
// Initialize the storage
await s3Storage . init ( )
// Test basic metadata operations
const testMetadata = { test : 'data' , value : 123 }
await s3Storage . saveMetadata ( 'test-key' , testMetadata )
const retrievedMetadata = await s3Storage . getMetadata ( 'test-key' )
expect ( retrievedMetadata ) . toEqual ( testMetadata )
// Clean up
await s3Storage . clear ( )
} )
it ( 'should handle noun operations correctly with S3 storage' , async ( ) = > {
// Create the bucket first using our mock
const createBucketCommand = new S3Commands . CreateBucketCommand ( {
Bucket : 'test-bucket'
} )
await s3Mock . mockS3Client . send ( createBucketCommand )
// Create a new instance with our mocked environment
const s3Storage = new S3CompatibleStorage ( {
bucketName : 'test-bucket' ,
region : 'us-east-1' ,
accessKeyId : 'test-access-key' ,
secretAccessKey : 'test-secret-key' ,
serviceType : 's3'
} )
// Initialize the storage
await s3Storage . init ( )
// Create test noun
const testVector : Vector = [ 0.1 , 0.2 , 0.3 , 0.4 , 0.5 ]
const testNoun = {
id : 'test-noun-1' ,
vector : testVector ,
connections : new Map ( [
[ 0 , new Set ( [ 'test-noun-2' , 'test-noun-3' ] ) ]
] )
}
// Save the noun
await s3Storage . saveNoun ( testNoun )
// Retrieve the noun
const retrievedNoun = await s3Storage . getNoun ( 'test-noun-1' )
// Verify the noun was saved and retrieved correctly
expect ( retrievedNoun ) . toBeDefined ( )
expect ( retrievedNoun ? . id ) . toBe ( 'test-noun-1' )
expect ( retrievedNoun ? . vector ) . toEqual ( testVector )
// Verify connections were saved correctly
// Note: connections are stored as a Map in memory but might be serialized differently
expect ( retrievedNoun ? . connections ) . toBeDefined ( )
expect ( retrievedNoun ? . connections . get ( 0 ) ) . toBeDefined ( )
expect ( retrievedNoun ? . connections . get ( 0 ) ? . has ( 'test-noun-2' ) ) . toBe ( true )
expect ( retrievedNoun ? . connections . get ( 0 ) ? . has ( 'test-noun-3' ) ) . toBe ( true )
// Test getAllNouns
const allNouns = await s3Storage . getAllNouns ( )
expect ( allNouns . length ) . toBe ( 1 )
expect ( allNouns [ 0 ] . id ) . toBe ( 'test-noun-1' )
// Test deleteNoun
await s3Storage . deleteNoun ( 'test-noun-1' )
const deletedNoun = await s3Storage . getNoun ( 'test-noun-1' )
expect ( deletedNoun ) . toBeNull ( )
// Clean up
await s3Storage . clear ( )
} )
it ( 'should handle verb operations correctly with S3 storage' , async ( ) = > {
// Create the bucket first using our mock
const createBucketCommand = new S3Commands . CreateBucketCommand ( {
Bucket : 'test-bucket'
} )
await s3Mock . mockS3Client . send ( createBucketCommand )
// Create a new instance with our mocked environment
const s3Storage = new S3CompatibleStorage ( {
bucketName : 'test-bucket' ,
region : 'us-east-1' ,
accessKeyId : 'test-access-key' ,
secretAccessKey : 'test-secret-key' ,
serviceType : 's3'
} )
// Initialize the storage
await s3Storage . init ( )
// Create test verb
const testVector : Vector = [ 0.1 , 0.2 , 0.3 , 0.4 , 0.5 ]
2025-07-25 09:44:10 -07:00
const timestamp = {
seconds : Math.floor ( Date . now ( ) / 1000 ) ,
nanoseconds : ( Date . now ( ) % 1000 ) * 1000000
}
feat(tests): add robust mock implementations and expand test coverage for S3 and OPFS storage
- Introduced comprehensive mock for the Origin Private File System (OPFS) in `tests/mocks/opfs-mock.ts`, simulating environment for detailed storage testing.
- Added `tests/opfs-storage.test.ts`, containing extensive test cases for `OPFSStorage` operations including metadata, nouns, verbs, and storage status.
- Improved S3 mock implementation in `tests/mocks/s3-mock.ts` with better object persistence, validation, and logging to emulate real S3 behavior.
- Resolved issues related to metadata, nouns, verbs, and storage usage inconsistencies in mock storage adapters.
- Enhanced logging and error handling to aid in debugging and test reliability.
Purpose: Improve test completeness and reliability by introducing detailed mocks and extended test cases for S3 and OPFS storage systems.
2025-07-21 13:42:10 -07:00
const testVerb = {
id : 'test-verb-1' ,
vector : testVector ,
connections : new Map ( ) ,
2025-07-25 09:44:10 -07:00
source : 'source-noun-1' ,
target : 'target-noun-1' ,
verb : 'test-relation' ,
feat(tests): add robust mock implementations and expand test coverage for S3 and OPFS storage
- Introduced comprehensive mock for the Origin Private File System (OPFS) in `tests/mocks/opfs-mock.ts`, simulating environment for detailed storage testing.
- Added `tests/opfs-storage.test.ts`, containing extensive test cases for `OPFSStorage` operations including metadata, nouns, verbs, and storage status.
- Improved S3 mock implementation in `tests/mocks/s3-mock.ts` with better object persistence, validation, and logging to emulate real S3 behavior.
- Resolved issues related to metadata, nouns, verbs, and storage usage inconsistencies in mock storage adapters.
- Enhanced logging and error handling to aid in debugging and test reliability.
Purpose: Improve test completeness and reliability by introducing detailed mocks and extended test cases for S3 and OPFS storage systems.
2025-07-21 13:42:10 -07:00
weight : 0.75 ,
2025-07-25 09:44:10 -07:00
metadata : { description : 'Test relation' } ,
createdAt : timestamp ,
updatedAt : timestamp ,
createdBy : {
augmentation : 'test-service' ,
version : '1.0'
}
feat(tests): add robust mock implementations and expand test coverage for S3 and OPFS storage
- Introduced comprehensive mock for the Origin Private File System (OPFS) in `tests/mocks/opfs-mock.ts`, simulating environment for detailed storage testing.
- Added `tests/opfs-storage.test.ts`, containing extensive test cases for `OPFSStorage` operations including metadata, nouns, verbs, and storage status.
- Improved S3 mock implementation in `tests/mocks/s3-mock.ts` with better object persistence, validation, and logging to emulate real S3 behavior.
- Resolved issues related to metadata, nouns, verbs, and storage usage inconsistencies in mock storage adapters.
- Enhanced logging and error handling to aid in debugging and test reliability.
Purpose: Improve test completeness and reliability by introducing detailed mocks and extended test cases for S3 and OPFS storage systems.
2025-07-21 13:42:10 -07:00
}
// Save the verb
await s3Storage . saveVerb ( testVerb )
// Retrieve the verb
const retrievedVerb = await s3Storage . getVerb ( 'test-verb-1' )
// Verify the verb was saved and retrieved correctly
expect ( retrievedVerb ) . toBeDefined ( )
expect ( retrievedVerb ? . id ) . toBe ( 'test-verb-1' )
expect ( retrievedVerb ? . vector ) . toEqual ( testVector )
expect ( retrievedVerb ? . sourceId ) . toBe ( 'source-noun-1' )
expect ( retrievedVerb ? . targetId ) . toBe ( 'target-noun-1' )
expect ( retrievedVerb ? . type ) . toBe ( 'test-relation' )
expect ( retrievedVerb ? . weight ) . toBe ( 0.75 )
expect ( retrievedVerb ? . metadata ) . toEqual ( { description : 'Test relation' } )
// Test getAllVerbs
const allVerbs = await s3Storage . getAllVerbs ( )
expect ( allVerbs . length ) . toBe ( 1 )
expect ( allVerbs [ 0 ] . id ) . toBe ( 'test-verb-1' )
// Test getVerbsBySource
const verbsBySource = await s3Storage . getVerbsBySource ( 'source-noun-1' )
expect ( verbsBySource . length ) . toBe ( 1 )
expect ( verbsBySource [ 0 ] . id ) . toBe ( 'test-verb-1' )
// Test getVerbsByTarget
const verbsByTarget = await s3Storage . getVerbsByTarget ( 'target-noun-1' )
expect ( verbsByTarget . length ) . toBe ( 1 )
expect ( verbsByTarget [ 0 ] . id ) . toBe ( 'test-verb-1' )
// Test getVerbsByType
const verbsByType = await s3Storage . getVerbsByType ( 'test-relation' )
expect ( verbsByType . length ) . toBe ( 1 )
expect ( verbsByType [ 0 ] . id ) . toBe ( 'test-verb-1' )
// Test deleteVerb
await s3Storage . deleteVerb ( 'test-verb-1' )
const deletedVerb = await s3Storage . getVerb ( 'test-verb-1' )
expect ( deletedVerb ) . toBeNull ( )
// Clean up
await s3Storage . clear ( )
} )
it ( 'should handle storage status correctly with S3 storage' , async ( ) = > {
// Create the bucket first using our mock
const createBucketCommand = new S3Commands . CreateBucketCommand ( {
Bucket : 'test-bucket'
} )
await s3Mock . mockS3Client . send ( createBucketCommand )
// Create a new instance with our mocked environment
const s3Storage = new S3CompatibleStorage ( {
bucketName : 'test-bucket' ,
region : 'us-east-1' ,
accessKeyId : 'test-access-key' ,
secretAccessKey : 'test-secret-key' ,
serviceType : 's3'
} )
// Initialize the storage
await s3Storage . init ( )
// Add some data to the storage
const testVector : Vector = [ 0.1 , 0.2 , 0.3 , 0.4 , 0.5 ]
const testNoun = {
id : 'test-noun-1' ,
vector : testVector ,
connections : new Map ( [
[ 0 , new Set ( [ 'test-noun-2' , 'test-noun-3' ] ) ]
] )
}
await s3Storage . saveNoun ( testNoun )
await s3Storage . saveMetadata ( 'test-key' , { test : 'data' , value : 123 } )
// Get storage status
const status = await s3Storage . getStorageStatus ( )
// Verify status
expect ( status . type ) . toBe ( 's3' )
expect ( status . used ) . toBeGreaterThan ( 0 )
// Clean up
await s3Storage . clear ( )
} )
it ( 'should handle multiple objects and pagination with S3 storage' , async ( ) = > {
// Create the bucket first using our mock
const createBucketCommand = new S3Commands . CreateBucketCommand ( {
Bucket : 'test-bucket'
} )
await s3Mock . mockS3Client . send ( createBucketCommand )
// Create a new instance with our mocked environment
const s3Storage = new S3CompatibleStorage ( {
bucketName : 'test-bucket' ,
region : 'us-east-1' ,
accessKeyId : 'test-access-key' ,
secretAccessKey : 'test-secret-key' ,
serviceType : 's3'
} )
// Initialize the storage
await s3Storage . init ( )
// Create multiple test nouns
const testVector : Vector = [ 0.1 , 0.2 , 0.3 , 0.4 , 0.5 ]
const nounCount = 10
for ( let i = 0 ; i < nounCount ; i ++ ) {
const testNoun = {
id : ` test-noun- ${ i } ` ,
vector : testVector ,
connections : new Map ( [
[ 0 , new Set ( [ ` test-noun- ${ ( i + 1 ) % nounCount } ` , ` test-noun- ${ ( i + 2 ) % nounCount } ` ] ) ]
] )
}
await s3Storage . saveNoun ( testNoun )
}
// Test getAllNouns
const allNouns = await s3Storage . getAllNouns ( )
expect ( allNouns . length ) . toBe ( nounCount )
// Clean up
await s3Storage . clear ( )
} )
2025-07-31 10:22:47 -07:00
it ( 'should handle change log functionality correctly with S3 storage' , async ( ) = > {
// Create the bucket first using our mock
const createBucketCommand = new S3Commands . CreateBucketCommand ( {
Bucket : 'test-bucket'
} )
await s3Mock . mockS3Client . send ( createBucketCommand )
// Create a new instance with our mocked environment
const s3Storage = new S3CompatibleStorage ( {
bucketName : 'test-bucket' ,
region : 'us-east-1' ,
accessKeyId : 'test-access-key' ,
secretAccessKey : 'test-secret-key' ,
serviceType : 's3'
} )
// Initialize the storage
await s3Storage . init ( )
// Create test nouns that will generate change log entries
const testVector : Vector = [ 0.1 , 0.2 , 0.3 , 0.4 , 0.5 ]
// Save first noun - should create a change log entry
const testNoun1 = {
id : 'test-noun-change-1' ,
vector : testVector ,
connections : new Map ( )
}
await s3Storage . saveNoun ( testNoun1 )
// Wait a bit to ensure timestamps are different
await new Promise ( resolve = > setTimeout ( resolve , 10 ) )
const firstTimestamp = Date . now ( )
// Wait a bit more before creating second noun
await new Promise ( resolve = > setTimeout ( resolve , 10 ) )
// Save second noun - should create another change log entry
const testNoun2 = {
id : 'test-noun-change-2' ,
vector : testVector ,
connections : new Map ( )
}
await s3Storage . saveNoun ( testNoun2 )
// Get changes since beginning of time
const allChanges = await s3Storage . getChangesSince ( 0 )
// Verify we have at least 2 changes (might be more due to initialization)
expect ( allChanges . length ) . toBeGreaterThanOrEqual ( 2 )
// Verify the changes contain our noun operations
const nounChanges = allChanges . filter ( c = >
c . entityType === 'noun' &&
( c . entityId === 'test-noun-change-1' || c . entityId === 'test-noun-change-2' )
)
expect ( nounChanges . length ) . toBe ( 2 )
// Get changes since first timestamp - should only include the second noun
const recentChanges = await s3Storage . getChangesSince ( firstTimestamp )
const recentNounChanges = recentChanges . filter ( c = >
c . entityType === 'noun' && c . entityId === 'test-noun-change-2'
)
expect ( recentNounChanges . length ) . toBe ( 1 )
// Clean up
await s3Storage . clear ( )
} )
it ( 'should handle change log functionality with getChangesSince' , async ( ) = > {
// Create the bucket first using our mock
const createBucketCommand = new S3Commands . CreateBucketCommand ( {
Bucket : 'test-bucket'
} )
await s3Mock . mockS3Client . send ( createBucketCommand )
// Create a new instance with our mocked environment
const s3Storage = new S3CompatibleStorage ( {
bucketName : 'test-bucket' ,
region : 'us-east-1' ,
accessKeyId : 'test-access-key' ,
secretAccessKey : 'test-secret-key' ,
serviceType : 's3'
} )
// Initialize the storage
await s3Storage . init ( )
// Create test vector
const testVector : Vector = [ 0.1 , 0.2 , 0.3 , 0.4 , 0.5 ]
// Create first noun (older entry)
const testNoun1 = {
id : 'test-noun-cleanup-1' ,
vector : testVector ,
connections : new Map ( )
}
await s3Storage . saveNoun ( testNoun1 )
// Record the timestamp after first noun
const oldTimestamp = Date . now ( )
// Wait to ensure timestamps are different
await new Promise ( resolve = > setTimeout ( resolve , 100 ) )
// Create second noun (newer entry)
const testNoun2 = {
id : 'test-noun-cleanup-2' ,
vector : testVector ,
connections : new Map ( )
}
await s3Storage . saveNoun ( testNoun2 )
// Verify we have both change log entries
const allChanges = await s3Storage . getChangesSince ( 0 )
const testNounChanges = allChanges . filter ( c = >
c . entityType === 'noun' &&
( c . entityId === 'test-noun-cleanup-1' || c . entityId === 'test-noun-cleanup-2' )
)
expect ( testNounChanges . length ) . toBe ( 2 )
// Get changes since oldTimestamp - should only include the second noun
const recentChanges = await s3Storage . getChangesSince ( oldTimestamp )
const recentNounChanges = recentChanges . filter ( c = >
c . entityType === 'noun' &&
( c . entityId === 'test-noun-cleanup-1' || c . entityId === 'test-noun-cleanup-2' )
)
// Should only have the newer entry for test-noun-cleanup-2
expect ( recentNounChanges . length ) . toBe ( 1 )
expect ( recentNounChanges [ 0 ] . entityId ) . toBe ( 'test-noun-cleanup-2' )
// Clean up
await s3Storage . clear ( )
} )
} )