Files
2026-07-13 13:12:33 +08:00

58 lines
2.6 KiB
TypeScript

import { test, expect } from '@playwright/test'
const CONTROL_URL = '/control/'
const LIVE = process.env.OPENSQUILLA_E2E_LIVE === '1'
test.describe('Code block syntax highlighting', () => {
test('idle chat renders no highlighted code blocks', async ({ page }) => {
await page.goto(CONTROL_URL + 'chat/new')
await page.waitForSelector('.conn-pill', { timeout: 10000 })
await expect(page.locator('code.hljs')).toHaveCount(0)
await expect(page.locator('.code-lang')).toHaveCount(0)
})
test('live python snippet renders distinct token colors and a language label', async ({ page }) => {
test.skip(!LIVE, 'Live gateway test; set OPENSQUILLA_E2E_LIVE=1 to run.')
test.setTimeout(240000)
await page.goto(CONTROL_URL + 'chat/new')
await page.waitForSelector('.conn-pill', { timeout: 10000 })
await page.locator('.chat-textarea').fill(
'Reply with exactly one fenced python code block (```python) defining def greet(name): return f"hello {name}" — keep the def keyword and the string literal. No prose outside the block.',
)
await page.locator('.chat-send-btn[aria-label="Send"]').click()
const block = page.locator('.msg-ai .msg-ai-text pre code.hljs').first()
await expect(block).toBeVisible({ timeout: 180000 })
await expect(page.locator('.stream-activity')).toHaveCount(0, { timeout: 180000 })
// Highlighter token spans survive sanitization.
const keyword = block.locator('.hljs-keyword').first()
const literal = block.locator('.hljs-string').first()
await expect(keyword).toBeVisible()
await expect(literal).toBeVisible()
// Two token kinds resolve to different computed colors, and both differ
// from the block's base text color — the --syntax-* tokens applied.
const keywordColor = await keyword.evaluate(node => getComputedStyle(node).color)
const stringColor = await literal.evaluate(node => getComputedStyle(node).color)
const baseColor = await block.evaluate(node => getComputedStyle(node).color)
expect(keywordColor).not.toBe(stringColor)
expect(keywordColor).not.toBe(baseColor)
expect(stringColor).not.toBe(baseColor)
// The language label chip renders on the block.
const label = page.locator('.msg-ai .msg-ai-text pre .code-lang').first()
await expect(label).toBeVisible()
await expect(label).toHaveText(/python/i)
// Highlighting survives a reload: history replays through the same renderer.
await page.reload()
await page.waitForSelector('.conn-pill', { timeout: 10000 })
const replayed = page.locator('.msg-ai .msg-ai-text pre code.hljs .hljs-keyword').first()
await expect(replayed).toBeVisible({ timeout: 30000 })
})
})