エージェントが c89ac4c で追加した force-add により、worktree 実行時に .takt/reports/ がコミットに含まれてしまう問題を修正。 .takt/ は .gitignore で除外済みのため force-add は不要。
157 lines
4.5 KiB
TypeScript
157 lines
4.5 KiB
TypeScript
/**
|
|
* Tests for autoCommitAndPush
|
|
*/
|
|
|
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
import { autoCommitAndPush } from '../infra/task/autoCommit.js';
|
|
|
|
// Mock child_process.execFileSync
|
|
vi.mock('node:child_process', () => ({
|
|
execFileSync: vi.fn(),
|
|
}));
|
|
|
|
import { execFileSync } from 'node:child_process';
|
|
const mockExecFileSync = vi.mocked(execFileSync);
|
|
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
describe('autoCommitAndPush', () => {
|
|
it('should create a commit and push when there are changes', () => {
|
|
mockExecFileSync.mockImplementation((cmd, args) => {
|
|
const argsArr = args as string[];
|
|
if (argsArr[0] === 'status') {
|
|
return 'M src/index.ts\n';
|
|
}
|
|
if (argsArr[0] === 'rev-parse') {
|
|
return 'abc1234\n';
|
|
}
|
|
return Buffer.from('');
|
|
});
|
|
|
|
const result = autoCommitAndPush('/tmp/clone', 'my-task', '/project');
|
|
|
|
expect(result.success).toBe(true);
|
|
expect(result.commitHash).toBe('abc1234');
|
|
expect(result.message).toContain('abc1234');
|
|
|
|
// Verify git add -A was called
|
|
expect(mockExecFileSync).toHaveBeenCalledWith(
|
|
'git',
|
|
['add', '-A'],
|
|
expect.objectContaining({ cwd: '/tmp/clone' })
|
|
);
|
|
|
|
// Verify commit was called with correct message (no co-author)
|
|
expect(mockExecFileSync).toHaveBeenCalledWith(
|
|
'git',
|
|
['commit', '-m', 'takt: my-task'],
|
|
expect.objectContaining({ cwd: '/tmp/clone' })
|
|
);
|
|
|
|
// Verify push was called with projectDir directly (no origin remote)
|
|
expect(mockExecFileSync).toHaveBeenCalledWith(
|
|
'git',
|
|
['push', '/project', 'HEAD'],
|
|
expect.objectContaining({ cwd: '/tmp/clone' })
|
|
);
|
|
});
|
|
|
|
it('should return success with no commit when there are no changes', () => {
|
|
mockExecFileSync.mockImplementation((cmd, args) => {
|
|
const argsArr = args as string[];
|
|
if (argsArr[0] === 'status') {
|
|
return ''; // No changes
|
|
}
|
|
return Buffer.from('');
|
|
});
|
|
|
|
const result = autoCommitAndPush('/tmp/clone', 'my-task', '/project');
|
|
|
|
expect(result.success).toBe(true);
|
|
expect(result.commitHash).toBeUndefined();
|
|
expect(result.message).toBe('No changes to commit');
|
|
|
|
// Verify git add -A was called
|
|
expect(mockExecFileSync).toHaveBeenCalledWith(
|
|
'git',
|
|
['add', '-A'],
|
|
expect.objectContaining({ cwd: '/tmp/clone' })
|
|
);
|
|
|
|
// Verify commit was NOT called
|
|
expect(mockExecFileSync).not.toHaveBeenCalledWith(
|
|
'git',
|
|
['commit', '-m', expect.any(String)],
|
|
expect.anything()
|
|
);
|
|
|
|
// Verify push was NOT called
|
|
expect(mockExecFileSync).not.toHaveBeenCalledWith(
|
|
'git',
|
|
['push', '/project', 'HEAD'],
|
|
expect.anything()
|
|
);
|
|
});
|
|
|
|
it('should return failure when git command fails', () => {
|
|
mockExecFileSync.mockImplementation(() => {
|
|
throw new Error('git error: not a git repository');
|
|
});
|
|
|
|
const result = autoCommitAndPush('/tmp/clone', 'my-task', '/project');
|
|
|
|
expect(result.success).toBe(false);
|
|
expect(result.commitHash).toBeUndefined();
|
|
expect(result.message).toContain('Auto-commit failed');
|
|
expect(result.message).toContain('not a git repository');
|
|
});
|
|
|
|
it('should not include co-author in commit message', () => {
|
|
mockExecFileSync.mockImplementation((cmd, args) => {
|
|
const argsArr = args as string[];
|
|
if (argsArr[0] === 'status') {
|
|
return 'M file.ts\n';
|
|
}
|
|
if (argsArr[0] === 'rev-parse') {
|
|
return 'def5678\n';
|
|
}
|
|
return Buffer.from('');
|
|
});
|
|
|
|
autoCommitAndPush('/tmp/clone', 'test-task', '/project');
|
|
|
|
// Find the commit call
|
|
const commitCall = mockExecFileSync.mock.calls.find(
|
|
call => (call[1] as string[])[0] === 'commit'
|
|
);
|
|
|
|
expect(commitCall).toBeDefined();
|
|
const commitMessage = (commitCall![1] as string[])[2];
|
|
expect(commitMessage).toBe('takt: test-task');
|
|
expect(commitMessage).not.toContain('Co-Authored-By');
|
|
});
|
|
|
|
it('should use the correct commit message format', () => {
|
|
mockExecFileSync.mockImplementation((cmd, args) => {
|
|
const argsArr = args as string[];
|
|
if (argsArr[0] === 'status') {
|
|
return 'A new-file.ts\n';
|
|
}
|
|
if (argsArr[0] === 'rev-parse') {
|
|
return 'aaa1111\n';
|
|
}
|
|
return Buffer.from('');
|
|
});
|
|
|
|
autoCommitAndPush('/tmp/clone', '認証機能を追加する', '/project');
|
|
|
|
const commitCall = mockExecFileSync.mock.calls.find(
|
|
call => (call[1] as string[])[0] === 'commit'
|
|
);
|
|
expect((commitCall![1] as string[])[2]).toBe('takt: 認証機能を追加する');
|
|
});
|
|
|
|
});
|