feat: prepare Zhinian desktop pilot
This commit is contained in:
@@ -2,6 +2,20 @@ import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
const hostApiFetchMock = vi.fn();
|
||||
const subscribeHostEventMock = vi.fn();
|
||||
const chatStateMock = vi.hoisted(() => ({
|
||||
state: {
|
||||
currentSessionKey: 'session-1',
|
||||
sessions: [] as Array<{ key: string }>,
|
||||
sending: true,
|
||||
activeRunId: 'run-1' as string | null,
|
||||
pendingFinal: true,
|
||||
lastUserMessageAt: 123,
|
||||
error: null as string | null,
|
||||
loadHistory: vi.fn(),
|
||||
loadSessions: vi.fn(),
|
||||
handleChatEvent: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock('@/lib/host-api', () => ({
|
||||
hostApiFetch: (...args: unknown[]) => hostApiFetchMock(...args),
|
||||
@@ -11,10 +25,28 @@ vi.mock('@/lib/host-events', () => ({
|
||||
subscribeHostEvent: (...args: unknown[]) => subscribeHostEventMock(...args),
|
||||
}));
|
||||
|
||||
vi.mock('@/stores/chat', () => ({
|
||||
useChatStore: {
|
||||
getState: () => chatStateMock.state,
|
||||
setState: (patch: Record<string, unknown>) => {
|
||||
Object.assign(chatStateMock.state, patch);
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
describe('gateway store event wiring', () => {
|
||||
beforeEach(() => {
|
||||
vi.resetModules();
|
||||
vi.clearAllMocks();
|
||||
Object.assign(chatStateMock.state, {
|
||||
currentSessionKey: 'session-1',
|
||||
sessions: [],
|
||||
sending: true,
|
||||
activeRunId: 'run-1',
|
||||
pendingFinal: true,
|
||||
lastUserMessageAt: 123,
|
||||
error: null,
|
||||
});
|
||||
});
|
||||
|
||||
it('subscribes to host events through subscribeHostEvent on init', async () => {
|
||||
@@ -76,4 +108,61 @@ describe('gateway store event wiring', () => {
|
||||
expect(status.gatewayReady).toBeUndefined();
|
||||
expect(status.state === 'running' && status.gatewayReady !== false).toBe(true);
|
||||
});
|
||||
|
||||
it('does not clear sending state on intermediate agent phase=end notifications', async () => {
|
||||
hostApiFetchMock.mockResolvedValueOnce({ state: 'running', port: 18789 });
|
||||
|
||||
const handlers = new Map<string, (payload: unknown) => void>();
|
||||
subscribeHostEventMock.mockImplementation((eventName: string, handler: (payload: unknown) => void) => {
|
||||
handlers.set(eventName, handler);
|
||||
return () => {};
|
||||
});
|
||||
|
||||
const { useGatewayStore } = await import('@/stores/gateway');
|
||||
await useGatewayStore.getState().init();
|
||||
|
||||
handlers.get('gateway:notification')?.({
|
||||
method: 'agent',
|
||||
params: {
|
||||
phase: 'end',
|
||||
runId: 'run-1',
|
||||
sessionKey: 'session-1',
|
||||
},
|
||||
});
|
||||
|
||||
await vi.waitFor(() => {
|
||||
expect(chatStateMock.state.loadHistory).toHaveBeenCalled();
|
||||
});
|
||||
expect(chatStateMock.state.sending).toBe(true);
|
||||
expect(chatStateMock.state.activeRunId).toBe('run-1');
|
||||
expect(chatStateMock.state.pendingFinal).toBe(true);
|
||||
});
|
||||
|
||||
it('clears sending state on terminal agent completion notifications', async () => {
|
||||
hostApiFetchMock.mockResolvedValueOnce({ state: 'running', port: 18789 });
|
||||
|
||||
const handlers = new Map<string, (payload: unknown) => void>();
|
||||
subscribeHostEventMock.mockImplementation((eventName: string, handler: (payload: unknown) => void) => {
|
||||
handlers.set(eventName, handler);
|
||||
return () => {};
|
||||
});
|
||||
|
||||
const { useGatewayStore } = await import('@/stores/gateway');
|
||||
await useGatewayStore.getState().init();
|
||||
|
||||
handlers.get('gateway:notification')?.({
|
||||
method: 'agent',
|
||||
params: {
|
||||
phase: 'completed',
|
||||
runId: 'run-1',
|
||||
sessionKey: 'session-1',
|
||||
},
|
||||
});
|
||||
|
||||
await vi.waitFor(() => {
|
||||
expect(chatStateMock.state.sending).toBe(false);
|
||||
});
|
||||
expect(chatStateMock.state.activeRunId).toBeNull();
|
||||
expect(chatStateMock.state.pendingFinal).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user