|
1 | 1 | import { expect } from '@playwright/test'
|
2 |
| -import { acceptDisclaimer, closeSendPreference, sendChatMessage } from './utils/test-helpers' |
3 |
| -import { teacherTest as test } from './fixtures' |
| 2 | +import { acceptDisclaimer, closeSendPreference, sendChatMessage, useMockModel } from './utils/test-helpers' |
| 3 | +import { TestByRole } from './fixtures' |
4 | 4 |
|
5 |
| -test.describe('Chat v2 Conversation tests', () => { |
6 |
| - test.beforeEach(async ({ page }) => { |
7 |
| - await page.goto('/v2') |
8 |
| - await acceptDisclaimer(page) |
9 |
| - }) |
| 5 | +// Matrix of tests |
| 6 | +const testMatrix: { role: keyof typeof TestByRole; courses: (string | undefined)[] }[] = [ |
| 7 | + { role: 'student', courses: ['test-course'] }, |
| 8 | + { role: 'teacher', courses: ['test-course', undefined] }, |
| 9 | + { role: 'admin', courses: ['test-course', undefined] }, |
| 10 | +] |
10 | 11 |
|
11 |
| - test('Chat v2 mock response works', async ({ page }) => { |
12 |
| - await page.getByTestId('model-selector').first().click() |
13 |
| - await page.getByRole('option', { name: 'mock' }).click() |
| 12 | +testMatrix.forEach((testConfig) => { |
| 13 | + const test = TestByRole[testConfig.role] |
14 | 14 |
|
15 |
| - await sendChatMessage(page, 'testinen morjens') |
| 15 | + testConfig.courses.forEach((course) => { |
| 16 | + test.describe(`${course ? `Course` : 'General'} chat test for ${testConfig.role}`, () => { |
| 17 | + test.beforeEach(async ({ page }) => { |
| 18 | + await page.goto(`/v2/${course || ''}`) |
| 19 | + }) |
16 | 20 |
|
17 |
| - await closeSendPreference(page) |
| 21 | + test('Disclaimer is visible', async ({ page }) => { |
| 22 | + await expect(page.getByTestId('submit-accept-disclaimer')).toBeVisible() |
| 23 | + }) |
18 | 24 |
|
19 |
| - await expect(page.getByTestId('user-message')).toContainText('testinen morjens') |
20 |
| - await expect(page.getByTestId('assistant-message')).toContainText('You are calling mock endpoint for streaming mock data') |
21 |
| - }) |
| 25 | + test('Disclaimer is not visible after accepting and reloading', async ({ page }) => { |
| 26 | + await acceptDisclaimer(page) |
| 27 | + await page.reload() |
| 28 | + await expect(page.getByTestId('submit-accept-disclaimer')).not.toBeVisible() |
| 29 | + }) |
| 30 | + |
| 31 | + test('Disclaimer (help) can be opened manually', async ({ page }) => { |
| 32 | + await acceptDisclaimer(page) |
| 33 | + await page.getByTestId('help-button').click() |
| 34 | + await expect(page.getByTestId('submit-accept-disclaimer')).toBeVisible() |
| 35 | + }) |
| 36 | + |
| 37 | + test('Settings can be opened and closed', async ({ page }) => { |
| 38 | + await acceptDisclaimer(page) |
| 39 | + await page.getByTestId('settings-button').click() |
| 40 | + await expect(page.locator('#close-settings')).toBeVisible() |
| 41 | + |
| 42 | + await page.keyboard.press('Escape') |
| 43 | + await expect(page.locator('#close-settings')).not.toBeVisible() |
| 44 | + }) |
| 45 | + |
| 46 | + test('Can select model', async ({ page }) => { |
| 47 | + await acceptDisclaimer(page) |
| 48 | + await useMockModel(page) |
| 49 | + }) |
| 50 | + |
| 51 | + test('Chat v2 mock response works', async ({ page }) => { |
| 52 | + await acceptDisclaimer(page) |
| 53 | + await useMockModel(page) |
| 54 | + |
| 55 | + await sendChatMessage(page, 'testinen morjens') |
| 56 | + |
| 57 | + await closeSendPreference(page) |
| 58 | + |
| 59 | + await expect(page.getByTestId('user-message')).toContainText('testinen morjens') |
| 60 | + await expect(page.getByTestId('assistant-message')).toContainText('You are calling mock endpoint for streaming mock data') |
| 61 | + }) |
| 62 | + |
| 63 | + test('Can empty conversation', async ({ page }) => { |
| 64 | + await acceptDisclaimer(page) |
| 65 | + await useMockModel(page) |
| 66 | + |
| 67 | + await sendChatMessage(page, 'tää tyhjennetään') |
| 68 | + |
| 69 | + await closeSendPreference(page) |
| 70 | + |
| 71 | + await expect(page.getByTestId('user-message')).toContainText('tää tyhjennetään') |
| 72 | + await expect(page.getByTestId('assistant-message')).toContainText('OVER', { timeout: 6000 }) |
| 73 | + |
| 74 | + page.on('dialog', (dialog) => dialog.accept()) |
| 75 | + await page.getByTestId('empty-conversation-button').click() |
| 76 | + |
| 77 | + await expect(page.getByTestId('user-message')).not.toBeVisible() |
| 78 | + await expect(page.getByTestId('assistant-message')).not.toBeVisible() |
| 79 | + }) |
| 80 | + |
| 81 | + test('Custom system prompt can be changed', async ({ page }) => { |
| 82 | + await acceptDisclaimer(page) |
| 83 | + await useMockModel(page) |
| 84 | + await page.getByTestId('settings-button').click() |
| 85 | + |
| 86 | + const systemPrompt = 'mocktest this is the system prompt' |
| 87 | + await page.getByTestId('assistant-instructions-input').fill(systemPrompt) |
| 88 | + await page.getByTestId('settings-ok-button').click() |
| 89 | + |
| 90 | + await sendChatMessage(page, 'I can send anything now, the model just echoes the system prompt since it begins with mocktest.') |
| 91 | + await closeSendPreference(page) |
| 92 | + |
| 93 | + await expect(page.getByTestId('assistant-message')).toContainText(systemPrompt) |
| 94 | + }) |
| 95 | + |
| 96 | + test('Default temperature is 0.5 and can adjust temperature', async ({ page }) => { |
| 97 | + await acceptDisclaimer(page) |
| 98 | + await useMockModel(page) |
| 99 | + |
| 100 | + await sendChatMessage(page, 'temperature') |
| 101 | + await closeSendPreference(page) |
| 102 | + await expect(page.getByTestId('assistant-message').first()).toContainText('Temperature: 0.5') |
| 103 | + |
| 104 | + await page.getByTestId('settings-button').click() |
| 105 | + |
| 106 | + const slider = page.getByRole('slider').first() |
| 107 | + // Move right 6 times |
| 108 | + for (let i = 0; i < 6; i++) { |
| 109 | + await slider.press('ArrowRight') |
| 110 | + } |
| 111 | + |
| 112 | + // Close settings |
| 113 | + await page.getByTestId('settings-ok-button').click() |
| 114 | + |
| 115 | + await sendChatMessage(page, 'temperature') |
| 116 | + await expect(page.getByTestId('assistant-message').last()).toContainText('Temperature: 1') |
| 117 | + }) |
| 118 | + |
| 119 | + if (course) |
| 120 | + test('Course chat RAG feature', async ({ page }) => { |
| 121 | + await acceptDisclaimer(page) |
| 122 | + await useMockModel(page) |
| 123 | + |
| 124 | + const ragName = `rag-${test.info().workerIndex}-${testConfig.role}` |
| 125 | + await page.locator('#rag-index-selector').first().click() |
| 126 | + await page.getByRole('menuitem', { name: ragName, exact: true }).click() |
22 | 127 |
|
23 |
| - test('Can empty conversation', async ({ page }) => { |
24 |
| - await page.getByTestId('model-selector').first().click() |
25 |
| - await page.getByRole('option', { name: 'mock' }).click() |
| 128 | + await sendChatMessage(page, 'rag') |
| 129 | + await closeSendPreference(page) |
26 | 130 |
|
27 |
| - await sendChatMessage(page, 'tää tyhjennetään') |
| 131 | + // Shows file search loading indicator |
| 132 | + await expect(page.getByTestId('tool-call-message')).toBeVisible() |
28 | 133 |
|
29 |
| - await closeSendPreference(page) |
| 134 | + // Responds with RAG mock document text |
| 135 | + await expect(page.getByTestId('assistant-message')).toContainText('This is the first mock document') |
30 | 136 |
|
31 |
| - await expect(page.getByTestId('user-message')).toContainText('tää tyhjennetään') |
32 |
| - await expect(page.getByTestId('assistant-message')).toContainText('OVER', { timeout: 6000 }) |
| 137 | + // Source button is visible |
| 138 | + await expect(page.getByTestId('file-search-sources')).toBeVisible() |
33 | 139 |
|
34 |
| - page.on('dialog', (dialog) => dialog.accept()) |
35 |
| - await page.getByTestId('empty-conversation-button').click() |
| 140 | + // Sources drawer has been opened and title is visible |
| 141 | + await expect(page.getByTestId('sources-header')).toBeVisible() |
36 | 142 |
|
37 |
| - await expect(page.getByTestId('user-message')).not.toBeVisible() |
38 |
| - await expect(page.getByTestId('assistant-message')).not.toBeVisible() |
| 143 | + // Three source items should be visible |
| 144 | + await expect(page.getByTestId('sources-truncated-item')).toHaveCount(3) |
| 145 | + }) |
| 146 | + }) |
39 | 147 | })
|
40 | 148 | })
|
0 commit comments