agent-ecosystem/test/renderer/store/cliInstallerSlice.test.ts
iliya 0c2f70b2b2 feat: implement in-app project editor with CodeMirror integration
- Added architectural plan and iteration plan for the in-app project editor.
- Introduced new components for the editor, including CodeEditorOverlay, FileTreePanel, and EditorTabsPanel.
- Established state management using Zustand for editor state persistence.
- Implemented IPC channels for file operations and editor functionality.
- Enhanced TeamDetailView with a button to open the editor overlay.
- Conducted reuse analysis for existing components to optimize codebase integration.
2026-02-27 22:36:06 +02:00

189 lines
5.5 KiB
TypeScript

import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
// Mock api module
vi.mock('@renderer/api', () => ({
api: {
cliInstaller: {
getStatus: vi.fn(),
install: vi.fn(),
onProgress: vi.fn(() => vi.fn()),
},
// Minimal stubs for other api methods referenced by store slices
getProjects: vi.fn(() => Promise.resolve([])),
getSessions: vi.fn(() => Promise.resolve([])),
notifications: {
get: vi.fn(() =>
Promise.resolve({
notifications: [],
total: 0,
totalCount: 0,
unreadCount: 0,
hasMore: false,
})
),
getUnreadCount: vi.fn(() => Promise.resolve(0)),
onNew: vi.fn(),
onUpdated: vi.fn(),
onClicked: vi.fn(),
},
config: { get: vi.fn(() => Promise.resolve({})) },
updater: { check: vi.fn(), onStatus: vi.fn() },
context: {
getActive: vi.fn(() => Promise.resolve('local')),
list: vi.fn(),
onChanged: vi.fn(),
},
teams: {
list: vi.fn(() => Promise.resolve([])),
onTeamChange: vi.fn(),
onProvisioningProgress: vi.fn(),
},
ssh: { onStatus: vi.fn() },
onFileChange: vi.fn(),
onTodoChange: vi.fn(),
getAppVersion: vi.fn(() => Promise.resolve('1.0.0')),
},
isElectronMode: () => true,
}));
import { api } from '@renderer/api';
import { useStore } from '@renderer/store';
import type { CliInstallationStatus } from '@shared/types';
describe('cliInstallerSlice', () => {
beforeEach(() => {
vi.clearAllMocks();
// Reset store state
useStore.setState({
cliStatus: null,
cliInstallerState: 'idle',
cliDownloadProgress: 0,
cliDownloadTransferred: 0,
cliDownloadTotal: 0,
cliInstallerError: null,
cliCompletedVersion: null,
});
});
afterEach(() => {
vi.restoreAllMocks();
});
describe('initial state', () => {
it('has correct defaults', () => {
const state = useStore.getState();
expect(state.cliStatus).toBeNull();
expect(state.cliInstallerState).toBe('idle');
expect(state.cliDownloadProgress).toBe(0);
expect(state.cliInstallerError).toBeNull();
});
});
describe('fetchCliStatus', () => {
it('updates cliStatus from API', async () => {
const mockStatus: CliInstallationStatus = {
installed: true,
installedVersion: '2.1.59',
binaryPath: '/usr/local/bin/claude',
latestVersion: '2.1.59',
updateAvailable: false,
authLoggedIn: false,
authMethod: null,
};
vi.mocked(api.cliInstaller.getStatus).mockResolvedValue(mockStatus);
await useStore.getState().fetchCliStatus();
expect(useStore.getState().cliStatus).toEqual(mockStatus);
});
it('handles API errors gracefully', async () => {
vi.mocked(api.cliInstaller.getStatus).mockRejectedValue(new Error('Network error'));
await useStore.getState().fetchCliStatus();
// Should not throw, status remains null
expect(useStore.getState().cliStatus).toBeNull();
});
it('detects update available', async () => {
const mockStatus: CliInstallationStatus = {
installed: true,
installedVersion: '2.1.34',
binaryPath: '/usr/local/bin/claude',
latestVersion: '2.1.59',
updateAvailable: true,
authLoggedIn: true,
authMethod: 'oauth_token',
};
vi.mocked(api.cliInstaller.getStatus).mockResolvedValue(mockStatus);
await useStore.getState().fetchCliStatus();
expect(useStore.getState().cliStatus?.updateAvailable).toBe(true);
});
});
describe('installCli', () => {
it('sets state to checking and calls API', () => {
vi.mocked(api.cliInstaller.install).mockResolvedValue(undefined);
useStore.getState().installCli();
expect(useStore.getState().cliInstallerState).toBe('checking');
expect(useStore.getState().cliInstallerError).toBeNull();
expect(api.cliInstaller.install).toHaveBeenCalled();
});
it('resets download progress on new install', () => {
useStore.setState({
cliDownloadProgress: 50,
cliDownloadTransferred: 100_000_000,
cliDownloadTotal: 200_000_000,
});
vi.mocked(api.cliInstaller.install).mockResolvedValue(undefined);
useStore.getState().installCli();
expect(useStore.getState().cliDownloadProgress).toBe(0);
expect(useStore.getState().cliDownloadTransferred).toBe(0);
expect(useStore.getState().cliDownloadTotal).toBe(0);
});
});
describe('progress event handling', () => {
it('updates download progress from events', () => {
useStore.setState({
cliInstallerState: 'downloading',
cliDownloadProgress: 50,
cliDownloadTransferred: 100_000_000,
cliDownloadTotal: 200_000_000,
});
const state = useStore.getState();
expect(state.cliInstallerState).toBe('downloading');
expect(state.cliDownloadProgress).toBe(50);
});
it('tracks completed version', () => {
useStore.setState({
cliInstallerState: 'completed',
cliCompletedVersion: '2.1.59',
});
expect(useStore.getState().cliCompletedVersion).toBe('2.1.59');
});
it('tracks error state', () => {
useStore.setState({
cliInstallerState: 'error',
cliInstallerError: 'SHA256 checksum mismatch',
});
expect(useStore.getState().cliInstallerState).toBe('error');
expect(useStore.getState().cliInstallerError).toBe('SHA256 checksum mismatch');
});
});
});