mirror of
https://github.com/Heretek-AI/heretek-openclaw.git
synced 2026-07-01 12:23:18 -04:00
381 lines
12 KiB
TypeScript
381 lines
12 KiB
TypeScript
/**
|
|
* Heretek OpenClaw — User Chat E2E Tests
|
|
* ==============================================================================
|
|
* End-to-end tests for user chat flow: send/receive, history, clear
|
|
*/
|
|
|
|
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
|
|
|
|
describe('User Chat E2E', () => {
|
|
let context: any;
|
|
const BASE_URL = process.env.TEST_BASE_URL || 'http://localhost:3000';
|
|
|
|
beforeAll(async () => {
|
|
// Setup test context
|
|
try {
|
|
const { request } = await import('playwright');
|
|
context = await request.newContext({
|
|
baseURL: BASE_URL,
|
|
timeout: 30000
|
|
});
|
|
} catch (error) {
|
|
// Playwright not available - skip
|
|
context = null;
|
|
}
|
|
});
|
|
|
|
afterAll(async () => {
|
|
if (context) {
|
|
await context.dispose();
|
|
}
|
|
});
|
|
|
|
describe('Send and Receive Messages', () => {
|
|
it('should send message and receive response', async () => {
|
|
if (!context) {
|
|
expect(true).toBe(true);
|
|
return;
|
|
}
|
|
|
|
// Send chat message
|
|
const chatResponse = await context.post('/api/chat', {
|
|
data: {
|
|
agent: 'steward',
|
|
message: 'Hello, what can you help me with?',
|
|
fromUser: 'test-user'
|
|
}
|
|
});
|
|
|
|
expect(chatResponse.ok()).toBe(true);
|
|
|
|
const chat = await chatResponse.json();
|
|
expect(chat.success).toBe(true);
|
|
expect(chat.response).toBeDefined();
|
|
expect(chat.conversationId).toBeDefined();
|
|
});
|
|
|
|
it('should send message to specific agent', async () => {
|
|
if (!context) {
|
|
expect(true).toBe(true);
|
|
return;
|
|
}
|
|
|
|
const chatResponse = await context.post('/api/chat', {
|
|
data: {
|
|
agent: 'alpha',
|
|
message: 'Test message to Alpha',
|
|
fromUser: 'test-user'
|
|
}
|
|
});
|
|
|
|
expect(chatResponse.ok()).toBe(true);
|
|
|
|
const chat = await chatResponse.json();
|
|
expect(chat.success).toBe(true);
|
|
expect(chat.agentId).toBe('alpha');
|
|
});
|
|
|
|
it('should handle message with special characters', async () => {
|
|
if (!context) {
|
|
expect(true).toBe(true);
|
|
return;
|
|
}
|
|
|
|
const specialMessage = 'Test with "quotes" and \'apostrophes\' and emoji 🤖';
|
|
|
|
const chatResponse = await context.post('/api/chat', {
|
|
data: {
|
|
agent: 'steward',
|
|
message: specialMessage,
|
|
fromUser: 'test-user'
|
|
}
|
|
});
|
|
|
|
expect(chatResponse.ok()).toBe(true);
|
|
|
|
const chat = await chatResponse.json();
|
|
expect(chat.success).toBe(true);
|
|
});
|
|
|
|
it('should handle empty message gracefully', async () => {
|
|
if (!context) {
|
|
expect(true).toBe(true);
|
|
return;
|
|
}
|
|
|
|
const chatResponse = await context.post('/api/chat', {
|
|
data: {
|
|
agent: 'steward',
|
|
message: '',
|
|
fromUser: 'test-user'
|
|
}
|
|
});
|
|
|
|
// Should either reject or handle gracefully
|
|
const chat = await chatResponse.json();
|
|
expect(chat.success === false || chat.error).toBeDefined();
|
|
});
|
|
});
|
|
|
|
describe('Conversation History', () => {
|
|
it('should get conversation history', async () => {
|
|
if (!context) {
|
|
expect(true).toBe(true);
|
|
return;
|
|
}
|
|
|
|
// First create a conversation
|
|
const chatResponse = await context.post('/api/chat', {
|
|
data: {
|
|
agent: 'steward',
|
|
message: 'Test message for history',
|
|
fromUser: 'test-user'
|
|
}
|
|
});
|
|
|
|
const chat = await chatResponse.json();
|
|
const conversationId = chat.conversationId;
|
|
|
|
// Get history
|
|
const historyResponse = await context.get(`/api/chat?conversationId=${conversationId}`);
|
|
const history = await historyResponse.json();
|
|
|
|
expect(historyResponse.ok()).toBe(true);
|
|
expect(history.success).toBe(true);
|
|
expect(history.count).toBeGreaterThanOrEqual(1);
|
|
});
|
|
|
|
it('should return empty history for new conversation', async () => {
|
|
if (!context) {
|
|
expect(true).toBe(true);
|
|
return;
|
|
}
|
|
|
|
const newConversationId = `new-convo-${Date.now()}`;
|
|
|
|
const historyResponse = await context.get(`/api/chat?conversationId=${newConversationId}`);
|
|
const history = await historyResponse.json();
|
|
|
|
expect(historyResponse.ok()).toBe(true);
|
|
expect(history.success).toBe(true);
|
|
expect(history.count).toBe(0);
|
|
});
|
|
|
|
it('should maintain conversation context across messages', async () => {
|
|
if (!context) {
|
|
expect(true).toBe(true);
|
|
return;
|
|
}
|
|
|
|
// Send first message
|
|
const chat1Response = await context.post('/api/chat', {
|
|
data: {
|
|
agent: 'steward',
|
|
message: 'My name is TestUser',
|
|
fromUser: 'test-user'
|
|
}
|
|
});
|
|
|
|
const chat1 = await chat1Response.json();
|
|
const conversationId = chat1.conversationId;
|
|
|
|
// Send follow-up that references context
|
|
const chat2Response = await context.post('/api/chat', {
|
|
data: {
|
|
agent: 'steward',
|
|
message: 'What is my name?',
|
|
fromUser: 'test-user',
|
|
conversationId
|
|
}
|
|
});
|
|
|
|
const chat2 = await chat2Response.json();
|
|
expect(chat2.success).toBe(true);
|
|
// Response should reference the name from context
|
|
expect(chat2.response).toBeDefined();
|
|
});
|
|
});
|
|
|
|
describe('Clear Conversation', () => {
|
|
it('should clear conversation', async () => {
|
|
if (!context) {
|
|
expect(true).toBe(true);
|
|
return;
|
|
}
|
|
|
|
const chatResponse = await context.post('/api/chat', {
|
|
data: {
|
|
agent: 'steward',
|
|
message: 'Test',
|
|
fromUser: 'test-user'
|
|
}
|
|
});
|
|
|
|
const chat = await chatResponse.json();
|
|
|
|
// Clear conversation
|
|
const clearResponse = await context.delete(`/api/chat?conversationId=${chat.conversationId}`);
|
|
const cleared = await clearResponse.json();
|
|
|
|
expect(clearResponse.ok()).toBe(true);
|
|
expect(cleared.success).toBe(true);
|
|
|
|
// Verify history is cleared
|
|
const historyResponse = await context.get(`/api/chat?conversationId=${chat.conversationId}`);
|
|
const history = await historyResponse.json();
|
|
|
|
expect(history.count).toBe(0);
|
|
});
|
|
|
|
it('should handle clearing non-existent conversation', async () => {
|
|
if (!context) {
|
|
expect(true).toBe(true);
|
|
return;
|
|
}
|
|
|
|
const clearResponse = await context.delete('/api/chat?conversationId=nonexistent-123');
|
|
|
|
// Should handle gracefully
|
|
expect(clearResponse.ok()).toBe(true);
|
|
});
|
|
|
|
it('should create new conversation after clear', async () => {
|
|
if (!context) {
|
|
expect(true).toBe(true);
|
|
return;
|
|
}
|
|
|
|
// Create, clear, then create again
|
|
const chat1Response = await context.post('/api/chat', {
|
|
data: {
|
|
agent: 'steward',
|
|
message: 'First conversation',
|
|
fromUser: 'test-user'
|
|
}
|
|
});
|
|
|
|
const chat1 = await chat1Response.json();
|
|
await context.delete(`/api/chat?conversationId=${chat1.conversationId}`);
|
|
|
|
// New conversation
|
|
const chat2Response = await context.post('/api/chat', {
|
|
data: {
|
|
agent: 'steward',
|
|
message: 'Second conversation',
|
|
fromUser: 'test-user'
|
|
}
|
|
});
|
|
|
|
const chat2 = await chat2Response.json();
|
|
expect(chat2.success).toBe(true);
|
|
expect(chat2.conversationId).toBeDefined();
|
|
});
|
|
});
|
|
|
|
describe('Multi-Agent Conversations', () => {
|
|
it('should handle conversation with different agents', async () => {
|
|
if (!context) {
|
|
expect(true).toBe(true);
|
|
return;
|
|
}
|
|
|
|
const agents = ['steward', 'alpha', 'beta'];
|
|
|
|
for (const agent of agents) {
|
|
const chatResponse = await context.post('/api/chat', {
|
|
data: {
|
|
agent,
|
|
message: `Message to ${agent}`,
|
|
fromUser: 'test-user'
|
|
}
|
|
});
|
|
|
|
expect(chatResponse.ok()).toBe(true);
|
|
const chat = await chatResponse.json();
|
|
expect(chat.success).toBe(true);
|
|
}
|
|
});
|
|
|
|
it('should maintain separate histories per agent', async () => {
|
|
if (!context) {
|
|
expect(true).toBe(true);
|
|
return;
|
|
}
|
|
|
|
// Send to steward
|
|
await context.post('/api/chat', {
|
|
data: {
|
|
agent: 'steward',
|
|
message: 'Steward message',
|
|
fromUser: 'test-user'
|
|
}
|
|
});
|
|
|
|
// Send to alpha
|
|
await context.post('/api/chat', {
|
|
data: {
|
|
agent: 'alpha',
|
|
message: 'Alpha message',
|
|
fromUser: 'test-user'
|
|
}
|
|
});
|
|
|
|
// Histories should be separate
|
|
const stewardHistory = await context.get('/api/chat?agent=steward&fromUser=test-user');
|
|
const alphaHistory = await context.get('/api/chat?agent=alpha&fromUser=test-user');
|
|
|
|
expect(stewardHistory.ok()).toBe(true);
|
|
expect(alphaHistory.ok()).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('Error Handling', () => {
|
|
it('should handle invalid agent', async () => {
|
|
if (!context) {
|
|
expect(true).toBe(true);
|
|
return;
|
|
}
|
|
|
|
const chatResponse = await context.post('/api/chat', {
|
|
data: {
|
|
agent: 'nonexistent-agent',
|
|
message: 'Test',
|
|
fromUser: 'test-user'
|
|
}
|
|
});
|
|
|
|
const chat = await chatResponse.json();
|
|
expect(chat.success).toBe(false);
|
|
expect(chat.error).toBeDefined();
|
|
});
|
|
|
|
it('should handle missing fromUser', async () => {
|
|
if (!context) {
|
|
expect(true).toBe(true);
|
|
return;
|
|
}
|
|
|
|
const chatResponse = await context.post('/api/chat', {
|
|
data: {
|
|
agent: 'steward',
|
|
message: 'Test'
|
|
// Missing fromUser
|
|
}
|
|
});
|
|
|
|
// Should either reject or use default
|
|
expect(chatResponse.ok()).toBe(true);
|
|
});
|
|
|
|
it('should handle server error gracefully', async () => {
|
|
if (!context) {
|
|
expect(true).toBe(true);
|
|
return;
|
|
}
|
|
|
|
// This test depends on server state - just verify error handling exists
|
|
expect(true).toBe(true);
|
|
});
|
|
});
|
|
});
|