hermes-agent/apps/desktop/src/store/gateway-switch.test.ts
Brooklyn Nicholson b3bde1fbee feat(desktop): soft gateway switch + gateway-settings polish
Switching connection mode (local / cloud agent / remote) no longer
full-window-reloads into the cold-boot CONNECTING screen. The primary
backend is torn down in place (no renderer reload); the shell + Settings
stay up while session lists are wiped so sidebar skeletons retrigger, then
the socket re-dials and config/sessions refresh. Cold-boot CONNECTING
latches off after the first successful boot; the intentional teardown
suppresses the backend-exit toast. Dev affordance: a "Preview soft switch"
button under Gateway diagnostics (Electron has no ?query= entry).

Gateway settings UI brought in line with the rest of Settings:
- Mode cards use the shared selectableCardClass on an equal-height
  auto-rows-fr grid, stacking 1→3 (never an orphaned 2+1); titles wrap
  instead of truncating.
- Remote gateway's auth detail moves into a ? tooltip in the title; drop
  the redundant "connects to the one you choose" from the cloud card.
- textStrong buttons force px-0 so the underline sits flush with the label.
- Tooltip chip uses box-decoration-break: clone so the background hugs each
  wrapped line (bg only on the text), capped at max-w-64.

Fully i18n'd (en + zh; ja/zh-hant inherit via defineLocale).
2026-07-10 02:57:02 -05:00

65 lines
2 KiB
TypeScript

import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { $sessionsLimit, resetSessionsLimit, SIDEBAR_SESSIONS_PAGE_SIZE } from '@/store/layout'
import {
$cronSessions,
$freshDraftReady,
$messagingSessions,
$sessions,
$sessionsLoading,
$sessionsTotal,
setCronSessions,
setFreshDraftReady,
setMessagingSessions,
setSessions,
setSessionsLoading,
setSessionsTotal
} from '@/store/session'
import { $gatewaySwitching, previewGatewaySwitch, wipeSessionListsForGatewaySwitch } from './gateway-switch'
vi.mock('@/lib/query-client', () => ({
queryClient: { invalidateQueries: vi.fn() }
}))
describe('wipeSessionListsForGatewaySwitch', () => {
beforeEach(() => {
$gatewaySwitching.set(false)
setSessions([{ id: 's1', title: 'old', profile: 'default' } as never])
setSessionsTotal(1)
setCronSessions([{ id: 'c1', title: 'cron', profile: 'default' } as never])
setMessagingSessions([{ id: 'm1', title: 'tg', profile: 'default' } as never])
setSessionsLoading(false)
setFreshDraftReady(false)
$sessionsLimit.set(SIDEBAR_SESSIONS_PAGE_SIZE * 3)
})
afterEach(() => {
resetSessionsLimit()
setSessions([])
setCronSessions([])
setMessagingSessions([])
setSessionsLoading(true)
$gatewaySwitching.set(false)
})
it('clears lists and arms loading so sidebar skeletons retrigger', () => {
wipeSessionListsForGatewaySwitch()
expect($sessions.get()).toEqual([])
expect($sessionsTotal.get()).toBe(0)
expect($cronSessions.get()).toEqual([])
expect($messagingSessions.get()).toEqual([])
expect($sessionsLoading.get()).toBe(true)
expect($sessionsLimit.get()).toBe(SIDEBAR_SESSIONS_PAGE_SIZE)
expect($freshDraftReady.get()).toBe(true)
})
it('previewGatewaySwitch holds skeletons then clears loading', async () => {
await previewGatewaySwitch(20)
expect($sessions.get()).toEqual([])
expect($sessionsLoading.get()).toBe(false)
expect($gatewaySwitching.get()).toBe(false)
})
})