feat(sidebar): agent 终端等待 banner(needle + 跳过等待按钮)
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* TerminalWaitBanner unit tests: localized text with the needle, the skip
|
||||
* button wiring, and the long-needle display cap (full text stays on the
|
||||
* title attribute). The component imports no xterm — renderable in plain
|
||||
* jsdom (the repo's jsdom pattern, see bottom-auto-terminal.spec.tsx head).
|
||||
*/
|
||||
// @vitest-environment jsdom
|
||||
import { afterEach, describe, expect, it } from 'vitest'
|
||||
import { createElement } from 'react'
|
||||
import { createRoot, type Root } from 'react-dom/client'
|
||||
import { act } from 'react-dom/test-utils'
|
||||
import { setupReactAct } from './test-utils.ts'
|
||||
setupReactAct()
|
||||
|
||||
import { TerminalWaitBanner } from '../src/client/TerminalWaitBanner.tsx'
|
||||
|
||||
describe('TerminalWaitBanner', () => {
|
||||
const mounted: Array<{ root: Root; container: HTMLDivElement }> = []
|
||||
function mount(needle: string, onSkip: () => void): HTMLDivElement {
|
||||
const container = document.createElement('div')
|
||||
document.body.append(container)
|
||||
const root = createRoot(container)
|
||||
act(() => { root.render(createElement(TerminalWaitBanner, { needle, onSkip })) })
|
||||
mounted.push({ root, container })
|
||||
return container
|
||||
}
|
||||
afterEach(() => {
|
||||
for (const { root, container } of mounted.splice(0)) {
|
||||
act(() => { root.unmount() })
|
||||
container.remove()
|
||||
}
|
||||
})
|
||||
|
||||
it('shows the localized waiting text with the needle and a working skip button', () => {
|
||||
let skipped = 0
|
||||
const container = mount('BUILD_OK', () => { skipped += 1 })
|
||||
// jsdom navigator.language is en-US → the en dictionary applies.
|
||||
expect(container.textContent).toContain('Agent is waiting for')
|
||||
expect(container.textContent).toContain('BUILD_OK')
|
||||
expect(container.textContent).toContain('Skip wait')
|
||||
const button = container.querySelector('button')
|
||||
expect(button).not.toBeNull()
|
||||
act(() => { button!.dispatchEvent(new MouseEvent('click', { bubbles: true })) })
|
||||
expect(skipped).toBe(1)
|
||||
})
|
||||
|
||||
it('truncates a long needle for display but keeps the full text on the title', () => {
|
||||
const long = 'X'.repeat(200)
|
||||
const container = mount(long, () => {})
|
||||
const span = container.querySelector('span[title]')
|
||||
expect(span).not.toBeNull()
|
||||
expect(span!.getAttribute('title')).toBe(long)
|
||||
// The needle's inline contribution is capped (NEEDLE_DISPLAY_CAP): at
|
||||
// most 80 X's are rendered — the full 200-char run only rides the title
|
||||
// tooltip. The localized sentence around the needle is not measured;
|
||||
// its length varies per language, so counting the needle's own chars is
|
||||
// the language-agnostic form of the display-cap assertion.
|
||||
expect((span!.textContent?.match(/X/g) ?? []).length).toBeLessThanOrEqual(80)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user