项目文件夹

文件
wehub-resource-sync 98e40dac97
CLI Smoke Test / smoke-test-linux (20) (push) Has been cancelled
CLI Smoke Test / smoke-test-linux (24) (push) Has been cancelled
CLI Smoke Test / smoke-test-windows (20) (push) Has been cancelled
CLI Smoke Test / smoke-test-windows (24) (push) Has been cancelled
Expo App TypeScript typecheck / typecheck (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:40:49 +08:00

138 行
4.7 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from 'vitest';
const { machineRPC, refreshSessions } = vi.hoisted(() => ({
machineRPC: vi.fn(),
refreshSessions: vi.fn(),
}));
vi.mock('./apiSocket', () => ({
apiSocket: { machineRPC },
}));
vi.mock('./sync', () => ({
sync: { refreshSessions },
}));
// ops.ts imports storage (for sessionSetAgentModes), which transitively pulls
// in react-native — mock it out, these tests never touch it.
vi.mock('./storage', () => ({
storage: { getState: vi.fn(() => ({ sessions: {} })) },
}));
describe('codex fork ops', () => {
beforeEach(() => {
machineRPC.mockReset();
refreshSessions.mockReset();
});
it('passes new-session mode defaults through spawn RPC', async () => {
machineRPC.mockResolvedValue({ type: 'success', sessionId: 'happy-new' });
const { machineSpawnNewSession } = await import('./ops');
const result = await machineSpawnNewSession({
machineId: 'machine-1',
directory: '/tmp/project',
agent: 'claude',
permissionMode: 'bypassPermissions',
modelMode: 'opus',
effortLevel: 'xhigh',
});
expect(result).toEqual({ type: 'success', sessionId: 'happy-new' });
expect(machineRPC).toHaveBeenCalledWith(
'machine-1',
'spawn-happy-session',
expect.objectContaining({
directory: '/tmp/project',
agent: 'claude',
permissionMode: 'bypassPermissions',
modelMode: 'opus',
effortLevel: 'xhigh',
}),
);
});
it('forks a full Codex thread and spawns a Codex session resumed to the new thread', async () => {
machineRPC.mockImplementation(async (_machineId: string, method: string) => {
if (method === 'codex-fork-thread') {
return { type: 'success', newCodexThreadId: 'thread-forked' };
}
if (method === 'spawn-happy-session') {
return { type: 'success', sessionId: 'happy-forked' };
}
throw new Error(`unexpected method ${method}`);
});
const { forkAndSpawn } = await import('./ops');
const result = await forkAndSpawn({
kind: 'codex',
sessionId: 'happy-source',
machineId: 'machine-1',
directory: '/tmp/project',
codexThreadId: 'thread-source',
});
expect(result).toEqual({ type: 'success', sessionId: 'happy-forked' });
expect(machineRPC).toHaveBeenNthCalledWith(
1,
'machine-1',
'codex-fork-thread',
{ directory: '/tmp/project', codexThreadId: 'thread-source' },
);
expect(machineRPC).toHaveBeenNthCalledWith(
2,
'machine-1',
'spawn-happy-session',
expect.objectContaining({
agent: 'codex',
directory: '/tmp/project',
resumeCodexThreadId: 'thread-forked',
parentSessionId: 'happy-source',
}),
);
expect(refreshSessions).toHaveBeenCalledTimes(1);
});
it('duplicates a Codex thread from a selected user item before spawning', async () => {
machineRPC.mockImplementation(async (_machineId: string, method: string) => {
if (method === 'codex-duplicate-thread') {
return { type: 'success', newCodexThreadId: 'thread-cut' };
}
if (method === 'spawn-happy-session') {
return { type: 'success', sessionId: 'happy-cut' };
}
throw new Error(`unexpected method ${method}`);
});
const { forkAndSpawn } = await import('./ops');
const result = await forkAndSpawn({
kind: 'codex',
sessionId: 'happy-source',
machineId: 'machine-1',
directory: '/tmp/project',
codexThreadId: 'thread-source',
}, {
cutAfterItemId: 'user-item-2',
forkedFromMessageId: 'message-2',
});
expect(result).toEqual({ type: 'success', sessionId: 'happy-cut' });
expect(machineRPC).toHaveBeenNthCalledWith(
1,
'machine-1',
'codex-duplicate-thread',
{ directory: '/tmp/project', codexThreadId: 'thread-source', cutAfterItemId: 'user-item-2' },
);
expect(machineRPC).toHaveBeenNthCalledWith(
2,
'machine-1',
'spawn-happy-session',
expect.objectContaining({
agent: 'codex',
resumeCodexThreadId: 'thread-cut',
forkedFromMessageId: 'message-2',
}),
);
});
});