@wearesage/schema
Version:
A flexible schema definition and validation system for TypeScript with multi-database support
289 lines (246 loc) • 9.92 kB
text/typescript
import "reflect-metadata";
import { universalEntityService } from './services/index';
import { MetadataLayerAdapter } from './adapters/metadata-layer';
import { Neo4jAdapter } from './adapters/neo4j';
import { PostgreSQLAdapter } from './adapters/postgresql';
// Import copied entities with full complexity
import { User } from './test-entities/User';
import { Message } from './test-entities/Message';
import { Conversation } from './test-entities/Conversation';
import { Space } from './test-entities/Space';
describe('Full System Integration Tests', () => {
let systemContext: any;
beforeAll(async () => {
// Register entities
universalEntityService.registerEntities([User, Message, Conversation, Space]);
// Create system context
systemContext = {
user: {
id: 'test-system',
username: 'test-system',
email: 'test@system.com',
role: 999,
permissions: ['admin', 'user']
},
requestId: 'test-' + Date.now()
};
});
describe('1. Basic Entity Creation', () => {
let testUser: any;
let testSpace: any;
test('should create a User entity', async () => {
testUser = await universalEntityService.create(User, {
name: 'Test User',
email: 'test@example.com',
status: 'active'
}, systemContext);
expect(testUser).toBeDefined();
expect(testUser.id).toBeDefined();
expect(testUser.name).toBe('Test User');
expect(testUser.email).toBe('test@example.com');
});
test('should create a Space entity', async () => {
testSpace = await universalEntityService.create(Space, {
name: 'Test Space',
spaceType: 'chat',
visibility: 'private',
ownedByType: 'user',
ownedById: testUser.id,
participants: [testUser]
}, systemContext);
expect(testSpace).toBeDefined();
expect(testSpace.id).toBeDefined();
expect(testSpace.name).toBe('Test Space');
expect(testSpace.spaceType).toBe('chat');
});
});
describe('2. Conversation Entity (extends Space)', () => {
let testUser: any;
let testConversation: any;
beforeAll(async () => {
testUser = await universalEntityService.create(User, {
name: 'Conversation Test User',
email: 'conv@example.com',
status: 'active'
}, systemContext);
});
test('should create a Conversation entity with all required properties', async () => {
testConversation = await universalEntityService.create(Conversation, {
// Space properties
name: 'Test Conversation',
spaceType: 'chat',
visibility: 'private',
ownedByType: 'user',
ownedById: testUser.id,
participants: [testUser],
// Conversation-specific properties
model: 'test-model',
temperature: 0.7,
conversationType: 'chat',
status: 'active'
}, systemContext);
expect(testConversation).toBeDefined();
expect(testConversation.id).toBeDefined();
expect(testConversation.model).toBe('test-model');
expect(testConversation.temperature).toBe(0.7);
expect(testConversation.conversationType).toBe('chat');
});
});
describe('3. Message-Conversation Relationships', () => {
let testUser: any;
let testConversation: any;
let testMessage: any;
beforeAll(async () => {
testUser = await universalEntityService.create(User, {
name: 'Message Test User',
email: 'msg@example.com',
status: 'active'
}, systemContext);
testConversation = await universalEntityService.create(Conversation, {
name: 'Message Test Conversation',
spaceType: 'chat',
visibility: 'private',
ownedByType: 'user',
ownedById: testUser.id,
participants: [testUser],
model: 'test-model',
temperature: 0.7,
conversationType: 'chat',
status: 'active'
}, systemContext);
});
test('should create a Message with conversation relationship', async () => {
testMessage = await universalEntityService.create(Message, {
content: 'Hello, this is a test message with embeddings!',
role: 'user',
messageIndex: 0,
conversation: testConversation, // Full object relationship
sender: {
type: 'human',
id: testUser.id,
displayName: 'Test User'
}
}, systemContext);
expect(testMessage).toBeDefined();
expect(testMessage.id).toBeDefined();
expect(testMessage.content).toBe('Hello, this is a test message with embeddings!');
expect(testMessage.role).toBe('user');
expect(testMessage.messageIndex).toBe(0);
});
test('should create a Message with conversation object reference', async () => {
const message2 = await universalEntityService.create(Message, {
content: 'Second message with conversation object',
role: 'assistant',
messageIndex: 1,
conversation: testConversation, // Full object reference
sender: {
type: 'ai',
id: 'test-ai',
displayName: 'Test AI'
}
}, systemContext);
expect(message2).toBeDefined();
expect(message2.content).toBe('Second message with conversation object');
expect(message2.role).toBe('assistant');
});
});
describe('4. Embeddings Generation', () => {
let testUser: any;
let testConversation: any;
let testMessage: any;
beforeAll(async () => {
testUser = await universalEntityService.create(User, {
name: 'Embeddings Test User',
email: 'embed@example.com',
status: 'active'
}, systemContext);
testConversation = await universalEntityService.create(Conversation, {
name: 'Embeddings Test Conversation',
spaceType: 'chat',
visibility: 'private',
ownedByType: 'user',
ownedById: testUser.id,
participants: [testUser],
model: 'test-model',
temperature: 0.7,
conversationType: 'chat',
status: 'active'
}, systemContext);
});
test('should generate embeddings for Message content', async () => {
const consoleSpy = jest.spyOn(console, 'log');
testMessage = await universalEntityService.create(Message, {
content: 'This message should generate embeddings for semantic search!',
role: 'user',
messageIndex: 0,
conversation: testConversation,
thinking: 'Some AI thinking process here...',
sender: {
type: 'human',
id: testUser.id,
displayName: 'Test User'
}
}, systemContext);
// Check if embeddings generation was logged
expect(consoleSpy).toHaveBeenCalledWith('🧠 Generated embeddings for entity');
// Check if contentEmbedding field exists (from @Embeddings decorator)
expect((testMessage as any).contentEmbedding).toBeDefined();
consoleSpy.mockRestore();
});
test('should generate embeddings for Conversation', async () => {
const consoleSpy = jest.spyOn(console, 'log');
const conv = await universalEntityService.create(Conversation, {
name: 'Conversation with semantic embedding',
spaceType: 'chat',
visibility: 'private',
ownedByType: 'user',
ownedById: testUser.id,
participants: [testUser],
model: 'test-model',
temperature: 0.7,
conversationType: 'chat',
status: 'active',
systemPrompt: 'You are a helpful AI assistant focused on testing embeddings.'
}, systemContext);
// Check if embeddings generation was logged
expect(consoleSpy).toHaveBeenCalledWith('🧠 Generated embeddings for entity');
// Check if semanticEmbedding field exists (from @Embeddings decorator)
expect((conv as any).semanticEmbedding).toBeDefined();
consoleSpy.mockRestore();
});
});
describe('5. Metadata Layer Functionality', () => {
test('should create PostgreSQL metadata tables', async () => {
// This test will check if PostgreSQL metadata tables are created
// Tables should be created based on @PostgresMetadata decorators
// We expect tables like:
// - message_metadata (from Message entity)
// - conversation_metadata (from Conversation entity)
// Note: This will be verified by checking actual PostgreSQL tables
expect(true).toBe(true); // Placeholder - will be verified by observing behavior
});
test('should store metadata in PostgreSQL lookup tables', async () => {
// This test verifies that metadata is actually being stored in PostgreSQL
// as lookup tables for the Neo4j graph data
expect(true).toBe(true); // Placeholder - will be verified by checking PostgreSQL
});
});
describe('6. Neo4j Relationship Verification', () => {
test('should create BELONGS_TO relationships in Neo4j', async () => {
// This test verifies that Message -> BELONGS_TO -> Conversation relationships
// are actually created in the Neo4j graph database
expect(true).toBe(true); // Placeholder - will be verified by checking Neo4j
});
});
describe('7. Adapter Configuration Verification', () => {
test('should be using MetadataLayerAdapter (not just Neo4jAdapter)', async () => {
// Verify that the system is actually using the MetadataLayerAdapter
// which wraps Neo4j + PostgreSQL + Embeddings
const service = universalEntityService as any;
const adapter = service.adapter;
expect(adapter).toBeInstanceOf(MetadataLayerAdapter);
expect(adapter.primaryAdapter).toBeInstanceOf(Neo4jAdapter);
expect(adapter.metadataAdapter).toBeInstanceOf(PostgreSQLAdapter);
});
});
});