/** * Mock for window.electronAPI used in tests. * Provides typed mocks for all IPC methods. */ import { vi } from 'vitest'; import type { Project, Session, SessionDetail } from '../../src/renderer/types/data'; export interface MockElectronAPI { getProjects: ReturnType<typeof vi.fn<() => Promise<Project[]>>>; getSessions: ReturnType<typeof vi.fn<(projectId: string) => Promise<Session[]>>>; getSessionsPaginated: ReturnType< typeof vi.fn< ( projectId: string, cursor: string | null, limit?: number, options?: { includeTotalCount?: boolean; prefilterAll?: boolean } ) => Promise<{ sessions: Session[]; nextCursor: string | null; hasMore: boolean; totalCount: number; }> > >; getSessionDetail: ReturnType< typeof vi.fn<(projectId: string, sessionId: string) => Promise<SessionDetail | null>> >; getRepositoryGroups: ReturnType<typeof vi.fn>; getWorktreeSessions: ReturnType<typeof vi.fn>; getSubagentDetail: ReturnType<typeof vi.fn>; searchSessions: ReturnType<typeof vi.fn>; readClaudeMdFiles: ReturnType<typeof vi.fn>; readDirectoryClaudeMd: ReturnType<typeof vi.fn>; readMentionedFile: ReturnType<typeof vi.fn>; validateMentions: ReturnType<typeof vi.fn>; openPath: ReturnType<typeof vi.fn>; openExternal: ReturnType<typeof vi.fn>; notifications: { onNew: ReturnType<typeof vi.fn>; onUpdated: ReturnType<typeof vi.fn>; getUnread: ReturnType<typeof vi.fn>; markAsRead: ReturnType<typeof vi.fn>; markAllAsRead: ReturnType<typeof vi.fn>; // Methods used by notificationSlice get: ReturnType<typeof vi.fn>; markRead: ReturnType<typeof vi.fn>; markAllRead: ReturnType<typeof vi.fn>; delete: ReturnType<typeof vi.fn>; clear: ReturnType<typeof vi.fn>; }; onFileChange: ReturnType<typeof vi.fn>; onTodoChange: ReturnType<typeof vi.fn>; config: { get: ReturnType<typeof vi.fn>; update: ReturnType<typeof vi.fn>; addIgnoreRegex: ReturnType<typeof vi.fn>; removeIgnoreRegex: ReturnType<typeof vi.fn>; addIgnoreRepository: ReturnType<typeof vi.fn>; removeIgnoreRepository: ReturnType<typeof vi.fn>; snooze: ReturnType<typeof vi.fn>; clearSnooze: ReturnType<typeof vi.fn>; addTrigger: ReturnType<typeof vi.fn>; updateTrigger: ReturnType<typeof vi.fn>; removeTrigger: ReturnType<typeof vi.fn>; getTriggers: ReturnType<typeof vi.fn>; testTrigger: ReturnType<typeof vi.fn>; selectFolders: ReturnType<typeof vi.fn>; selectClaudeRootFolder: ReturnType<typeof vi.fn>; getClaudeRootInfo: ReturnType<typeof vi.fn>; findWslClaudeRoots: ReturnType<typeof vi.fn>; openInEditor: ReturnType<typeof vi.fn>; pinSession: ReturnType<typeof vi.fn>; unpinSession: ReturnType<typeof vi.fn>; };} /** * Create a fresh mock electronAPI instance. */export function createMockElectronAPI(): MockElectronAPI { return { getProjects: vi.fn().mockResolvedValue([]), getSessions: vi.fn().mockResolvedValue([]), getSessionsPaginated: vi.fn().mockResolvedValue({ sessions: [], nextCursor: null, hasMore: false, totalCount: 0, }), getSessionDetail: vi.fn().mockResolvedValue(null), getRepositoryGroups: vi.fn().mockResolvedValue([]), getWorktreeSessions: vi.fn().mockResolvedValue([]), getSubagentDetail: vi.fn().mockResolvedValue(null), searchSessions: vi.fn().mockResolvedValue({ results: [], totalMatches: 0, sessionsSearched: 0, query: '', }), readClaudeMdFiles: vi.fn().mockResolvedValue({}), readDirectoryClaudeMd: vi.fn().mockResolvedValue({ path: '', exists: false, charCount: 0, estimatedTokens: 0, }), readMentionedFile: vi.fn().mockResolvedValue(null), validateMentions: vi.fn().mockResolvedValue({}), openPath: vi.fn().mockResolvedValue({ success: true }), openExternal: vi.fn().mockResolvedValue({ success: true }), notifications: { onNew: vi.fn().mockReturnValue(() => undefined), onUpdated: vi.fn().mockReturnValue(() => undefined), getUnread: vi.fn().mockResolvedValue([]), markAsRead: vi.fn().mockResolvedValue(undefined), markAllAsRead: vi.fn().mockResolvedValue(undefined), // Methods used by notificationSlice get: vi.fn().mockResolvedValue({ notifications: [] }), markRead: vi.fn().mockResolvedValue(true), markAllRead: vi.fn().mockResolvedValue(true), delete: vi.fn().mockResolvedValue(true), clear: vi.fn().mockResolvedValue(true), }, onFileChange: vi.fn().mockReturnValue(() => undefined), onTodoChange: vi.fn().mockReturnValue(() => undefined), config: { get: vi.fn().mockResolvedValue({ notifications: { enabled: true, soundEnabled: true, ignoredRegex: [], ignoredRepositories: [], snoozedUntil: null, snoozeMinutes: 30, triggers: [], }, general: { launchAtLogin: false, showDockIcon: true, theme: 'dark', defaultTab: 'dashboard', claudeRootPath: null, }, display: { showTimestamps: true, compactMode: false, syntaxHighlighting: true, }, sessions: { pinnedSessions: {}, }, }), update: vi.fn(), addIgnoreRegex: vi.fn(), removeIgnoreRegex: vi.fn(), addIgnoreRepository: vi.fn(), removeIgnoreRepository: vi.fn(), snooze: vi.fn(), clearSnooze: vi.fn(), addTrigger: vi.fn(), updateTrigger: vi.fn(), removeTrigger: vi.fn(), getTriggers: vi.fn().mockResolvedValue([]), testTrigger: vi.fn(), selectFolders: vi.fn().mockResolvedValue([]), selectClaudeRootFolder: vi.fn().mockResolvedValue(null), getClaudeRootInfo: vi.fn().mockResolvedValue({ defaultPath: '~/.claude', resolvedPath: '~/.claude', customPath: null, }), findWslClaudeRoots: vi.fn().mockResolvedValue([]), openInEditor: vi.fn(), pinSession: vi.fn(), unpinSession: vi.fn(), }, };} /** * Install mock electronAPI on window object. * Returns the mock instance for assertions. */export function installMockElectronAPI(): MockElectronAPI { const mock = createMockElectronAPI(); vi.stubGlobal('window', { ...window, electronAPI: mock, }); return mock;}
/**
* Mock for window.electronAPI used in tests.
* Provides typed mocks for all IPC methods.
*/
import { vi } from 'vitest';
import type { Project, Session, SessionDetail } from '../../src/renderer/types/data';
export interface MockElectronAPI {
getProjects: ReturnType<typeof vi.fn<() => Promise<Project[]>>>;
getSessions: ReturnType<typeof vi.fn<(projectId: string) => Promise<Session[]>>>;
getSessionsPaginated: ReturnType<
typeof vi.fn<
(
projectId: string,
cursor: string | null,
limit?: number,
options?: { includeTotalCount?: boolean; prefilterAll?: boolean }
) => Promise<{
sessions: Session[];
nextCursor: string | null;
hasMore: boolean;
totalCount: number;
}>
>
>;
getSessionDetail: ReturnType<
typeof vi.fn<(projectId: string, sessionId: string) => Promise<SessionDetail | null>>
>;
getRepositoryGroups: ReturnType<typeof vi.fn>;
getWorktreeSessions: ReturnType<typeof vi.fn>;
getSubagentDetail: ReturnType<typeof vi.fn>;
searchSessions: ReturnType<typeof vi.fn>;
readClaudeMdFiles: ReturnType<typeof vi.fn>;
readDirectoryClaudeMd: ReturnType<typeof vi.fn>;
readMentionedFile: ReturnType<typeof vi.fn>;
validateMentions: ReturnType<typeof vi.fn>;
openPath: ReturnType<typeof vi.fn>;
openExternal: ReturnType<typeof vi.fn>;
notifications: {
onNew: ReturnType<typeof vi.fn>;
onUpdated: ReturnType<typeof vi.fn>;
getUnread: ReturnType<typeof vi.fn>;
markAsRead: ReturnType<typeof vi.fn>;
markAllAsRead: ReturnType<typeof vi.fn>;
// Methods used by notificationSlice
get: ReturnType<typeof vi.fn>;
markRead: ReturnType<typeof vi.fn>;
markAllRead: ReturnType<typeof vi.fn>;
delete: ReturnType<typeof vi.fn>;
clear: ReturnType<typeof vi.fn>;
};
onFileChange: ReturnType<typeof vi.fn>;
onTodoChange: ReturnType<typeof vi.fn>;
config: {
get: ReturnType<typeof vi.fn>;
update: ReturnType<typeof vi.fn>;
addIgnoreRegex: ReturnType<typeof vi.fn>;
removeIgnoreRegex: ReturnType<typeof vi.fn>;
addIgnoreRepository: ReturnType<typeof vi.fn>;
removeIgnoreRepository: ReturnType<typeof vi.fn>;
snooze: ReturnType<typeof vi.fn>;
clearSnooze: ReturnType<typeof vi.fn>;
addTrigger: ReturnType<typeof vi.fn>;
updateTrigger: ReturnType<typeof vi.fn>;
removeTrigger: ReturnType<typeof vi.fn>;
getTriggers: ReturnType<typeof vi.fn>;
testTrigger: ReturnType<typeof vi.fn>;
selectFolders: ReturnType<typeof vi.fn>;
selectClaudeRootFolder: ReturnType<typeof vi.fn>;
getClaudeRootInfo: ReturnType<typeof vi.fn>;
findWslClaudeRoots: ReturnType<typeof vi.fn>;
openInEditor: ReturnType<typeof vi.fn>;
pinSession: ReturnType<typeof vi.fn>;
unpinSession: ReturnType<typeof vi.fn>;
};
}
/**
* Create a fresh mock electronAPI instance.
*/
export function createMockElectronAPI(): MockElectronAPI {
return {
getProjects: vi.fn().mockResolvedValue([]),
getSessions: vi.fn().mockResolvedValue([]),
getSessionsPaginated: vi.fn().mockResolvedValue({
sessions: [],
nextCursor: null,
hasMore: false,
totalCount: 0,
}),
getSessionDetail: vi.fn().mockResolvedValue(null),
getRepositoryGroups: vi.fn().mockResolvedValue([]),
getWorktreeSessions: vi.fn().mockResolvedValue([]),
getSubagentDetail: vi.fn().mockResolvedValue(null),
searchSessions: vi.fn().mockResolvedValue({
results: [],
totalMatches: 0,
sessionsSearched: 0,
query: '',
}),
readClaudeMdFiles: vi.fn().mockResolvedValue({}),
readDirectoryClaudeMd: vi.fn().mockResolvedValue({
path: '',
exists: false,
charCount: 0,
estimatedTokens: 0,
}),
readMentionedFile: vi.fn().mockResolvedValue(null),
validateMentions: vi.fn().mockResolvedValue({}),
openPath: vi.fn().mockResolvedValue({ success: true }),
openExternal: vi.fn().mockResolvedValue({ success: true }),
notifications: {
onNew: vi.fn().mockReturnValue(() => undefined),
onUpdated: vi.fn().mockReturnValue(() => undefined),
getUnread: vi.fn().mockResolvedValue([]),
markAsRead: vi.fn().mockResolvedValue(undefined),
markAllAsRead: vi.fn().mockResolvedValue(undefined),
// Methods used by notificationSlice
get: vi.fn().mockResolvedValue({ notifications: [] }),
markRead: vi.fn().mockResolvedValue(true),
markAllRead: vi.fn().mockResolvedValue(true),
delete: vi.fn().mockResolvedValue(true),
clear: vi.fn().mockResolvedValue(true),
},
onFileChange: vi.fn().mockReturnValue(() => undefined),
onTodoChange: vi.fn().mockReturnValue(() => undefined),
config: {
get: vi.fn().mockResolvedValue({
notifications: {
enabled: true,
soundEnabled: true,
ignoredRegex: [],
ignoredRepositories: [],
snoozedUntil: null,
snoozeMinutes: 30,
triggers: [],
},
general: {
launchAtLogin: false,
showDockIcon: true,
theme: 'dark',
defaultTab: 'dashboard',
claudeRootPath: null,
},
display: {
showTimestamps: true,
compactMode: false,
syntaxHighlighting: true,
},
sessions: {
pinnedSessions: {},
},
}),
update: vi.fn(),
addIgnoreRegex: vi.fn(),
removeIgnoreRegex: vi.fn(),
addIgnoreRepository: vi.fn(),
removeIgnoreRepository: vi.fn(),
snooze: vi.fn(),
clearSnooze: vi.fn(),
addTrigger: vi.fn(),
updateTrigger: vi.fn(),
removeTrigger: vi.fn(),
getTriggers: vi.fn().mockResolvedValue([]),
testTrigger: vi.fn(),
selectFolders: vi.fn().mockResolvedValue([]),
selectClaudeRootFolder: vi.fn().mockResolvedValue(null),
getClaudeRootInfo: vi.fn().mockResolvedValue({
defaultPath: '~/.claude',
resolvedPath: '~/.claude',
customPath: null,
}),
findWslClaudeRoots: vi.fn().mockResolvedValue([]),
openInEditor: vi.fn(),
pinSession: vi.fn(),
unpinSession: vi.fn(),
},
};
}
/**
* Install mock electronAPI on window object.
* Returns the mock instance for assertions.
*/
export function installMockElectronAPI(): MockElectronAPI {
const mock = createMockElectronAPI();
vi.stubGlobal('window', {
...window,
electronAPI: mock,
});
return mock;
}