openpencil/tests/e2e/chat/restore.spec.ts
Danila Poyarkov b4e479d9d0
feat: persist AI conversations and add chat history (#661)
* 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
2026-09-08 11:19:07 +03:00

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)
})