import { beforeEach, describe, expect, it, vi } from 'vitest' const h = vi.hoisted(() => ({ provider: { displayName: 'Dota 2', start: vi.fn(), stop: vi.fn(), detect: vi.fn(), install: vi.fn(), uninstall: vi.fn(), reconcile: vi.fn() }, startGsiServer: vi.fn(), stopGsiServer: vi.fn(), onLaunchOptionsApplied: vi.fn(), gamesEnabled: { dota2: true }, fireMatchSummary: vi.fn(), log: { info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn() } })) vi.mock('electron', () => ({ BrowserWindow: { getAllWindows: () => [] } })) vi.mock('./dota2', () => ({ Dota2Provider: vi.fn(function Dota2Provider() { return h.provider }) })) vi.mock('./gsi-server', () => ({ startGsiServer: h.startGsiServer, stopGsiServer: h.stopGsiServer })) vi.mock('./steam-launch-options', () => ({ onLaunchOptionsApplied: h.onLaunchOptionsApplied })) vi.mock('../store', () => ({ getChallenges: () => [], getGamesEnabled: () => h.gamesEnabled })) vi.mock('../notifications', () => ({ fireMatchSummary: h.fireMatchSummary })) vi.mock('../logger', () => ({ log: h.log })) async function loadRegistry(): Promise { return import('./registry') } beforeEach(() => { vi.resetModules() h.provider.start.mockResolvedValue(undefined) h.provider.stop.mockResolvedValue(undefined) h.provider.detect.mockResolvedValue({ id: 'dota2', name: 'Dota 2', installed: true, integrationActive: true, launchOptionStatus: 'applied', enabled: true }) h.provider.install.mockResolvedValue(undefined) h.provider.uninstall.mockResolvedValue(undefined) h.provider.reconcile.mockResolvedValue(undefined) h.startGsiServer.mockReset() h.startGsiServer.mockResolvedValue(undefined) h.stopGsiServer.mockReset() h.stopGsiServer.mockResolvedValue(undefined) h.onLaunchOptionsApplied.mockClear() h.fireMatchSummary.mockClear() h.log.info.mockClear() h.log.warn.mockClear() h.log.error.mockClear() h.log.debug.mockClear() }) describe('games registry lifecycle', () => { it('сбрасывает running после ошибки старта GSI и позволяет повторный старт', async () => { h.startGsiServer .mockRejectedValueOnce(new Error('port busy')) .mockResolvedValueOnce(undefined) const { startGamesRegistry } = await loadRegistry() await startGamesRegistry() await startGamesRegistry() expect(h.startGsiServer).toHaveBeenCalledTimes(2) expect(h.provider.start).toHaveBeenCalledTimes(1) }) it('stopGamesRegistry ждёт полного shutdown GSI-сервера', async () => { let releaseStop!: () => void const stopPromise = new Promise((resolve) => { releaseStop = resolve }) h.stopGsiServer.mockReturnValue(stopPromise) const { startGamesRegistry, stopGamesRegistry } = await loadRegistry() await startGamesRegistry() let resolved = false const pending = stopGamesRegistry().then(() => { resolved = true }) await Promise.resolve() expect(resolved).toBe(false) releaseStop() await pending expect(resolved).toBe(true) }) })