import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { createPinia, setActivePinia } from 'pinia' import { fetchOpenClawAgents, fetchOpenClawCapabilities, openClawOverviewQueryOptions, projectOpenClawAgentNodes, type OpenClawOverviewDto, } from '../src/api/openclawRuntime' import { queryClient } from '../src/api/queryClient' import { useAuthStore } from '../src/stores/auth' import type { OpenClawAgent, OpenClawCapability, OpenClawCollection, } from '../src/types/openclaw' const now = '2026-07-31T10:00:00.000Z' function collection(items: T[]): OpenClawCollection { return { state: 'ready', items, nextCursor: null, message: null, recovery: null, checkedAt: now, } } function overviewFixture(): OpenClawOverviewDto { return { connection: { state: 'connected', configured: true, credentialConfigured: true, connected: true, endpoint: 'ws://openclaw-gateway:18789', gatewayVersion: '2026.7.1', requiredVersion: '2026.7.1', versionPinned: true, versionMatches: true, protocolVersion: 4, grantedScopes: ['operator.read'], advertisedEvents: ['agent', 'task'], lastConnectedAt: now, lastEventAt: now, reconnectAttempts: 0, message: 'Connected', recovery: null, checkedAt: now, deviceId: 'nexus-test', pairingRequired: false, pairingRequestId: null, }, capabilities: [], tasks: collection([{ id: 'task-1', title: 'Prepare release', status: 'running', kind: 'agent', runtime: 'openclaw', agentId: 'iris', sessionKey: 'agent:iris:main', runId: 'run-1', flowId: null, parentTaskId: null, createdAt: now, startedAt: now, updatedAt: now, finishedAt: null, progress: 42, summary: 'Checks the release gates.', error: null, canCancel: true, }]), sessions: collection([{ key: 'agent:iris:main', sessionId: 'session-1', agentId: 'iris', title: 'Release session', status: 'running', kind: 'agent', channel: null, model: 'openai/gpt-5.4', provider: 'openai', runId: 'run-1', updatedAt: now, inputTokens: 800, outputTokens: 400, totalTokens: 1_200, canAbort: true, }]), cronJobs: collection([]), approvals: collection([]), activity: collection([]), models: collection([{ id: 'openai/gpt-5.4', name: 'GPT-5.4', provider: 'openai', configured: true, available: true, contextWindow: 1_000_000, reason: null, }]), agents: collection([{ id: 'iris', name: 'Iris', description: 'Coordinates the team.', model: null, provider: 'openai', workspace: '/managed/agents/iris', status: 'ready', }]), generatedAt: now, } } function authenticate(): void { const auth = useAuthStore() auth.initialized = true auth.applySession({ accessToken: 'runtime-access-token', expiresAt: '2026-07-31T12:00:00.000Z', user: { id: 'bao', email: 'bao@nexus.local', displayName: 'Bao', role: 'owner', }, }) } function pathOf(input: RequestInfo | URL): string { const raw = input instanceof Request ? input.url : String(input) return new URL(raw, 'http://localhost').pathname } beforeEach(() => { setActivePinia(createPinia()) authenticate() queryClient.clear() }) afterEach(() => { queryClient.clear() vi.unstubAllGlobals() }) describe('shared OpenClaw runtime queries', () => { it('deduplicates simultaneous overview consumers at the authenticated boundary', async () => { const fetchMock = vi.fn(async () => new Response(JSON.stringify(overviewFixture()), { status: 200, headers: { 'Content-Type': 'application/json' }, })) vi.stubGlobal('fetch', fetchMock) const options = openClawOverviewQueryOptions() const results = await Promise.all([ queryClient.fetchQuery(options), queryClient.fetchQuery(options), queryClient.fetchQuery(options), ]) expect(results.every(result => result.connection.connected)).toBe(true) expect(fetchMock).toHaveBeenCalledTimes(1) const [input, init] = fetchMock.mock.calls[0]! expect(pathOf(input)).toBe('/api/v1/openclaw/overview') expect(new Headers(init?.headers).get('Authorization')).toBe('Bearer runtime-access-token') }) it('uses the dedicated capability and agent contracts', async () => { const capabilities: OpenClawCapability[] = [{ id: 'agents-list', label: 'List agents', method: 'agents.list', requiredScope: 'operator.read', available: true, state: 'ready', reason: null, }] const agents: OpenClawCollection = collection([ overviewFixture().agents.items[0]!, ]) const fetchMock = vi.fn(async (input: RequestInfo | URL) => { const path = pathOf(input) return new Response(JSON.stringify( path.endsWith('/capabilities') ? capabilities : agents, ), { status: 200, headers: { 'Content-Type': 'application/json' }, }) }) vi.stubGlobal('fetch', fetchMock) await expect(fetchOpenClawCapabilities()).resolves.toEqual(capabilities) await expect(fetchOpenClawAgents()).resolves.toEqual(agents) expect(fetchMock.mock.calls.map(call => pathOf(call[0]))).toEqual([ '/api/v1/openclaw/capabilities', '/api/v1/openclaw/agents', ]) }) it('projects task, session, model and token state without a dashboard facade', () => { expect(projectOpenClawAgentNodes(overviewFixture())).toEqual([ expect.objectContaining({ id: 'iris', status: 'work', statusLabel: 'Arbeitet', task: 'Prepare release', progress: 42, model: 'openai/gpt-5.4', tokens: '1.2k', }), ]) }) })