167 lines
5.2 KiB
TypeScript
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()
|
|
})
|
|
})
|