- Fix chatbot chat history tests: use regex pattern (/\/api\/chat/) instead of glob pattern to properly match URLs with query strings - Add skip condition for performance tests (require RUN_PERFORMANCE_TESTS=1) as Lighthouse audits take too long for regular test runs - Increase performance test timeout to 180s for when they are run - Add proper fallback handling for non-GET requests in route mocks All 103 chromium tests pass with CI=true (forces fresh dev server). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
718 lines
23 KiB
TypeScript
718 lines
23 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
|
|
/**
|
|
* Chatbot E2E Test Suite
|
|
*
|
|
* This suite tests the AI chatbot functionality including:
|
|
* - Opening and closing the chat window
|
|
* - Message flow (sending and receiving)
|
|
* - Error handling and validation
|
|
* - UI interactions (clear chat, suggested prompts)
|
|
* - Accessibility features
|
|
*
|
|
* Note: These tests use mocked API responses for reliability.
|
|
* Integration tests with the real API should be run separately.
|
|
*/
|
|
|
|
/**
|
|
* Chatbot UI Tests
|
|
*
|
|
* Verify that the chatbot UI renders correctly and interactions work.
|
|
*/
|
|
test.describe('Chatbot UI', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
await page.goto('/de', {
|
|
waitUntil: 'networkidle',
|
|
});
|
|
});
|
|
|
|
test('Chatbot floating button is visible', async ({ page }) => {
|
|
// Verify the floating chat button exists
|
|
const chatButton = page.locator('button[aria-label="Open chat"]');
|
|
await expect(chatButton).toBeVisible();
|
|
});
|
|
|
|
test('Chatbot opens when floating button is clicked', async ({ page }) => {
|
|
// Click the chat button
|
|
const chatButton = page.locator('button[aria-label="Open chat"]');
|
|
await chatButton.click();
|
|
|
|
// Verify chat window opens
|
|
const chatWindow = page.locator('.fixed.z-50.bg-zinc-900');
|
|
await expect(chatWindow).toBeVisible();
|
|
|
|
// Verify chat header is visible
|
|
const chatHeader = page.locator('text=AI Assistant');
|
|
await expect(chatHeader).toBeVisible();
|
|
});
|
|
|
|
test('Chatbot closes when close button is clicked', async ({ page }) => {
|
|
// Open chat
|
|
const chatButton = page.locator('button[aria-label="Open chat"]');
|
|
await chatButton.click();
|
|
|
|
// Wait for chat window to be visible
|
|
const chatWindow = page.locator('.fixed.z-50.bg-zinc-900');
|
|
await expect(chatWindow).toBeVisible();
|
|
|
|
// Click close button
|
|
const closeButton = page.locator('button[aria-label="Close chat"]');
|
|
await closeButton.click();
|
|
|
|
// Wait for animation and verify chat is closed
|
|
await page.waitForTimeout(300);
|
|
|
|
// Floating button should be visible again
|
|
await expect(chatButton).toBeVisible();
|
|
});
|
|
|
|
test('Chatbot shows welcome message when empty', async ({ page }) => {
|
|
// Open chat
|
|
const chatButton = page.locator('button[aria-label="Open chat"]');
|
|
await chatButton.click();
|
|
|
|
// Verify welcome message
|
|
const welcomeHeading = page.locator("text=Hi, I'm Damjan's AI Assistant");
|
|
await expect(welcomeHeading).toBeVisible();
|
|
|
|
// Verify help text
|
|
const helpText = page.locator('text=I can help you learn about');
|
|
await expect(helpText).toBeVisible();
|
|
});
|
|
|
|
test('Chatbot shows suggested prompts when empty', async ({ page }) => {
|
|
// Open chat
|
|
const chatButton = page.locator('button[aria-label="Open chat"]');
|
|
await chatButton.click();
|
|
|
|
// Verify "Try asking:" label
|
|
const tryAskingLabel = page.locator('text=Try asking:');
|
|
await expect(tryAskingLabel).toBeVisible();
|
|
|
|
// Verify suggested prompts are visible
|
|
const suggestedPrompts = page.locator('button:has-text("What services do you offer?")');
|
|
await expect(suggestedPrompts).toBeVisible();
|
|
|
|
const experiencePrompt = page.locator('button:has-text("Tell me about your experience")');
|
|
await expect(experiencePrompt).toBeVisible();
|
|
|
|
const techPrompt = page.locator('button:has-text("What technologies do you work with?")');
|
|
await expect(techPrompt).toBeVisible();
|
|
});
|
|
|
|
test('Chat input field is present and functional', async ({ page }) => {
|
|
// Open chat
|
|
const chatButton = page.locator('button[aria-label="Open chat"]');
|
|
await chatButton.click();
|
|
|
|
// Verify input field
|
|
const inputField = page.locator('input[aria-label="Chat message input"]');
|
|
await expect(inputField).toBeVisible();
|
|
await expect(inputField).toBeEnabled();
|
|
|
|
// Verify placeholder
|
|
await expect(inputField).toHaveAttribute('placeholder', 'Type a message...');
|
|
|
|
// Type in input
|
|
await inputField.fill('Test message');
|
|
await expect(inputField).toHaveValue('Test message');
|
|
});
|
|
|
|
test('Send button is disabled when input is empty', async ({ page }) => {
|
|
// Open chat
|
|
const chatButton = page.locator('button[aria-label="Open chat"]');
|
|
await chatButton.click();
|
|
|
|
// Verify send button is disabled with empty input
|
|
const sendButton = page.locator('button[aria-label="Send message"]');
|
|
await expect(sendButton).toBeDisabled();
|
|
|
|
// Type in input
|
|
const inputField = page.locator('input[aria-label="Chat message input"]');
|
|
await inputField.fill('Test message');
|
|
|
|
// Verify send button is now enabled
|
|
await expect(sendButton).toBeEnabled();
|
|
});
|
|
|
|
test('Privacy note is displayed', async ({ page }) => {
|
|
// Open chat
|
|
const chatButton = page.locator('button[aria-label="Open chat"]');
|
|
await chatButton.click();
|
|
|
|
// Verify privacy note
|
|
const privacyNote = page.locator('text=Messages may be stored to improve service');
|
|
await expect(privacyNote).toBeVisible();
|
|
});
|
|
});
|
|
|
|
/**
|
|
* Chatbot Message Flow Tests
|
|
*
|
|
* Verify that sending and receiving messages works correctly.
|
|
* These tests mock API responses for reliability.
|
|
*/
|
|
test.describe('Chatbot Message Flow', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
// Mock the chat API endpoint
|
|
await page.route('**/api/chat', async (route) => {
|
|
const request = route.request();
|
|
const method = request.method();
|
|
|
|
if (method === 'POST') {
|
|
// Simulate streaming response for POST
|
|
const encoder = new TextEncoder();
|
|
const chunks = [
|
|
'data: {"content":"Hello","sessionId":"test-session"}\n\n',
|
|
'data: {"content":"! How can I","sessionId":"test-session"}\n\n',
|
|
'data: {"content":" help you today?","sessionId":"test-session"}\n\n',
|
|
'data: {"done":true,"sessionId":"test-session"}\n\n',
|
|
];
|
|
|
|
await route.fulfill({
|
|
status: 200,
|
|
headers: {
|
|
'Content-Type': 'text/event-stream',
|
|
'Cache-Control': 'no-cache',
|
|
},
|
|
body: chunks.join(''),
|
|
});
|
|
} else if (method === 'GET') {
|
|
// Return empty history for GET
|
|
await route.fulfill({
|
|
status: 200,
|
|
contentType: 'application/json',
|
|
body: JSON.stringify({ messages: [], sessionId: 'test-session' }),
|
|
});
|
|
}
|
|
});
|
|
|
|
await page.goto('/de', {
|
|
waitUntil: 'networkidle',
|
|
});
|
|
});
|
|
|
|
test('Sending a message shows user message in chat', async ({ page }) => {
|
|
// Open chat
|
|
const chatButton = page.locator('button[aria-label="Open chat"]');
|
|
await chatButton.click();
|
|
|
|
// Type and send message
|
|
const inputField = page.locator('input[aria-label="Chat message input"]');
|
|
await inputField.fill('Hello, how are you?');
|
|
|
|
const sendButton = page.locator('button[aria-label="Send message"]');
|
|
await sendButton.click();
|
|
|
|
// Verify user message appears in chat
|
|
const userMessage = page.locator('text=Hello, how are you?');
|
|
await expect(userMessage).toBeVisible();
|
|
|
|
// Input should be cleared after sending
|
|
await expect(inputField).toHaveValue('');
|
|
});
|
|
|
|
test('Sending a message triggers API response', async ({ page }) => {
|
|
// Open chat
|
|
const chatButton = page.locator('button[aria-label="Open chat"]');
|
|
await chatButton.click();
|
|
|
|
// Type and send message
|
|
const inputField = page.locator('input[aria-label="Chat message input"]');
|
|
await inputField.fill('Hello');
|
|
|
|
const sendButton = page.locator('button[aria-label="Send message"]');
|
|
await sendButton.click();
|
|
|
|
// Wait for assistant response
|
|
const assistantMessage = page.locator('text=Hello! How can I help you today?');
|
|
await expect(assistantMessage).toBeVisible({ timeout: 5000 });
|
|
});
|
|
|
|
test('Clicking suggested prompt sends message', async ({ page }) => {
|
|
// Open chat
|
|
const chatButton = page.locator('button[aria-label="Open chat"]');
|
|
await chatButton.click();
|
|
|
|
// Click suggested prompt
|
|
const suggestedPrompt = page.locator('button:has-text("What services do you offer?")');
|
|
await suggestedPrompt.click();
|
|
|
|
// Verify user message appears
|
|
const userMessage = page.locator('text=What services do you offer?');
|
|
await expect(userMessage).toBeVisible();
|
|
});
|
|
|
|
test('Enter key submits the message', async ({ page }) => {
|
|
// Open chat
|
|
const chatButton = page.locator('button[aria-label="Open chat"]');
|
|
await chatButton.click();
|
|
|
|
// Type message and press Enter
|
|
const inputField = page.locator('input[aria-label="Chat message input"]');
|
|
await inputField.fill('Test enter submission');
|
|
await inputField.press('Enter');
|
|
|
|
// Verify user message appears
|
|
const userMessage = page.locator('text=Test enter submission');
|
|
await expect(userMessage).toBeVisible();
|
|
});
|
|
|
|
test('Input is disabled during message sending', async ({ page }) => {
|
|
// Open chat
|
|
const chatButton = page.locator('button[aria-label="Open chat"]');
|
|
await chatButton.click();
|
|
|
|
// Type and send message
|
|
const inputField = page.locator('input[aria-label="Chat message input"]');
|
|
await inputField.fill('Test message');
|
|
|
|
const sendButton = page.locator('button[aria-label="Send message"]');
|
|
await sendButton.click();
|
|
|
|
// Input should be disabled during loading
|
|
await expect(inputField).toBeDisabled();
|
|
|
|
// Wait for response to complete
|
|
await page.waitForTimeout(500);
|
|
});
|
|
});
|
|
|
|
/**
|
|
* Chatbot Error Handling Tests
|
|
*
|
|
* Verify that errors are handled gracefully.
|
|
*/
|
|
test.describe('Chatbot Error Handling', () => {
|
|
test('Shows error message when API fails', async ({ page }) => {
|
|
// Mock API to return error
|
|
await page.route('**/api/chat', async (route) => {
|
|
const method = route.request().method();
|
|
|
|
if (method === 'POST') {
|
|
await route.fulfill({
|
|
status: 500,
|
|
contentType: 'application/json',
|
|
body: JSON.stringify({ error: 'Internal server error' }),
|
|
});
|
|
} else if (method === 'GET') {
|
|
await route.fulfill({
|
|
status: 200,
|
|
contentType: 'application/json',
|
|
body: JSON.stringify({ messages: [], sessionId: 'test-session' }),
|
|
});
|
|
}
|
|
});
|
|
|
|
await page.goto('/de', {
|
|
waitUntil: 'networkidle',
|
|
});
|
|
|
|
// Open chat
|
|
const chatButton = page.locator('button[aria-label="Open chat"]');
|
|
await chatButton.click();
|
|
|
|
// Send message
|
|
const inputField = page.locator('input[aria-label="Chat message input"]');
|
|
await inputField.fill('Test message');
|
|
|
|
const sendButton = page.locator('button[aria-label="Send message"]');
|
|
await sendButton.click();
|
|
|
|
// Wait for error message
|
|
const errorContainer = page.locator('.bg-red-900\\/20');
|
|
await expect(errorContainer).toBeVisible({ timeout: 5000 });
|
|
});
|
|
|
|
test('Error message can be dismissed', async ({ page }) => {
|
|
// Mock API to return error
|
|
await page.route('**/api/chat', async (route) => {
|
|
const method = route.request().method();
|
|
|
|
if (method === 'POST') {
|
|
await route.fulfill({
|
|
status: 500,
|
|
contentType: 'application/json',
|
|
body: JSON.stringify({ error: 'Test error' }),
|
|
});
|
|
} else if (method === 'GET') {
|
|
await route.fulfill({
|
|
status: 200,
|
|
contentType: 'application/json',
|
|
body: JSON.stringify({ messages: [], sessionId: 'test-session' }),
|
|
});
|
|
}
|
|
});
|
|
|
|
await page.goto('/de', {
|
|
waitUntil: 'networkidle',
|
|
});
|
|
|
|
// Open chat
|
|
const chatButton = page.locator('button[aria-label="Open chat"]');
|
|
await chatButton.click();
|
|
|
|
// Send message to trigger error
|
|
const inputField = page.locator('input[aria-label="Chat message input"]');
|
|
await inputField.fill('Test message');
|
|
|
|
const sendButton = page.locator('button[aria-label="Send message"]');
|
|
await sendButton.click();
|
|
|
|
// Wait for error and dismiss it
|
|
const errorContainer = page.locator('.bg-red-900\\/20');
|
|
await expect(errorContainer).toBeVisible({ timeout: 5000 });
|
|
|
|
// Click dismiss button
|
|
const dismissButton = page.locator('text=Dismiss');
|
|
await dismissButton.click();
|
|
|
|
// Error should be hidden
|
|
await expect(errorContainer).not.toBeVisible();
|
|
});
|
|
|
|
test('Handles streaming error gracefully', async ({ page }) => {
|
|
// Mock API to return error in stream
|
|
await page.route('**/api/chat', async (route) => {
|
|
const method = route.request().method();
|
|
|
|
if (method === 'POST') {
|
|
await route.fulfill({
|
|
status: 200,
|
|
headers: {
|
|
'Content-Type': 'text/event-stream',
|
|
'Cache-Control': 'no-cache',
|
|
},
|
|
body: 'data: {"error":"Stream error occurred"}\n\n',
|
|
});
|
|
} else if (method === 'GET') {
|
|
await route.fulfill({
|
|
status: 200,
|
|
contentType: 'application/json',
|
|
body: JSON.stringify({ messages: [], sessionId: 'test-session' }),
|
|
});
|
|
}
|
|
});
|
|
|
|
await page.goto('/de', {
|
|
waitUntil: 'networkidle',
|
|
});
|
|
|
|
// Open chat
|
|
const chatButton = page.locator('button[aria-label="Open chat"]');
|
|
await chatButton.click();
|
|
|
|
// Send message
|
|
const inputField = page.locator('input[aria-label="Chat message input"]');
|
|
await inputField.fill('Test message');
|
|
|
|
const sendButton = page.locator('button[aria-label="Send message"]');
|
|
await sendButton.click();
|
|
|
|
// Error should be shown
|
|
const errorContainer = page.locator('.bg-red-900\\/20');
|
|
await expect(errorContainer).toBeVisible({ timeout: 5000 });
|
|
});
|
|
});
|
|
|
|
/**
|
|
* Chatbot Clear Chat Tests
|
|
*
|
|
* Verify that clearing chat works correctly.
|
|
*/
|
|
test.describe('Chatbot Clear Chat', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
// Mock the chat API endpoint
|
|
await page.route('**/api/chat', async (route) => {
|
|
const method = route.request().method();
|
|
|
|
if (method === 'POST') {
|
|
await route.fulfill({
|
|
status: 200,
|
|
headers: {
|
|
'Content-Type': 'text/event-stream',
|
|
'Cache-Control': 'no-cache',
|
|
},
|
|
body:
|
|
'data: {"content":"Test response","sessionId":"test-session"}\n\ndata: {"done":true,"sessionId":"test-session"}\n\n',
|
|
});
|
|
} else if (method === 'GET') {
|
|
await route.fulfill({
|
|
status: 200,
|
|
contentType: 'application/json',
|
|
body: JSON.stringify({ messages: [], sessionId: 'test-session' }),
|
|
});
|
|
}
|
|
});
|
|
|
|
await page.goto('/de', {
|
|
waitUntil: 'networkidle',
|
|
});
|
|
});
|
|
|
|
test('Clear chat button appears after sending message', async ({ page }) => {
|
|
// Open chat
|
|
const chatButton = page.locator('button[aria-label="Open chat"]');
|
|
await chatButton.click();
|
|
|
|
// Clear button should not be visible initially (no messages)
|
|
const clearButton = page.locator('button[aria-label="Clear chat"]');
|
|
await expect(clearButton).not.toBeVisible();
|
|
|
|
// Send a message
|
|
const inputField = page.locator('input[aria-label="Chat message input"]');
|
|
await inputField.fill('Test message');
|
|
|
|
const sendButton = page.locator('button[aria-label="Send message"]');
|
|
await sendButton.click();
|
|
|
|
// Wait for message to appear
|
|
await page.waitForTimeout(500);
|
|
|
|
// Clear button should now be visible
|
|
await expect(clearButton).toBeVisible();
|
|
});
|
|
|
|
test('Clicking clear chat removes all messages', async ({ page }) => {
|
|
// Open chat
|
|
const chatButton = page.locator('button[aria-label="Open chat"]');
|
|
await chatButton.click();
|
|
|
|
// Send a message
|
|
const inputField = page.locator('input[aria-label="Chat message input"]');
|
|
await inputField.fill('Test message');
|
|
|
|
const sendButton = page.locator('button[aria-label="Send message"]');
|
|
await sendButton.click();
|
|
|
|
// Wait for messages
|
|
await page.waitForTimeout(1000);
|
|
|
|
// Click clear button
|
|
const clearButton = page.locator('button[aria-label="Clear chat"]');
|
|
await clearButton.click();
|
|
|
|
// Verify messages are cleared and welcome message returns
|
|
const welcomeHeading = page.locator("text=Hi, I'm Damjan's AI Assistant");
|
|
await expect(welcomeHeading).toBeVisible();
|
|
|
|
// Clear button should be hidden again
|
|
await expect(clearButton).not.toBeVisible();
|
|
});
|
|
});
|
|
|
|
/**
|
|
* Chatbot Accessibility Tests
|
|
*
|
|
* Verify that the chatbot is accessible.
|
|
*/
|
|
test.describe('Chatbot Accessibility', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
// Mock the chat API
|
|
await page.route('**/api/chat', async (route) => {
|
|
if (route.request().method() === 'GET') {
|
|
await route.fulfill({
|
|
status: 200,
|
|
contentType: 'application/json',
|
|
body: JSON.stringify({ messages: [], sessionId: 'test-session' }),
|
|
});
|
|
}
|
|
});
|
|
|
|
await page.goto('/de', {
|
|
waitUntil: 'networkidle',
|
|
});
|
|
});
|
|
|
|
test('Chatbot floating button has aria-label', async ({ page }) => {
|
|
const chatButton = page.locator('button[aria-label="Open chat"]');
|
|
await expect(chatButton).toBeVisible();
|
|
await expect(chatButton).toHaveAttribute('aria-label', 'Open chat');
|
|
});
|
|
|
|
test('Close button has aria-label', async ({ page }) => {
|
|
// Open chat
|
|
const chatButton = page.locator('button[aria-label="Open chat"]');
|
|
await chatButton.click();
|
|
|
|
const closeButton = page.locator('button[aria-label="Close chat"]');
|
|
await expect(closeButton).toBeVisible();
|
|
await expect(closeButton).toHaveAttribute('aria-label', 'Close chat');
|
|
});
|
|
|
|
test('Input field has aria-label', async ({ page }) => {
|
|
// Open chat
|
|
const chatButton = page.locator('button[aria-label="Open chat"]');
|
|
await chatButton.click();
|
|
|
|
const inputField = page.locator('input[aria-label="Chat message input"]');
|
|
await expect(inputField).toBeVisible();
|
|
await expect(inputField).toHaveAttribute('aria-label', 'Chat message input');
|
|
});
|
|
|
|
test('Send button has aria-label', async ({ page }) => {
|
|
// Open chat
|
|
const chatButton = page.locator('button[aria-label="Open chat"]');
|
|
await chatButton.click();
|
|
|
|
const sendButton = page.locator('button[aria-label="Send message"]');
|
|
await expect(sendButton).toBeVisible();
|
|
await expect(sendButton).toHaveAttribute('aria-label', 'Send message');
|
|
});
|
|
|
|
test('Input field receives focus when chat opens', async ({ page }) => {
|
|
// Open chat
|
|
const chatButton = page.locator('button[aria-label="Open chat"]');
|
|
await chatButton.click();
|
|
|
|
// Wait for focus to be set
|
|
await page.waitForTimeout(200);
|
|
|
|
// Verify input has focus
|
|
const inputField = page.locator('input[aria-label="Chat message input"]');
|
|
await expect(inputField).toBeFocused();
|
|
});
|
|
});
|
|
|
|
/**
|
|
* Chatbot Mobile Tests
|
|
*
|
|
* Verify that the chatbot works correctly on mobile devices.
|
|
*/
|
|
test.describe('Chatbot Mobile', () => {
|
|
test.use({ viewport: { width: 375, height: 812 } });
|
|
|
|
test.beforeEach(async ({ page }) => {
|
|
// Mock the chat API
|
|
await page.route('**/api/chat', async (route) => {
|
|
if (route.request().method() === 'GET') {
|
|
await route.fulfill({
|
|
status: 200,
|
|
contentType: 'application/json',
|
|
body: JSON.stringify({ messages: [], sessionId: 'test-session' }),
|
|
});
|
|
}
|
|
});
|
|
|
|
await page.goto('/de', {
|
|
waitUntil: 'networkidle',
|
|
});
|
|
});
|
|
|
|
test('Chatbot floating button is visible on mobile', async ({ page }) => {
|
|
const chatButton = page.locator('button[aria-label="Open chat"]');
|
|
await expect(chatButton).toBeVisible();
|
|
});
|
|
|
|
test('Chatbot opens correctly on mobile', async ({ page }) => {
|
|
// Open chat
|
|
const chatButton = page.locator('button[aria-label="Open chat"]');
|
|
await chatButton.click();
|
|
|
|
// Verify chat window is visible
|
|
const chatWindow = page.locator('.fixed.z-50.bg-zinc-900');
|
|
await expect(chatWindow).toBeVisible();
|
|
|
|
// Verify chat is usable
|
|
const inputField = page.locator('input[aria-label="Chat message input"]');
|
|
await expect(inputField).toBeVisible();
|
|
});
|
|
|
|
test('Chat window does not overflow on mobile', async ({ page }) => {
|
|
// Open chat
|
|
const chatButton = page.locator('button[aria-label="Open chat"]');
|
|
await chatButton.click();
|
|
|
|
// Get chat window dimensions
|
|
const chatWindow = page.locator('.fixed.z-50.bg-zinc-900');
|
|
const box = await chatWindow.boundingBox();
|
|
|
|
expect(box).not.toBeNull();
|
|
if (box) {
|
|
// Chat window should fit within viewport
|
|
expect(box.x).toBeGreaterThanOrEqual(0);
|
|
expect(box.y).toBeGreaterThanOrEqual(0);
|
|
expect(box.x + box.width).toBeLessThanOrEqual(375 + 1); // Allow 1px tolerance
|
|
}
|
|
});
|
|
});
|
|
|
|
/**
|
|
* Chatbot Chat History Tests
|
|
*
|
|
* Verify that chat history is loaded correctly.
|
|
*/
|
|
test.describe('Chatbot Chat History', () => {
|
|
test('Loads chat history when opening', async ({ page }) => {
|
|
// Mock API with existing history - use regex to match URLs with query strings
|
|
await page.route(/\/api\/chat/, async (route) => {
|
|
if (route.request().method() === 'GET') {
|
|
await route.fulfill({
|
|
status: 200,
|
|
contentType: 'application/json',
|
|
body: JSON.stringify({
|
|
messages: [
|
|
{ id: '1', role: 'user', content: 'Previous question', created_at: new Date().toISOString() },
|
|
{ id: '2', role: 'assistant', content: 'Previous answer', created_at: new Date().toISOString() },
|
|
],
|
|
sessionId: 'existing-session',
|
|
}),
|
|
});
|
|
} else {
|
|
// Let other methods (POST) pass through or mock them too
|
|
await route.continue();
|
|
}
|
|
});
|
|
|
|
await page.goto('/de', {
|
|
waitUntil: 'networkidle',
|
|
});
|
|
|
|
// Open chat
|
|
const chatButton = page.locator('button[aria-label="Open chat"]');
|
|
await chatButton.click();
|
|
|
|
// Wait for chat history to load
|
|
await page.waitForTimeout(1000);
|
|
|
|
const previousQuestion = page.locator('text=Previous question');
|
|
await expect(previousQuestion).toBeVisible({ timeout: 5000 });
|
|
|
|
const previousAnswer = page.locator('text=Previous answer');
|
|
await expect(previousAnswer).toBeVisible({ timeout: 5000 });
|
|
});
|
|
|
|
test('Shows welcome message when no history exists', async ({ page }) => {
|
|
// Mock API with empty history - use regex to match URLs with query strings
|
|
await page.route(/\/api\/chat/, async (route) => {
|
|
if (route.request().method() === 'GET') {
|
|
await route.fulfill({
|
|
status: 200,
|
|
contentType: 'application/json',
|
|
body: JSON.stringify({
|
|
messages: [],
|
|
sessionId: 'new-session',
|
|
}),
|
|
});
|
|
} else {
|
|
await route.continue();
|
|
}
|
|
});
|
|
|
|
await page.goto('/de', {
|
|
waitUntil: 'networkidle',
|
|
});
|
|
|
|
// Open chat
|
|
const chatButton = page.locator('button[aria-label="Open chat"]');
|
|
await chatButton.click();
|
|
|
|
// Wait for chat to load
|
|
await page.waitForTimeout(500);
|
|
|
|
// Verify welcome message is shown
|
|
const welcomeHeading = page.locator("text=Hi, I'm Damjan's AI Assistant");
|
|
await expect(welcomeHeading).toBeVisible({ timeout: 5000 });
|
|
});
|
|
});
|