mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-11 13:41:53 +00:00
Status row opens/closes the preview pane; external link uses a dedicated file:// browser bridge (openExternal, not openPath).
138 lines
4.8 KiB
TypeScript
138 lines
4.8 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it } from 'vitest'
|
|
|
|
import { $rightRailActiveTabId, PREVIEW_PANE_ID, RIGHT_RAIL_PREVIEW_TAB_ID } from './layout'
|
|
import { $paneOpen } from './panes'
|
|
import {
|
|
$filePreviewTabs,
|
|
$filePreviewTarget,
|
|
$previewServerRestart,
|
|
$previewServerRestartStatus,
|
|
$previewTarget,
|
|
$sessionPreviewRegistry,
|
|
beginPreviewServerRestart,
|
|
clearSessionPreviewRegistry,
|
|
closeActiveRightRailTab,
|
|
dismissPreviewTarget,
|
|
getSessionPreviewRecord,
|
|
type PreviewTarget,
|
|
progressPreviewServerRestart,
|
|
setCurrentSessionPreviewTarget
|
|
} from './preview'
|
|
import { $activeSessionId, $selectedStoredSessionId } from './session'
|
|
|
|
function previewTarget(source: string): PreviewTarget {
|
|
return {
|
|
kind: 'file',
|
|
label: source,
|
|
path: source,
|
|
previewKind: 'html',
|
|
source,
|
|
url: `file://${source}`
|
|
}
|
|
}
|
|
|
|
function withRenderMode(target: PreviewTarget, renderMode: PreviewTarget['renderMode']): PreviewTarget {
|
|
return { ...target, renderMode }
|
|
}
|
|
|
|
describe('preview store', () => {
|
|
beforeEach(() => {
|
|
$previewServerRestart.set(null)
|
|
$activeSessionId.set('session-1')
|
|
$selectedStoredSessionId.set(null)
|
|
window.localStorage.clear()
|
|
clearSessionPreviewRegistry()
|
|
})
|
|
|
|
afterEach(() => {
|
|
$previewServerRestart.set(null)
|
|
$activeSessionId.set(null)
|
|
$selectedStoredSessionId.set(null)
|
|
window.localStorage.clear()
|
|
clearSessionPreviewRegistry()
|
|
})
|
|
|
|
it('does not notify status subscribers for restart progress text', () => {
|
|
const statuses: string[] = []
|
|
const unsubscribe = $previewServerRestartStatus.subscribe(status => statuses.push(status))
|
|
|
|
beginPreviewServerRestart('task-1', 'http://localhost:5174')
|
|
progressPreviewServerRestart('task-1', 'first line')
|
|
progressPreviewServerRestart('task-1', 'second line')
|
|
unsubscribe()
|
|
|
|
expect(statuses).toEqual(['idle', 'running'])
|
|
})
|
|
|
|
it('persists registered previews and dismissal per session', () => {
|
|
const target = previewTarget('/work/demo.html')
|
|
|
|
setCurrentSessionPreviewTarget(target, 'tool-result')
|
|
|
|
expect($previewTarget.get()).toEqual(withRenderMode(target, 'preview'))
|
|
expect($paneOpen(PREVIEW_PANE_ID).get()).toBe(true)
|
|
expect(getSessionPreviewRecord('session-1')?.normalized).toEqual(withRenderMode(target, 'preview'))
|
|
expect(window.localStorage.getItem('hermes.desktop.sessionPreviews.v1')).toContain('/work/demo.html')
|
|
|
|
dismissPreviewTarget()
|
|
|
|
expect($previewTarget.get()).toBeNull()
|
|
expect($paneOpen(PREVIEW_PANE_ID).get()).toBe(false)
|
|
expect(getSessionPreviewRecord('session-1')).toBeNull()
|
|
expect($sessionPreviewRegistry.get()['session-1']?.[0]?.dismissedAt).toEqual(expect.any(Number))
|
|
|
|
setCurrentSessionPreviewTarget(target, 'tool-result')
|
|
|
|
expect(getSessionPreviewRecord('session-1')?.dismissedAt).toBeUndefined()
|
|
})
|
|
|
|
it('replaces the session preview instead of keeping a back stack', () => {
|
|
const first = previewTarget('/work/first.html')
|
|
const second = previewTarget('/work/second.html')
|
|
|
|
setCurrentSessionPreviewTarget(first, 'tool-result')
|
|
setCurrentSessionPreviewTarget(second, 'tool-result')
|
|
|
|
expect($sessionPreviewRegistry.get()['session-1']).toHaveLength(1)
|
|
expect(getSessionPreviewRecord('session-1')?.normalized).toEqual(withRenderMode(second, 'preview'))
|
|
|
|
dismissPreviewTarget()
|
|
|
|
expect($previewTarget.get()).toBeNull()
|
|
expect(getSessionPreviewRecord('session-1')).toBeNull()
|
|
expect($sessionPreviewRegistry.get()['session-1']?.map(record => record.normalized.url)).toEqual([
|
|
'file:///work/second.html'
|
|
])
|
|
})
|
|
|
|
it('keeps file inspection separate from live preview', () => {
|
|
const target = previewTarget('/work/demo.html')
|
|
const preview = previewTarget('/work/live.html')
|
|
|
|
setCurrentSessionPreviewTarget(preview, 'tool-result')
|
|
|
|
setCurrentSessionPreviewTarget(target, 'manual')
|
|
|
|
expect($filePreviewTarget.get()).toEqual(withRenderMode(target, 'source'))
|
|
expect($previewTarget.get()).toEqual(withRenderMode(preview, 'preview'))
|
|
expect(getSessionPreviewRecord('session-1')?.normalized).toEqual(withRenderMode(preview, 'preview'))
|
|
|
|
closeActiveRightRailTab()
|
|
|
|
expect($filePreviewTarget.get()).toBeNull()
|
|
expect($previewTarget.get()).toEqual(withRenderMode(preview, 'preview'))
|
|
})
|
|
|
|
it('keeps file tabs when a live preview opens', () => {
|
|
const file = previewTarget('/work/file.html')
|
|
const live = previewTarget('/work/live.html')
|
|
|
|
setCurrentSessionPreviewTarget(file, 'manual')
|
|
setCurrentSessionPreviewTarget(live, 'tool-result')
|
|
|
|
expect($filePreviewTabs.get().map(tab => tab.target)).toEqual([withRenderMode(file, 'source')])
|
|
expect($filePreviewTarget.get()).toBeNull()
|
|
expect($rightRailActiveTabId.get()).toBe(RIGHT_RAIL_PREVIEW_TAB_ID)
|
|
expect($previewTarget.get()).toEqual(withRenderMode(live, 'preview'))
|
|
})
|
|
})
|