Files
inkling/tests/unit/inboxApi-revisions.test.ts
altair823 4db7a0bce0 refactor(v032): recall IPC handle→on + fix sibling test mocks (#36)
- inbox:emitRecallShown / emitRecallSnoozed: ipcMain.handle → on
  (fire-and-forget honest pattern, return value 의존자 0)
- preload: ipcRenderer.invoke → send (matching on the main side)
- shared/types: Promise<void> → void on both recall emit methods
- store.ts: drop await on emitRecallSnoozed (now void)
- inboxApi-*.test.ts: add ipcMain.on to electron mock (broken by above)
- tests/unit/recall-ipc.test.ts: new TDD test for handle→on migration

Note: #20 CaptureService telemetry .catch debug log skipped —
CaptureService has no logger field; adding one would require non-trivial
constructor signature change. Reported as CONCERN below.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 14:23:19 +09:00

100 lines
3.5 KiB
TypeScript

import { describe, it, expect, beforeEach, vi } from 'vitest';
vi.mock('electron', () => ({
default: {
ipcMain: { handle: vi.fn(), on: vi.fn() }
}
}));
import electron from 'electron';
import { registerInboxApi } from '../../src/main/ipc/inboxApi.js';
import type { InboxIpcDeps } from '../../src/main/ipc/inboxApi.js';
function getHandler(channel: string): (...args: unknown[]) => unknown {
const handle = (electron.ipcMain as unknown as { handle: ReturnType<typeof vi.fn> }).handle;
const call = handle.mock.calls.find((c) => c[0] === channel);
if (!call) throw new Error(`channel ${channel} not registered`);
return call[1] as (...args: unknown[]) => unknown;
}
function makeDeps(overrides: Partial<InboxIpcDeps> = {}): InboxIpcDeps {
const repo = {
updateRawText: vi.fn(),
listRevisions: vi.fn(() => []),
restoreRevision: vi.fn(),
findById: vi.fn(),
list: vi.fn(),
listByStatus: vi.fn(),
countByStatus: vi.fn(() => 0),
countByAiStatus: vi.fn(() => 0),
countTrashed: vi.fn(() => 0),
countFailed: vi.fn(() => 0),
listTrashed: vi.fn(() => []),
setStatus: vi.fn(),
requeueDisabled: vi.fn(() => 0),
getAllPendingJobs: vi.fn(() => []),
getPendingCount: vi.fn(() => 0),
countToday: vi.fn(() => 0)
} as unknown as InboxIpcDeps['repo'];
return {
repo,
continuity: { get: vi.fn() } as unknown as InboxIpcDeps['continuity'],
capture: {} as InboxIpcDeps['capture'],
health: {} as InboxIpcDeps['health'],
intent: {} as InboxIpcDeps['intent'],
getInboxWindow: () => null,
settings: {} as InboxIpcDeps['settings'],
providerHolder: {} as InboxIpcDeps['providerHolder'],
paths: { profileDir: '/tmp' },
...overrides
};
}
describe('inboxApi revisions IPC', () => {
beforeEach(() => {
(electron.ipcMain as unknown as { handle: ReturnType<typeof vi.fn> }).handle.mockClear();
});
it('inbox:update-raw-text — repo.updateRawText 호출 + ok:true', async () => {
const deps = makeDeps();
registerInboxApi(deps);
const h = getHandler('inbox:update-raw-text');
const r = await h({}, 'note-1', 'new text');
expect(deps.repo.updateRawText).toHaveBeenCalledWith('note-1', 'new text');
expect(r).toEqual({ ok: true });
});
it('inbox:update-raw-text — 빈 문자열 reject', async () => {
const deps = makeDeps();
registerInboxApi(deps);
const h = getHandler('inbox:update-raw-text');
const r = await h({}, 'note-1', ' ');
expect(deps.repo.updateRawText).not.toHaveBeenCalled();
expect(r).toEqual({ ok: false, reason: 'empty' });
});
it('inbox:list-revisions — repo.listRevisions 결과 반환', async () => {
const deps = makeDeps();
(deps.repo.listRevisions as ReturnType<typeof vi.fn>).mockReturnValue([
{ revId: 1, noteId: 'a', rawText: 'v1', editedAt: 't1', editedBy: 'capture' }
]);
registerInboxApi(deps);
const h = getHandler('inbox:list-revisions');
const r = await h({}, 'a');
expect(r).toEqual([
{ revId: 1, noteId: 'a', rawText: 'v1', editedAt: 't1', editedBy: 'capture' }
]);
});
it('inbox:restore-revision — repo throw 시 ok:false', async () => {
const deps = makeDeps();
(deps.repo.restoreRevision as ReturnType<typeof vi.fn>).mockImplementation(() => {
throw new Error('revision 99 not found for note a');
});
registerInboxApi(deps);
const h = getHandler('inbox:restore-revision');
const r = await h({}, 'a', 99);
expect(r).toEqual({ ok: false, reason: 'revision 99 not found for note a' });
});
});