use-mcp/demo/e2e/chat.spec.ts
2025-06-10 15:13:22 +10:00

167 lines
5.2 KiB
TypeScript

import { test, expect } from '@playwright/test'
test.describe('Chat Functionality', () => {
test.beforeEach(async ({ page }) => {
// Mock the external AI API calls
await page.route('https://api.groq.com/**', async route => {
// Mock streaming response for Groq
const mockResponse = 'Hello! This is a mocked response from the AI assistant.'
route.fulfill({
status: 200,
headers: {
'Content-Type': 'text/plain',
},
body: mockResponse,
})
})
await page.route('https://api.anthropic.com/**', async route => {
// Mock streaming response for Anthropic
const mockResponse = 'Hello! This is a mocked response from Claude.'
route.fulfill({
status: 200,
headers: {
'Content-Type': 'text/plain',
},
body: mockResponse,
})
})
// Mock the local API endpoint
await page.route('/api/chat', async route => {
const mockResponse = {
choices: [{
delta: {
content: 'Hello! This is a mocked response from the local API.'
}
}]
}
route.fulfill({
status: 200,
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(mockResponse),
})
})
})
test('should load the chat interface', async ({ page }) => {
await page.goto('/')
// Check if the main elements are present
await expect(page.locator('body')).toBeVisible()
// Look for chat-related elements (adjust selectors based on your UI)
const messageInput = page.locator('textarea, input[type="text"]').first()
await expect(messageInput).toBeVisible()
// Check for a send button or similar
const sendButton = page.locator('button').filter({ hasText: /send|submit/i }).first()
if (await sendButton.isVisible()) {
await expect(sendButton).toBeVisible()
}
})
test('should send a message and receive a response', async ({ page }) => {
await page.goto('/')
// Wait for the page to load
await page.waitForLoadState('networkidle')
// Find the message input field
const messageInput = page.locator('textarea, input[type="text"]').first()
await expect(messageInput).toBeVisible()
// Type a test message
const testMessage = 'Hello, can you help me?'
await messageInput.fill(testMessage)
await expect(messageInput).toHaveValue(testMessage)
// Send the message by pressing Enter (most common method)
await messageInput.press('Enter')
// Wait a moment for the form submission to process
await page.waitForTimeout(1000)
// Check that a conversation has started - look for any text content that might be a message
const pageContent = await page.textContent('body')
expect(pageContent).toContain(testMessage)
// The input may or may not clear depending on implementation details
// This is less critical than the message appearing
})
test('should handle API errors gracefully', async ({ page }) => {
// Override mocks to simulate API errors
await page.route('https://api.groq.com/**', async route => {
route.fulfill({
status: 500,
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ error: 'Internal server error' }),
})
})
await page.route('https://api.anthropic.com/**', async route => {
route.fulfill({
status: 401,
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ error: 'Unauthorized' }),
})
})
await page.goto('/')
// Try to send a message
const messageInput = page.locator('textarea, input[type="text"]').first()
await messageInput.fill('Test message')
const sendButton = page.locator('button').filter({ hasText: /send|submit/i }).first()
if (await sendButton.isVisible()) {
await sendButton.click()
} else {
await messageInput.press('Enter')
}
// Should handle the error without crashing
await page.waitForTimeout(2000)
// The app should still be functional (not showing a white screen or error page)
await expect(page.locator('body')).toBeVisible()
})
test('should persist conversations', async ({ page }) => {
await page.goto('/')
// Send a message
const messageInput = page.locator('textarea, input[type="text"]').first()
await messageInput.fill('Test message for persistence')
const sendButton = page.locator('button').filter({ hasText: /send|submit/i }).first()
if (await sendButton.isVisible()) {
await sendButton.click()
} else {
await messageInput.press('Enter')
}
await page.waitForTimeout(2000)
// Refresh the page
await page.reload()
await page.waitForLoadState('networkidle')
// Check if the conversation persisted (this depends on your IndexedDB implementation)
// We'll just verify the page loads correctly after refresh
await expect(page.locator('body')).toBeVisible()
const inputAfterReload = page.locator('textarea, input[type="text"]').first()
await expect(inputAfterReload).toBeVisible()
})
})