From 665fff14b5253e6dd8c8dd5ae3a856243cc9a4be Mon Sep 17 00:00:00 2001 From: 777genius Date: Fri, 24 Apr 2026 20:53:45 +0300 Subject: [PATCH] test: cover opencode project evidence prepare --- .../TeamProvisioningServicePrepare.test.ts | 50 ++++++++++++++++ .../providerPrepareDiagnostics.test.ts | 60 +++++++++++++++++++ 2 files changed, 110 insertions(+) diff --git a/test/main/services/team/TeamProvisioningServicePrepare.test.ts b/test/main/services/team/TeamProvisioningServicePrepare.test.ts index 4382c275..112abc53 100644 --- a/test/main/services/team/TeamProvisioningServicePrepare.test.ts +++ b/test/main/services/team/TeamProvisioningServicePrepare.test.ts @@ -687,6 +687,56 @@ describe('TeamProvisioningService prepare/auth behavior', () => { ); }); + it('reports missing OpenCode project evidence as a provider note instead of model failures', async () => { + const projectEvidenceDiagnostic = + 'OpenCode production E2E evidence artifact has no entry for the current working directory'; + const projectEvidenceNote = + 'OpenCode has not been verified on this project yet. This does not mean the selected models are broken.'; + const prepare = vi.fn(async () => ({ + ok: false as const, + providerId: 'opencode' as const, + reason: 'e2e_missing', + retryable: false, + diagnostics: [projectEvidenceDiagnostic], + warnings: [], + })); + const registry = new TeamRuntimeAdapterRegistry([ + { + providerId: 'opencode', + prepare, + launch: vi.fn(), + reconcile: vi.fn(), + stop: vi.fn(), + } as any, + ]); + const svc = new TeamProvisioningService(); + svc.setRuntimeAdapterRegistry(registry); + + const result = await svc.prepareForProvisioning(tempRoot, { + providerId: 'opencode', + forceFresh: true, + modelIds: ['opencode/minimax-m2.5-free', 'opencode/ling-2.6-flash-free'], + modelVerificationMode: 'compatibility', + }); + + expect(result.ready).toBe(true); + expect(result.message).toBe('CLI is ready to launch (see notes)'); + expect(result.details).toEqual([ + 'Selected model opencode/minimax-m2.5-free verified for launch.', + 'Selected model opencode/ling-2.6-flash-free verified for launch.', + ]); + expect(result.warnings).toEqual([projectEvidenceNote]); + expect(result.message).not.toContain('unavailable'); + expect(prepare).toHaveBeenCalledTimes(1); + expect(prepare).toHaveBeenCalledWith( + expect.objectContaining({ + providerId: 'opencode', + model: undefined, + runtimeOnly: true, + }) + ); + }); + it('treats retryable OpenCode compatibility failures as blocking selected-model diagnostics', async () => { const prepare = vi.fn(async () => ({ ok: false as const, diff --git a/test/renderer/components/team/dialogs/providerPrepareDiagnostics.test.ts b/test/renderer/components/team/dialogs/providerPrepareDiagnostics.test.ts index 46a183da..9d9d2a1b 100644 --- a/test/renderer/components/team/dialogs/providerPrepareDiagnostics.test.ts +++ b/test/renderer/components/team/dialogs/providerPrepareDiagnostics.test.ts @@ -256,6 +256,66 @@ describe('runProviderPrepareDiagnostics', () => { ); }); + it('shows missing OpenCode project evidence as a provider note instead of model failures', async () => { + const projectEvidenceNote = + 'OpenCode has not been verified on this project yet. This does not mean the selected models are broken.'; + const prepareProvisioning = vi + .fn< + ( + cwd?: string, + providerId?: TeamProviderId, + providerIds?: TeamProviderId[], + selectedModels?: string[], + limitContext?: boolean, + modelVerificationMode?: 'compatibility' | 'deep' + ) => Promise + >() + .mockResolvedValue({ + ready: true, + message: 'CLI is ready to launch (see notes)', + details: [ + 'Selected model opencode/minimax-m2.5-free verified for launch.', + 'Selected model opencode/ling-2.6-flash-free verified for launch.', + ], + warnings: [projectEvidenceNote], + }); + + const result = await runProviderPrepareDiagnostics({ + cwd: '/tmp/project', + providerId: 'opencode', + selectedModelIds: ['opencode/minimax-m2.5-free', 'opencode/ling-2.6-flash-free'], + prepareProvisioning, + }); + + expect(result.status).toBe('notes'); + expect(result.details).toEqual([ + 'minimax-m2.5-free - verified', + 'ling-2.6-flash-free - verified', + ]); + expect(result.warnings).toEqual([projectEvidenceNote]); + expect(result.modelResultsById).toEqual({ + 'opencode/minimax-m2.5-free': { + status: 'ready', + line: 'minimax-m2.5-free - verified', + warningLine: null, + }, + 'opencode/ling-2.6-flash-free': { + status: 'ready', + line: 'ling-2.6-flash-free - verified', + warningLine: null, + }, + }); + expect(prepareProvisioning).toHaveBeenCalledTimes(1); + expect(prepareProvisioning).toHaveBeenCalledWith( + '/tmp/project', + 'opencode', + ['opencode'], + ['opencode/minimax-m2.5-free', 'opencode/ling-2.6-flash-free'], + undefined, + 'compatibility' + ); + }); + it('normalizes raw Codex API error envelopes into a clean model reason', async () => { const prepareProvisioning = vi.fn< (