Files
hermes-web-ui/tests/server/profile-delete-managed-gateway.test.ts
Zhicheng Han a2fde1fe1c 修复删除 profile 后 managed gateway 被重新拉起 (#1667)
* fix: retire deleted profile gateways without respawn

* fix: stop profile gateway before delete

* fix: verify profile deletion before API success

* test: cover profile delete managed gateway lifecycle

* fix: keep delete prep scoped to existing profiles
2026-06-19 16:05:57 +08:00

76 lines
2.2 KiB
TypeScript

import { EventEmitter } from 'events'
import { mkdir, mkdtemp, rm, writeFile } from 'fs/promises'
import { tmpdir } from 'os'
import { join } from 'path'
import { afterEach, describe, expect, it, vi } from 'vitest'
const originalEnv = { ...process.env }
class FakeChild extends EventEmitter {
pid: number
killSignals: string[] = []
constructor(pid: number) {
super()
this.pid = pid
}
unref() { /* no-op */ }
kill(signal?: string) {
this.killSignals.push(signal || 'SIGTERM')
return true
}
}
let fakeChildren: FakeChild[] = []
vi.mock('../../packages/server/src/services/hermes/hermes-process', () => ({
execHermesWithBin: vi.fn().mockResolvedValue({ stdout: '', stderr: '' }),
spawnHermesWithBin: vi.fn(() => {
const child = new FakeChild(20000 + fakeChildren.length)
fakeChildren.push(child)
return child
}),
}))
afterEach(() => {
vi.useRealTimers()
vi.restoreAllMocks()
vi.resetModules()
process.env = { ...originalEnv }
fakeChildren = []
})
describe('profile delete managed gateway lifecycle', () => {
it('reproduces #1633 and proves delete prep suppresses managed respawn', async () => {
vi.useFakeTimers()
vi.resetModules()
const home = await mkdtemp(join(tmpdir(), 'wui-1633-'))
process.env.HERMES_HOME = home
process.env.HERMES_BIN = '/usr/bin/hermes'
const profileDir = join(home, 'profiles', 'work')
await mkdir(profileDir, { recursive: true })
await writeFile(join(profileDir, 'config.yaml'), 'model:\n default: test\n', 'utf-8')
try {
const { startGatewayRunManaged } = await import('../../packages/server/src/services/hermes/gateway-runner')
const { prepareGatewayForProfileDelete } = await import('../../packages/server/src/services/hermes/gateway-autostart')
startGatewayRunManaged('/usr/bin/hermes', { profileDir })
expect(fakeChildren).toHaveLength(1)
const prep = prepareGatewayForProfileDelete('work')
expect(fakeChildren[0].killSignals).toEqual(['SIGTERM'])
fakeChildren[0].emit('exit', 0, 'SIGTERM')
await prep
await vi.advanceTimersByTimeAsync(6000)
expect(fakeChildren).toHaveLength(1)
} finally {
await rm(home, { recursive: true, force: true })
}
})
})