163 lines
7 KiB
TypeScript
163 lines
7 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
const mockIsTmuxRuntimeReadyForCurrentPlatform = vi.fn<() => Promise<boolean>>();
|
|
|
|
vi.mock('@features/tmux-installer/main', () => ({
|
|
isTmuxRuntimeReadyForCurrentPlatform: mockIsTmuxRuntimeReadyForCurrentPlatform,
|
|
}));
|
|
|
|
describe('runtimeTeammateMode', () => {
|
|
const originalTeamMateModeEnv = process.env.CLAUDE_TEAM_TEAMMATE_MODE;
|
|
|
|
beforeEach(() => {
|
|
vi.resetModules();
|
|
vi.clearAllMocks();
|
|
if (originalTeamMateModeEnv === undefined) {
|
|
delete process.env.CLAUDE_TEAM_TEAMMATE_MODE;
|
|
} else {
|
|
process.env.CLAUDE_TEAM_TEAMMATE_MODE = originalTeamMateModeEnv;
|
|
}
|
|
});
|
|
|
|
it('does not inject tmux mode in default desktop launch when tmux runtime is ready', async () => {
|
|
mockIsTmuxRuntimeReadyForCurrentPlatform.mockResolvedValue(true);
|
|
const { resolveDesktopTeammateModeDecision } =
|
|
await import('@main/services/team/runtimeTeammateMode');
|
|
|
|
const decision = await resolveDesktopTeammateModeDecision(undefined);
|
|
|
|
expect(decision.forceProcessTeammates).toBe(true);
|
|
expect(decision.injectedTeammateMode).toBeNull();
|
|
});
|
|
|
|
it('uses native process teammates when tmux runtime is not ready', async () => {
|
|
mockIsTmuxRuntimeReadyForCurrentPlatform.mockResolvedValue(false);
|
|
const { resolveDesktopTeammateModeDecision } =
|
|
await import('@main/services/team/runtimeTeammateMode');
|
|
|
|
const decision = await resolveDesktopTeammateModeDecision(undefined);
|
|
|
|
expect(decision.forceProcessTeammates).toBe(true);
|
|
expect(decision.injectedTeammateMode).toBeNull();
|
|
});
|
|
|
|
it('honors explicit tmux mode as a debug opt-out from process teammates', async () => {
|
|
mockIsTmuxRuntimeReadyForCurrentPlatform.mockResolvedValue(true);
|
|
const { resolveDesktopTeammateModeDecision } =
|
|
await import('@main/services/team/runtimeTeammateMode');
|
|
|
|
const decision = await resolveDesktopTeammateModeDecision('--teammate-mode tmux');
|
|
const equalsDecision = await resolveDesktopTeammateModeDecision('--teammate-mode=tmux');
|
|
|
|
expect(decision.forceProcessTeammates).toBe(false);
|
|
expect(decision.injectedTeammateMode).toBe('tmux');
|
|
expect(equalsDecision.forceProcessTeammates).toBe(false);
|
|
expect(equalsDecision.injectedTeammateMode).toBe('tmux');
|
|
expect(mockIsTmuxRuntimeReadyForCurrentPlatform).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('treats explicit auto mode as automatic process teammate selection without injection', async () => {
|
|
mockIsTmuxRuntimeReadyForCurrentPlatform.mockResolvedValue(true);
|
|
const { resolveDesktopTeammateModeDecision } =
|
|
await import('@main/services/team/runtimeTeammateMode');
|
|
|
|
const decision = await resolveDesktopTeammateModeDecision('--teammate-mode auto');
|
|
const equalsDecision = await resolveDesktopTeammateModeDecision('--teammate-mode=auto');
|
|
|
|
expect(decision.forceProcessTeammates).toBe(true);
|
|
expect(decision.injectedTeammateMode).toBeNull();
|
|
expect(equalsDecision.forceProcessTeammates).toBe(true);
|
|
expect(equalsDecision.injectedTeammateMode).toBeNull();
|
|
expect(mockIsTmuxRuntimeReadyForCurrentPlatform).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('honors CLAUDE_TEAM_TEAMMATE_MODE=tmux for desktop debug launches', async () => {
|
|
mockIsTmuxRuntimeReadyForCurrentPlatform.mockResolvedValue(true);
|
|
process.env.CLAUDE_TEAM_TEAMMATE_MODE = 'tmux';
|
|
const { resolveDesktopTeammateModeDecision } =
|
|
await import('@main/services/team/runtimeTeammateMode');
|
|
|
|
const decision = await resolveDesktopTeammateModeDecision(undefined);
|
|
|
|
expect(decision.forceProcessTeammates).toBe(false);
|
|
expect(decision.injectedTeammateMode).toBe('tmux');
|
|
expect(mockIsTmuxRuntimeReadyForCurrentPlatform).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('lets explicit teammate mode args override CLAUDE_TEAM_TEAMMATE_MODE', async () => {
|
|
mockIsTmuxRuntimeReadyForCurrentPlatform.mockResolvedValue(true);
|
|
process.env.CLAUDE_TEAM_TEAMMATE_MODE = 'tmux';
|
|
const { resolveDesktopTeammateModeDecision } =
|
|
await import('@main/services/team/runtimeTeammateMode');
|
|
|
|
const decision = await resolveDesktopTeammateModeDecision('--teammate-mode=in-process');
|
|
|
|
expect(decision.forceProcessTeammates).toBe(false);
|
|
expect(decision.injectedTeammateMode).toBeNull();
|
|
expect(mockIsTmuxRuntimeReadyForCurrentPlatform).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('ignores unsupported CLAUDE_TEAM_TEAMMATE_MODE values', async () => {
|
|
mockIsTmuxRuntimeReadyForCurrentPlatform.mockResolvedValue(true);
|
|
process.env.CLAUDE_TEAM_TEAMMATE_MODE = 'pane';
|
|
const { resolveDesktopTeammateModeDecision } =
|
|
await import('@main/services/team/runtimeTeammateMode');
|
|
|
|
const decision = await resolveDesktopTeammateModeDecision(undefined);
|
|
|
|
expect(decision.forceProcessTeammates).toBe(true);
|
|
expect(decision.injectedTeammateMode).toBeNull();
|
|
expect(mockIsTmuxRuntimeReadyForCurrentPlatform).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it('honors explicit in-process mode as an opt-out from process teammates', async () => {
|
|
mockIsTmuxRuntimeReadyForCurrentPlatform.mockResolvedValue(true);
|
|
const { resolveDesktopTeammateModeDecision } =
|
|
await import('@main/services/team/runtimeTeammateMode');
|
|
|
|
const decision = await resolveDesktopTeammateModeDecision('--teammate-mode=in-process');
|
|
|
|
expect(decision.forceProcessTeammates).toBe(false);
|
|
expect(decision.injectedTeammateMode).toBeNull();
|
|
expect(mockIsTmuxRuntimeReadyForCurrentPlatform).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('removes inherited process fallback env when explicit in-process mode opts out', async () => {
|
|
const { applyDesktopTeammateModeDecisionToEnv } =
|
|
await import('@main/services/team/runtimeTeammateMode');
|
|
const env = {
|
|
CLAUDE_TEAM_FORCE_PROCESS_TEAMMATES: '1',
|
|
};
|
|
|
|
applyDesktopTeammateModeDecisionToEnv(env, { forceProcessTeammates: false });
|
|
|
|
expect(env).not.toHaveProperty('CLAUDE_TEAM_FORCE_PROCESS_TEAMMATES');
|
|
});
|
|
|
|
it('builds injected teammate mode cli args only when a mode was selected', async () => {
|
|
const { buildDesktopTeammateModeCliArgs } =
|
|
await import('@main/services/team/runtimeTeammateMode');
|
|
|
|
expect(buildDesktopTeammateModeCliArgs({ injectedTeammateMode: 'tmux' })).toEqual([
|
|
'--teammate-mode',
|
|
'tmux',
|
|
]);
|
|
expect(buildDesktopTeammateModeCliArgs({ injectedTeammateMode: null })).toEqual([]);
|
|
});
|
|
|
|
it('re-checks tmux readiness after the environment changes instead of keeping a stale negative cache', async () => {
|
|
mockIsTmuxRuntimeReadyForCurrentPlatform
|
|
.mockResolvedValueOnce(false)
|
|
.mockResolvedValueOnce(true);
|
|
const { resolveDesktopTeammateModeDecision } =
|
|
await import('@main/services/team/runtimeTeammateMode');
|
|
|
|
const firstDecision = await resolveDesktopTeammateModeDecision(undefined);
|
|
const secondDecision = await resolveDesktopTeammateModeDecision(undefined);
|
|
|
|
expect(firstDecision.forceProcessTeammates).toBe(true);
|
|
expect(firstDecision.injectedTeammateMode).toBeNull();
|
|
expect(secondDecision.forceProcessTeammates).toBe(true);
|
|
expect(secondDecision.injectedTeammateMode).toBeNull();
|
|
});
|
|
});
|