test(client): cover independent trajectory history

This commit is contained in:
imccyu
2026-07-29 20:46:02 +08:00
parent e0022ff19e
commit 64acc5874b
6 changed files with 51 additions and 28 deletions

View File

@@ -4,7 +4,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import type { ConvViewProps } from '@deepseek-ai/dsh-client-ui-conversation/client'
import type { InjectFace } from '@deepseek-ai/dsh-client-ui-slots'
import type {
AssistantMessageNode, ConversationContext, RequestView,
AssistantMessageNode, ConversationContext,
SessionHistoryFace,
} from '@deepseek-ai/dsh-client-runtime/client'
import {
@@ -26,7 +26,6 @@ import {
import css from './views.module.css'
const EMPTY_IDS: ReadonlySet<number> = new Set()
const EMPTY_REQUESTS: readonly RequestView[] = []
/** Session-history paging needed by the event-complete trajectory view. */
export interface TrajectoryViewInjected {
@@ -161,7 +160,7 @@ export function TrajectoryView({
void loadAllHistoryRef.current(controller.signal)
return () => { controller.abort() }
}, [])
const requests = inspection.requests ?? EMPTY_REQUESTS
const requests = inspection.requests
const callSchemas = inspection.callSchemas
const contexts = useMemo<readonly ConversationContext[]>(
() => inspection.contexts.length === 0
@@ -324,7 +323,7 @@ export function TrajectoryView({
partial,
runningCalls,
requests: selectedRequests,
...(callSchemas === undefined ? {} : { callSchemas }),
callSchemas,
codeDispatches,
}),
[

View File

@@ -124,15 +124,15 @@ function standaloneProps(nodes: ConversationSnapshot['nodes']): ConvViewProps {
}
/** Real-stack bench: root Context + real SlotsService ring + the plugin fiber. */
async function bench() {
async function bench(snapshot = historySnapshot(NODES)) {
const ctx = new Context()
const slots = new SlotsService(ctx)
const loadAllHistory = vi.fn((_signal: AbortSignal) => Promise.resolve())
const historyStore = createSnapshotStore(historySnapshot(NODES))
const historyStore = createSnapshotStore(snapshot)
const history: SessionHistoryFace = {
sessionId: SID,
getSnapshot: historyStore.getSnapshot,
subscribe: historyStore.subscribe,
getSnapshot: () => historyStore.getSnapshot(),
subscribe: listener => historyStore.subscribe(listener),
loadAll: loadAllHistory,
}
// The conversation entry's role: declare the ring, then seed the chat entry.
@@ -181,11 +181,11 @@ function mount(slots: SlotsService, nodes: ConversationSnapshot['nodes'] = NODES
: injectEntry(SID)
const injectedProps = 'hooks' in injected
? {
loadAllHistory: (injected as TrajectoryViewInjected).loadAllHistory,
useHistory: bindSnapshotSelector(
(injected as TrajectoryViewInjected).hooks.history,
),
}
loadAllHistory: (injected as TrajectoryViewInjected).loadAllHistory,
useHistory: bindSnapshotSelector(
(injected as TrajectoryViewInjected).hooks.history,
),
}
: injected
return (
<View
@@ -310,8 +310,8 @@ describe('tab switching in ConversationRoot', () => {
})
it('empty window keeps the toolbar and reports no timing data', async () => {
const b = await bench()
mount(b.slots, [])
const b = await bench(historySnapshot([]))
mount(b.slots)
fireEvent.click(screen.getByRole('tab', { name: 'Trajectory' }))
expect(screen.getByRole('toolbar', { name: 'Trajectory toolbar' })).toBeTruthy()
expect(screen.getByText('No timing data')).toBeTruthy()