Files
makelore/tests/unit/opencode-startup-warmup.test.ts
inman f4113a872f
Some checks failed
Electron E2E / Electron E2E (macos-latest) (push) Has been cancelled
Electron E2E / Electron E2E (ubuntu-latest) (push) Has been cancelled
Electron E2E / Electron E2E (windows-latest) (push) Has been cancelled
收口 Makelore 客户端变更
2026-08-12 22:43:09 +08:00

104 lines
3.4 KiB
TypeScript

import { describe, expect, it, vi } from 'vitest';
import {
warmupOpencodeRuntime,
type OpencodeStartupWarmupDependencies,
} from '@electron/opencode/startup-warmup';
function createDependencies(
overrides: Partial<OpencodeStartupWarmupDependencies> = {},
): OpencodeStartupWarmupDependencies {
return {
hasAuthenticatedSession: () => true,
getStatus: () => ({ state: 'stopped', port: 4096 }),
getActiveProject: vi.fn(async () => ({ path: '/projects/demo' })),
readProjectConfig: vi.fn(async () => ({
status: 'valid' as const,
config: { initialized: true },
})),
getConfiguredProviderCount: vi.fn(async () => 1),
start: vi.fn(async () => ({ state: 'running' as const, port: 4096 })),
...overrides,
};
}
describe('warmupOpencodeRuntime', () => {
it('starts a ready runtime in the background', async () => {
const dependencies = createDependencies();
const result = await warmupOpencodeRuntime(dependencies);
expect(result).toEqual({
started: true,
status: { state: 'running', port: 4096 },
});
expect(dependencies.readProjectConfig).toHaveBeenCalledWith('/projects/demo');
expect(dependencies.getConfiguredProviderCount).toHaveBeenCalledOnce();
expect(dependencies.start).toHaveBeenCalledOnce();
});
it('does not start without an authenticated session', async () => {
const dependencies = createDependencies({
hasAuthenticatedSession: () => false,
});
await expect(warmupOpencodeRuntime(dependencies)).resolves.toEqual({
started: false,
reason: 'no-session',
});
expect(dependencies.getActiveProject).not.toHaveBeenCalled();
expect(dependencies.start).not.toHaveBeenCalled();
});
it.each([
['no active project', { getActiveProject: vi.fn(async () => null) }, 'no-active-project'],
[
'uninitialized project',
{
readProjectConfig: vi.fn(async () => ({
status: 'valid' as const,
config: { initialized: false },
})),
},
'project-not-ready',
],
['no configured provider', { getConfiguredProviderCount: vi.fn(async () => 0) }, 'no-provider'],
] as const)('skips when there is %s', async (_label, overrides, reason) => {
const dependencies = createDependencies(overrides);
await expect(warmupOpencodeRuntime(dependencies)).resolves.toMatchObject({
started: false,
reason,
});
expect(dependencies.start).not.toHaveBeenCalled();
});
it('does not compete with an already active runtime', async () => {
const dependencies = createDependencies({
getStatus: () => ({ state: 'starting', port: 4096 }),
});
await expect(warmupOpencodeRuntime(dependencies)).resolves.toEqual({
started: false,
reason: 'runtime-active',
});
expect(dependencies.getActiveProject).not.toHaveBeenCalled();
expect(dependencies.start).not.toHaveBeenCalled();
});
it('swallows startup errors and leaves lazy Chat startup available', async () => {
const error = new Error('runtime failed');
const onError = vi.fn();
const dependencies = createDependencies({
start: vi.fn(async () => { throw error; }),
onError,
});
await expect(warmupOpencodeRuntime(dependencies)).resolves.toMatchObject({
started: false,
reason: 'start-failed',
error,
});
expect(onError).toHaveBeenCalledWith(error, 'start');
});
});