63 lines
2.7 KiB
TypeScript
63 lines
2.7 KiB
TypeScript
import { test, expect } from '@playwright/test'
|
|
|
|
const CONTROL_URL = '/control/'
|
|
const LIVE = process.env.OPENSQUILLA_E2E_LIVE === '1'
|
|
|
|
test.describe('Assistant receipt meta', () => {
|
|
test('draft chat renders no receipt meta or usage popover', async ({ page }) => {
|
|
await page.goto(CONTROL_URL + 'chat/new')
|
|
await page.waitForSelector('.conn-pill', { timeout: 10000 })
|
|
|
|
await expect(page.locator('.msg-ai-meta')).toHaveCount(0)
|
|
await expect(page.locator('.msg-meta-popover')).toHaveCount(0)
|
|
})
|
|
|
|
test('live run keeps cost and savings inline and tucks token details into the popover', 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 the single word ok.')
|
|
await page.locator('.chat-send-btn[aria-label="Send"]').click()
|
|
|
|
const meta = page.locator('.msg-ai .msg-ai-meta').last()
|
|
await expect(meta).toBeVisible({ timeout: 180000 })
|
|
|
|
// Cost and savings stay inline on the meta line — no interaction needed.
|
|
await expect(meta.locator('.msg-meta__cost')).toContainText('$', { timeout: 60000 })
|
|
await expect(meta.locator('.savings-indicator')).toBeVisible()
|
|
await expect(meta.locator('.savings-indicator')).toContainText(/Saved ~\d+%/)
|
|
|
|
// Token/cache/think details are no longer inline on the meta line.
|
|
await expect(meta).not.toContainText('cache:')
|
|
await expect(meta).not.toContainText('think:')
|
|
await expect(meta).not.toContainText('↑')
|
|
|
|
// The usage popover opens from a focusable trigger and lists token details.
|
|
const trigger = meta.getByRole('button', { name: 'Usage details' })
|
|
await expect(trigger).toBeVisible()
|
|
await trigger.click()
|
|
const popover = meta.locator('.msg-meta-popover')
|
|
await expect(popover).toBeVisible()
|
|
await expect(popover.locator('.msg-meta-popover__label').first()).toHaveText('tokens')
|
|
await expect(popover).toContainText('↑')
|
|
const labels = await popover.locator('.msg-meta-popover__label').allTextContents()
|
|
for (const label of labels) {
|
|
expect(['tokens', 'cache', 'think']).toContain(label)
|
|
}
|
|
|
|
// Escape closes the popover and returns focus to the trigger.
|
|
await page.keyboard.press('Escape')
|
|
await expect(popover).toHaveCount(0)
|
|
await expect(trigger).toBeFocused()
|
|
|
|
// At 390px the receipt stays a single compact row.
|
|
await page.setViewportSize({ width: 390, height: 844 })
|
|
const box = await meta.boundingBox()
|
|
expect(box).not.toBeNull()
|
|
expect(box!.height).toBeLessThanOrEqual(30)
|
|
})
|
|
})
|