mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-03-20 23:13:07 +00:00
feat: Add GPT-5 model variants and improve Codex execution logic. Addressed code review comments
This commit is contained in:
@@ -1,27 +1,15 @@
|
||||
import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest';
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import type { Request, Response } from 'express';
|
||||
import { createMockExpressContext } from '../../../utils/mocks.js';
|
||||
|
||||
vi.mock('child_process', async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import('child_process')>();
|
||||
return {
|
||||
...actual,
|
||||
execFile: vi.fn(),
|
||||
};
|
||||
});
|
||||
vi.mock('@/services/worktree-branch-service.js', () => ({
|
||||
performSwitchBranch: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('util', async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import('util')>();
|
||||
return {
|
||||
...actual,
|
||||
promisify: (fn: unknown) => fn,
|
||||
};
|
||||
});
|
||||
|
||||
import { execFile } from 'child_process';
|
||||
import { performSwitchBranch } from '@/services/worktree-branch-service.js';
|
||||
import { createSwitchBranchHandler } from '@/routes/worktree/routes/switch-branch.js';
|
||||
|
||||
const mockExecFile = execFile as Mock;
|
||||
const mockPerformSwitchBranch = vi.mocked(performSwitchBranch);
|
||||
|
||||
describe('switch-branch route', () => {
|
||||
let req: Request;
|
||||
@@ -34,42 +22,77 @@ describe('switch-branch route', () => {
|
||||
res = context.res;
|
||||
});
|
||||
|
||||
it('should return 400 when branchName is missing', async () => {
|
||||
req.body = { worktreePath: '/repo/path' };
|
||||
|
||||
const handler = createSwitchBranchHandler();
|
||||
await handler(req, res);
|
||||
|
||||
expect(res.status).toHaveBeenCalledWith(400);
|
||||
expect(res.json).toHaveBeenCalledWith({
|
||||
success: false,
|
||||
error: 'branchName required',
|
||||
});
|
||||
expect(mockPerformSwitchBranch).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should return 400 when branchName starts with a dash', async () => {
|
||||
req.body = { worktreePath: '/repo/path', branchName: '-flag' };
|
||||
|
||||
const handler = createSwitchBranchHandler();
|
||||
await handler(req, res);
|
||||
|
||||
expect(res.status).toHaveBeenCalledWith(400);
|
||||
expect(res.json).toHaveBeenCalledWith({
|
||||
success: false,
|
||||
error: 'Invalid branch name',
|
||||
});
|
||||
expect(mockPerformSwitchBranch).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should return 400 when branchName starts with double dash', async () => {
|
||||
req.body = { worktreePath: '/repo/path', branchName: '--option' };
|
||||
|
||||
const handler = createSwitchBranchHandler();
|
||||
await handler(req, res);
|
||||
|
||||
expect(res.status).toHaveBeenCalledWith(400);
|
||||
expect(res.json).toHaveBeenCalledWith({
|
||||
success: false,
|
||||
error: 'Invalid branch name',
|
||||
});
|
||||
expect(mockPerformSwitchBranch).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should return 400 when branchName contains invalid characters', async () => {
|
||||
req.body = { worktreePath: '/repo/path', branchName: 'branch name with spaces' };
|
||||
|
||||
const handler = createSwitchBranchHandler();
|
||||
await handler(req, res);
|
||||
|
||||
expect(res.status).toHaveBeenCalledWith(400);
|
||||
expect(res.json).toHaveBeenCalledWith({
|
||||
success: false,
|
||||
error: 'Invalid branch name',
|
||||
});
|
||||
expect(mockPerformSwitchBranch).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should allow switching when only untracked files exist', async () => {
|
||||
req.body = {
|
||||
worktreePath: '/repo/path',
|
||||
branchName: 'feature/test',
|
||||
};
|
||||
|
||||
mockExecFile.mockImplementation(async (file: string, args: string[]) => {
|
||||
const command = `${file} ${args.join(' ')}`;
|
||||
if (command === 'git rev-parse --abbrev-ref HEAD') {
|
||||
return { stdout: 'main\n', stderr: '' };
|
||||
}
|
||||
if (command === 'git rev-parse --verify feature/test') {
|
||||
return { stdout: 'abc123\n', stderr: '' };
|
||||
}
|
||||
if (command === 'git branch -r --format=%(refname:short)') {
|
||||
return { stdout: '', stderr: '' };
|
||||
}
|
||||
if (command === 'git status --porcelain') {
|
||||
return { stdout: '?? .automaker/\n?? notes.txt\n', stderr: '' };
|
||||
}
|
||||
if (command === 'git checkout feature/test') {
|
||||
return { stdout: '', stderr: '' };
|
||||
}
|
||||
if (command === 'git fetch --all --quiet') {
|
||||
return { stdout: '', stderr: '' };
|
||||
}
|
||||
if (command === 'git stash list') {
|
||||
return { stdout: '', stderr: '' };
|
||||
}
|
||||
if (command.startsWith('git stash push')) {
|
||||
return { stdout: '', stderr: '' };
|
||||
}
|
||||
if (command === 'git stash pop') {
|
||||
return { stdout: '', stderr: '' };
|
||||
}
|
||||
return { stdout: '', stderr: '' };
|
||||
mockPerformSwitchBranch.mockResolvedValue({
|
||||
success: true,
|
||||
result: {
|
||||
previousBranch: 'main',
|
||||
currentBranch: 'feature/test',
|
||||
message: "Switched to branch 'feature/test'",
|
||||
hasConflicts: false,
|
||||
stashedChanges: false,
|
||||
},
|
||||
});
|
||||
|
||||
const handler = createSwitchBranchHandler();
|
||||
@@ -85,11 +108,7 @@ describe('switch-branch route', () => {
|
||||
stashedChanges: false,
|
||||
},
|
||||
});
|
||||
expect(mockExecFile).toHaveBeenCalledWith(
|
||||
'git',
|
||||
['checkout', 'feature/test'],
|
||||
expect.objectContaining({ cwd: '/repo/path' })
|
||||
);
|
||||
expect(mockPerformSwitchBranch).toHaveBeenCalledWith('/repo/path', 'feature/test', undefined);
|
||||
});
|
||||
|
||||
it('should stash changes and switch when tracked files are modified', async () => {
|
||||
@@ -98,42 +117,15 @@ describe('switch-branch route', () => {
|
||||
branchName: 'feature/test',
|
||||
};
|
||||
|
||||
let stashListCallCount = 0;
|
||||
|
||||
mockExecFile.mockImplementation(async (file: string, args: string[]) => {
|
||||
const command = `${file} ${args.join(' ')}`;
|
||||
if (command === 'git rev-parse --abbrev-ref HEAD') {
|
||||
return { stdout: 'main\n', stderr: '' };
|
||||
}
|
||||
if (command === 'git rev-parse --verify feature/test') {
|
||||
return { stdout: 'abc123\n', stderr: '' };
|
||||
}
|
||||
if (command === 'git status --porcelain') {
|
||||
return { stdout: ' M src/index.ts\n?? notes.txt\n', stderr: '' };
|
||||
}
|
||||
if (command === 'git branch -r --format=%(refname:short)') {
|
||||
return { stdout: '', stderr: '' };
|
||||
}
|
||||
if (command === 'git stash list') {
|
||||
stashListCallCount++;
|
||||
if (stashListCallCount === 1) {
|
||||
return { stdout: '', stderr: '' };
|
||||
}
|
||||
return { stdout: 'stash@{0}: automaker-branch-switch\n', stderr: '' };
|
||||
}
|
||||
if (command.startsWith('git stash push')) {
|
||||
return { stdout: '', stderr: '' };
|
||||
}
|
||||
if (command === 'git checkout feature/test') {
|
||||
return { stdout: '', stderr: '' };
|
||||
}
|
||||
if (command === 'git fetch --all --quiet') {
|
||||
return { stdout: '', stderr: '' };
|
||||
}
|
||||
if (command === 'git stash pop') {
|
||||
return { stdout: 'Already applied.\n', stderr: '' };
|
||||
}
|
||||
return { stdout: '', stderr: '' };
|
||||
mockPerformSwitchBranch.mockResolvedValue({
|
||||
success: true,
|
||||
result: {
|
||||
previousBranch: 'main',
|
||||
currentBranch: 'feature/test',
|
||||
message: "Switched to branch 'feature/test' (local changes stashed and reapplied)",
|
||||
hasConflicts: false,
|
||||
stashedChanges: true,
|
||||
},
|
||||
});
|
||||
|
||||
const handler = createSwitchBranchHandler();
|
||||
|
||||
Reference in New Issue
Block a user