openpencil/tests/e2e/chat/markdown.spec.ts
Danila Poyarkov b9731f6a90 test(chat): isolate domain specs and real LLM runs
- Replace the shared serial page with isolated configured-chat fixtures\n- Split composer, attachment, Markdown, profile, navigation, and response behavior\n- Use Playwright's structured @real-llm tag with a credential-gated config\n- Keep mock stream construction and page operations in focused helpers
2026-09-04 11:50:12 +03:00

57 lines
2.3 KiB
TypeScript

import { expect, test } from '#tests/helpers/chat/fixture'
test('completed responses release streaming parser history', async ({ configuredChat: chat }) => {
await chat.submit('Show a code block')
const markdown = chat.page.locator('.chat-markdown').last()
await expect(markdown).toHaveAttribute('data-chat-markdown-mode', 'static')
await expect(markdown.locator('.shiki').first()).toBeVisible()
})
test('code blocks follow light and dark themes', async ({ configuredChat: chat }) => {
await chat.submit('Show a code block')
const code = chat.assistantMessage().locator('.shiki').first()
await expect(code).toHaveCSS('background-color', 'rgb(30, 30, 30)')
await expect(code.locator('span').filter({ hasText: 'const' }).first()).not.toHaveCSS(
'color',
'rgb(240, 240, 240)'
)
await chat.page.evaluate(async () => {
const themeModulePath = '/src/app/shell/theme.ts'
const themeModule = await import(themeModulePath)
themeModule.useAppTheme().setTheme('light')
})
await chat.page.waitForFunction(() => document.documentElement.dataset.theme === 'light')
await expect(chat.page.locator('.chat-markdown').last()).toHaveClass(/light/)
await expect(code).toHaveCSS('background-color', 'rgb(255, 255, 255)')
})
test('Markdown blocks unsafe links and cross-origin images', async ({ configuredChat: chat }) => {
const approvedImageURL = new URL('/assets/approved.png', chat.page.url()).href
await chat.page.route(approvedImageURL, async (route) => {
await route.fulfill({
body: Buffer.from(
'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M/wHwAEAQH/69cbGAAAAABJRU5ErkJggg==',
'base64'
),
contentType: 'image/png'
})
})
await chat.submit('Show unsafe Markdown')
const assistant = chat.assistantMessage()
await expect(assistant.locator('a[href^="javascript:"]')).toHaveCount(0)
await expect(assistant.locator('img[src^="data:"]')).toHaveCount(0)
await expect(assistant.getByRole('img', { name: 'approved' })).toHaveAttribute(
'src',
approvedImageURL
)
await expect(assistant.getByRole('img', { name: 'unapproved' })).toHaveCount(0)
await expect(assistant.getByRole('img', { name: 'insecure' })).toHaveCount(0)
await expect(assistant.getByRole('link', { name: 'safe' })).toHaveAttribute(
'href',
'https://openpencil.dev/'
)
})