* feat: persist AI conversations and add chat history Store transcripts and attachment previews in IndexedDB, separate conversation history from transport lifetime, and add document-aware switching with shared Storybook coverage. Preserve interrupted activity and guard stale writes and async switches. * test: group chat history tests by domain * feat: simplify chat history navigation and diagnostics Use a compact header with searchable document-scoped history and a correctly anchored conversation menu. Move diagnostic copying into the menu with copy-result feedback, and separate Storybook fixtures from composition. * fix: address chat history review findings * test: cover harness shutdown and restored chat scrolling * fix: preserve Portless proxy port in MCP routes * docs: clarify UI animation conventions * feat: configure reasoning display and animate disclosure * fix: separate transcript following from reasoning disclosure * fix: restore selected chat after document recovery * refactor: separate chat history persistence and sessions * style: format reasoning story imports
34 lines
1.2 KiB
TypeScript
34 lines
1.2 KiB
TypeScript
import { test, expect } from '#tests/helpers/chat/fixture'
|
|
|
|
test('a long restored conversation scrolls to its latest message on mount', async ({
|
|
configuredChat: chat,
|
|
page
|
|
}) => {
|
|
const text = Array.from({ length: 100 }, (_, index) => `Restored line ${index}`).join('\n')
|
|
await chat.submit(text)
|
|
await expect(chat.assistantMessage()).toBeVisible()
|
|
await page.reload()
|
|
await chat.chatTab.click()
|
|
await page.getByRole('button', { name: 'Conversation history', exact: true }).click()
|
|
await page.getByRole('button', { name: 'All documents', exact: true }).click()
|
|
await page.getByRole('button', { name: /Restored line 0/ }).click()
|
|
await chat.designTab.click()
|
|
await chat.chatTab.click()
|
|
const viewport = page.getByTestId('chat-panel').locator('[data-reka-scroll-area-viewport]')
|
|
await expect
|
|
.poll(() =>
|
|
viewport.evaluate((element) => ({
|
|
overflows: element.scrollHeight > element.clientHeight,
|
|
bottomGap: element.scrollHeight - element.scrollTop - element.clientHeight
|
|
}))
|
|
)
|
|
.toMatchObject({ overflows: true })
|
|
await expect
|
|
.poll(() =>
|
|
viewport.evaluate(
|
|
(element) => element.scrollHeight - element.scrollTop - element.clientHeight
|
|
)
|
|
)
|
|
.toBeLessThan(3)
|
|
})
|