Files
hermes-desktop/tests/client/group-chat-store-workspace.test.ts
toor 01d9e301fc
Build / build (push) Canceled after 0s
Playwright / browser (push) Canceled after 0s
initialize Electron desktop app and remove unused files
2026-10-25 01:09:01 +08:00

95 lines
3.6 KiB
TypeScript

// @vitest-environment jsdom
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { createPinia, setActivePinia } from 'pinia'
const groupChatApiMock = vi.hoisted(() => ({
connectGroupChat: vi.fn(),
disconnectGroupChat: vi.fn(),
getSocket: vi.fn(() => null),
getStoredUserId: vi.fn(() => 'user-1'),
getStoredUserName: vi.fn(() => 'tester'),
createRoom: vi.fn(),
listRooms: vi.fn(),
getRoomDetail: vi.fn(),
joinRoomByCode: vi.fn(),
addAgent: vi.fn(),
listAgents: vi.fn(),
removeAgent: vi.fn(),
cloneRoom: vi.fn(),
deleteRoom: vi.fn(),
clearRoomContext: vi.fn(),
updateRoomWorkspace: vi.fn(),
}))
vi.mock('@/api/hermes/group-chat', () => groupChatApiMock)
vi.mock('@/api/client', () => ({
getApiKey: vi.fn(() => 'token'),
getActiveProfileName: vi.fn(() => 'default'),
getStoredUsername: vi.fn(() => null),
}))
vi.mock('@/api/auth', () => ({ fetchCurrentUser: vi.fn(async () => { throw new Error('no user') }) }))
vi.mock('@/api/hermes/download', () => ({ getDownloadUrl: vi.fn((path: string) => `/download?path=${path}`) }))
describe('group chat store workspace', () => {
beforeEach(() => {
setActivePinia(createPinia())
vi.clearAllMocks()
})
it('passes selected workspace when creating a room', async () => {
const { useGroupChatStore } = await import('@/stores/hermes/group-chat')
const store = useGroupChatStore()
groupChatApiMock.createRoom.mockResolvedValue({
room: { id: 'room-1', name: 'Room 1', inviteCode: null, workspace: '/tmp/repo' },
agents: [],
})
await store.createNewRoom('Room 1', 'invite-1', [], { triggerTokens: 100000, maxHistoryTokens: 32000, tailMessageCount: 10 }, '/tmp/repo')
expect(groupChatApiMock.createRoom).toHaveBeenCalledWith(expect.objectContaining({
name: 'Room 1',
inviteCode: 'invite-1',
workspace: '/tmp/repo',
}))
expect(store.rooms[0].workspace).toBe('/tmp/repo')
})
it('updates the rooms list after the workspace API succeeds', async () => {
const { useGroupChatStore } = await import('@/stores/hermes/group-chat')
const store = useGroupChatStore()
store.rooms = [{ id: 'room-1', name: 'Room 1', inviteCode: null, workspace: '' }]
groupChatApiMock.updateRoomWorkspace.mockResolvedValue({
room: { id: 'room-1', name: 'Room 1', inviteCode: null, workspace: '/tmp/repo' },
})
await store.setRoomWorkspace('room-1', '/tmp/repo')
expect(groupChatApiMock.updateRoomWorkspace).toHaveBeenCalledWith('room-1', '/tmp/repo')
expect(store.rooms[0].workspace).toBe('/tmp/repo')
})
it('clears workspace through the same API path', async () => {
const { useGroupChatStore } = await import('@/stores/hermes/group-chat')
const store = useGroupChatStore()
store.rooms = [{ id: 'room-1', name: 'Room 1', inviteCode: null, workspace: '/tmp/repo' }]
groupChatApiMock.updateRoomWorkspace.mockResolvedValue({
room: { id: 'room-1', name: 'Room 1', inviteCode: null, workspace: '' },
})
await store.setRoomWorkspace('room-1', '')
expect(store.rooms[0].workspace).toBe('')
})
it('does not mutate local workspace when the API rejects', async () => {
const { useGroupChatStore } = await import('@/stores/hermes/group-chat')
const store = useGroupChatStore()
store.rooms = [{ id: 'room-1', name: 'Room 1', inviteCode: null, workspace: '/tmp/repo' }]
groupChatApiMock.updateRoomWorkspace.mockRejectedValue(new Error('invalid workspace'))
await expect(store.setRoomWorkspace('room-1', '/outside')).rejects.toThrow('invalid workspace')
expect(store.rooms[0].workspace).toBe('/tmp/repo')
})
})