@wearesage/schema
Version:
A flexible schema definition and validation system for TypeScript with multi-database support
197 lines (162 loc) • 6.77 kB
text/typescript
import "reflect-metadata";
import { UniversalEntityService, EntityContext } from "../../services/UniversalEntityService";
import { TestConversation } from "../test-entities/TestConversation";
import { TestMessage } from "../test-entities/TestMessage";
import { TestUser } from "../test-entities/TestUser";
describe("UniversalEntityService Relationships", () => {
let service: UniversalEntityService;
let userContext: EntityContext;
beforeEach(() => {
service = UniversalEntityService.getInstance();
service.registerEntities([TestUser, TestConversation, TestMessage]);
userContext = {
user: {
id: 'user123',
username: 'testuser',
email: 'test@example.com',
role: 0,
permissions: ['user']
}
};
});
afterAll(async () => {
if ((service as any).adapter && (service as any).adapter.close) {
await (service as any).adapter.close();
}
});
describe("Entity Creation with Relationships", () => {
test("should create conversation and message with relationship", async () => {
// Create conversation
const conversation = await service.create(TestConversation, {
name: 'Test Conversation',
messageCount: 0
}, userContext);
console.log('✅ Created conversation:', conversation.id);
// Create message with conversation relationship
const message = await service.create(TestMessage, {
content: 'Hello world',
role: 'user',
messageIndex: 0,
conversation: conversation // 🔥 THIS IS THE CRITICAL RELATIONSHIP!
}, userContext);
console.log('✅ Created message:', message.id);
console.log('🔍 Message conversation:', message.conversation);
// Verify the relationship exists
expect(message.conversation).toBeDefined();
expect(message.conversation.id).toBe(conversation.id);
});
test("should create message with conversation ID reference", async () => {
// Create conversation
const conversation = await service.create(TestConversation, {
name: 'Test Conversation',
messageCount: 0
}, userContext);
// Create message with conversation ID (how our ingestion works)
const message = await service.create(TestMessage, {
content: 'Hello world',
role: 'user',
messageIndex: 0,
conversation: conversation // 🔥 Pass full conversation object
}, userContext);
console.log('✅ Created message with ID reference:', message.id);
console.log('🔍 Message conversation:', message.conversation);
// Verify the relationship exists
expect(message.conversation).toBeDefined();
expect(message.conversation.id).toBe(conversation.id);
});
});
describe("Relationship Querying", () => {
let conversation: TestConversation;
let message1: TestMessage;
let message2: TestMessage;
beforeEach(async () => {
// Create test data
conversation = await service.create(TestConversation, {
name: 'Test Conversation',
messageCount: 2
}, userContext);
message1 = await service.create(TestMessage, {
content: 'First message',
role: 'user',
messageIndex: 0,
conversation: conversation
}, userContext);
message2 = await service.create(TestMessage, {
content: 'Second message',
role: 'assistant',
messageIndex: 1,
conversation: conversation
}, userContext);
});
test("should query messages by conversation", async () => {
// Query all messages for this conversation
const messages = await service.findAll(TestMessage, {
conversation: conversation.id
}, userContext);
console.log('🔍 Found messages:', messages.length);
console.log('📄 Message contents:', messages.map(m => m.content));
expect(messages).toHaveLength(2);
expect(messages[0].conversation.id).toBe(conversation.id);
expect(messages[1].conversation.id).toBe(conversation.id);
});
test("should load related messages for conversation", async () => {
// Load the conversation with its messages
const loadedConversation = await service.findById(TestConversation, conversation.id, userContext);
expect(loadedConversation).toBeDefined();
// Try to load related messages
try {
const relatedMessages = await service.loadRelated(TestConversation, conversation.id, 'messages', userContext);
console.log('🔍 Related messages:', relatedMessages.length);
expect(relatedMessages).toHaveLength(2);
expect((relatedMessages[0] as any).content).toBeDefined();
} catch (error) {
console.error('❌ Failed to load related messages:', error);
throw error;
}
});
});
describe("Neo4j Direct Relationship Verification", () => {
test("should verify relationships exist in Neo4j", async () => {
// Create conversation and message
const conversation = await service.create(TestConversation, {
name: 'Neo4j Test Conversation',
messageCount: 1
}, userContext);
const message = await service.create(TestMessage, {
content: 'Neo4j test message',
role: 'user',
messageIndex: 0,
conversation: conversation
}, userContext);
// Check if Neo4j has the relationship
const neo4jAdapter = (service as any).adapter;
if (neo4jAdapter.type === 'neo4j') {
const relationshipQuery = `
MATCH (m:TestMessage {id: $messageId})-[r]->(c:TestConversation {id: $conversationId})
RETURN type(r) as relationshipType, count(r) as relationshipCount
`;
const result = await neo4jAdapter.runNativeQuery(relationshipQuery, {
messageId: message.id,
conversationId: conversation.id
});
console.log('🔍 Neo4j relationship result:', result);
expect(result).toBeDefined();
// We expect to find at least one relationship
expect(result.relationshipCount).toBeGreaterThan(0);
}
});
test("should count total relationships in Neo4j", async () => {
const neo4jAdapter = (service as any).adapter;
if (neo4jAdapter.type === 'neo4j') {
const relationshipCountQuery = `
MATCH ()-[r]->()
RETURN count(r) as totalRelationships
`;
const result = await neo4jAdapter.runNativeQuery(relationshipCountQuery);
console.log('🔍 Total relationships in Neo4j:', result);
// We should have SOME relationships if our entities are connected
expect(result.totalRelationships).toBeGreaterThan(0);
}
});
});
});