import { assertDeterministicBootstrapPrimaryMemberLimit, assertOpenCodeNotLaunchedThroughLegacyProvisioning, buildLargeDeterministicBootstrapWarning, getMixedLaunchFallbackRecoveryError, getOpenCodeMixedProviderProvisioningError, isPureOpenCodeProvisioningRequest, mergeProvisioningWarnings, } from '@main/services/team/provisioning/TeamProvisioningLaunchCompatibility'; import { describe, expect, it } from 'vitest'; describe('TeamProvisioningLaunchCompatibility', () => { it('classifies pure OpenCode legacy provisioning requests', () => { expect( isPureOpenCodeProvisioningRequest({ providerId: 'opencode', members: [{ providerId: 'opencode' }, {}], }) ).toBe(true); expect( isPureOpenCodeProvisioningRequest({ providerId: 'codex', members: [{ providerId: 'opencode' }], }) ).toBe(false); }); it('blocks pure OpenCode legacy stream-json launch but allows supported side-lane mixed teams', () => { expect(() => assertOpenCodeNotLaunchedThroughLegacyProvisioning({ providerId: 'opencode', members: [{ providerId: 'opencode' }], }) ).toThrow('OpenCode team launch is not enabled in the legacy Claude stream-json provisioning path'); expect(() => assertOpenCodeNotLaunchedThroughLegacyProvisioning({ providerId: 'codex', members: [{ providerId: 'opencode' }, { providerId: 'codex' }], }) ).not.toThrow(); }); it('keeps unsupported OpenCode-led mixed teams blocked with planner diagnostics', () => { expect(() => assertOpenCodeNotLaunchedThroughLegacyProvisioning({ providerId: 'opencode', members: [{ providerId: 'anthropic' }, { providerId: 'opencode' }], }) ).toThrow('Mixed teams with an OpenCode lead are not supported'); }); it('deduplicates provisioning warnings while preserving latest ordering', () => { expect(mergeProvisioningWarnings(undefined, null)).toBeUndefined(); expect(mergeProvisioningWarnings(['alpha', 'beta'], 'alpha')).toEqual(['beta', 'alpha']); expect(mergeProvisioningWarnings(['alpha'], 'beta')).toEqual(['alpha', 'beta']); }); it('bounds deterministic bootstrap team size warnings and hard limits', () => { expect(buildLargeDeterministicBootstrapWarning(8)).toBeNull(); expect(buildLargeDeterministicBootstrapWarning(9)).toContain('Large Codex team launch: 9'); expect(() => assertDeterministicBootstrapPrimaryMemberLimit(20)).not.toThrow(); expect(() => assertDeterministicBootstrapPrimaryMemberLimit(21)).toThrow( 'supports up to 20 primary teammates' ); }); it('keeps user-facing compatibility error copy stable', () => { expect(getOpenCodeMixedProviderProvisioningError()).toContain( 'outside the current support scope' ); expect(getMixedLaunchFallbackRecoveryError()).toContain('missing stable member metadata'); }); });