smart-git-push-tool.test.ts•9.45 kB
import { jest } from '@jest/globals';
// Mock child_process to prevent actual git commands during tests
const mockExecSync = jest.fn();
jest.unstable_mockModule('child_process', () => ({
execSync: mockExecSync,
}));
// Mock fs functions to prevent actual file system operations
const mockExistsSync = jest.fn();
const mockReadFileSync = jest.fn();
const mockStatSync = jest.fn();
jest.unstable_mockModule('fs', () => ({
existsSync: mockExistsSync,
readFileSync: mockReadFileSync,
statSync: mockStatSync,
}));
describe('Smart Git Push Tool', () => {
beforeEach(() => {
jest.clearAllMocks();
// Mock execSync to return successful git command outputs
mockExecSync.mockImplementation((command: string) => {
if (command.includes('git diff --cached --name-status')) {
return ''; // No staged files
}
if (command.includes('git commit')) {
return 'Commit successful';
}
if (command.includes('git push')) {
return 'Push successful';
}
return '';
});
// Mock file system operations
mockExistsSync.mockImplementation((path: string) => {
if (typeof path === 'string') {
if (path.includes('.git')) return true;
if (path.includes('package.json')) return true;
if (path.includes('.mcp-adr-cache')) return true;
}
return false;
});
mockReadFileSync.mockImplementation((path: string) => {
if (typeof path === 'string') {
if (path.includes('package.json')) {
return JSON.stringify({ name: 'test-project', version: '1.0.0' });
}
if (path.includes('.mcp-adr-cache')) {
return JSON.stringify({});
}
}
return '';
});
mockStatSync.mockReturnValue({ size: 1024 } as any);
});
describe('Module Loading', () => {
it('should import smart git push tool successfully', async () => {
const module = await import('../../src/tools/smart-git-push-tool.js');
expect(module).toBeDefined();
});
it('should export expected functions', async () => {
const module = await import('../../src/tools/smart-git-push-tool.js');
expect(module.smartGitPush).toBeDefined();
});
});
describe('Smart Git Push Functionality', () => {
it('should handle basic git push operations', async () => {
const { smartGitPush } = await import('../../src/tools/smart-git-push-tool.js');
const result = await smartGitPush({
projectPath: '/test/project',
branch: 'main',
commitMessage: 'Test commit',
});
expect(result).toHaveProperty('content');
expect(result.content).toHaveLength(1);
expect(result.content[0]).toHaveProperty('type', 'text');
});
it('should validate ADR compliance before push', async () => {
const { smartGitPush } = await import('../../src/tools/smart-git-push-tool.js');
const result = await smartGitPush({
projectPath: '/test/project',
validateAdrCompliance: true,
adrDirectory: 'docs/adrs',
});
expect(result.content[0].text).toContain('ADR');
});
it('should run pre-push validation checks', async () => {
const { smartGitPush } = await import('../../src/tools/smart-git-push-tool.js');
const result = await smartGitPush({
projectPath: '/test/project',
runPrePushChecks: true,
checksToRun: ['lint', 'test', 'build'],
});
expect(result.content[0].text).toContain('Status');
});
it('should handle force push scenarios safely', async () => {
const { smartGitPush } = await import('../../src/tools/smart-git-push-tool.js');
const result = await smartGitPush({
projectPath: '/test/project',
forcePush: true,
requireConfirmation: true,
});
expect(result.content[0].text).toContain('Status');
});
it('should integrate with memory rollback system', async () => {
const { smartGitPush } = await import('../../src/tools/smart-git-push-tool.js');
const result = await smartGitPush({
projectPath: '/test/project',
createRollbackPoint: true,
rollbackOnFailure: true,
});
expect(result.content[0].text).toContain('Status');
});
it('should handle multi-branch synchronization', async () => {
const { smartGitPush } = await import('../../src/tools/smart-git-push-tool.js');
const result = await smartGitPush({
projectPath: '/test/project',
syncBranches: ['main', 'develop', 'staging'],
strategy: 'merge',
});
expect(result).toHaveProperty('content');
});
it('should support conversation context', async () => {
const { smartGitPush } = await import('../../src/tools/smart-git-push-tool.js');
const conversationContext = {
previousTools: ['adr-suggestion'],
currentTool: 'smart-git-push',
recommendations: ['create-rollback'],
};
const result = await smartGitPush({
projectPath: '/test/project',
conversationContext,
});
expect(result).toHaveProperty('content');
});
});
describe('Integration with Bootstrap Validation', () => {
it('should validate deployment readiness before push', async () => {
const { smartGitPush } = await import('../../src/tools/smart-git-push-tool.js');
const result = await smartGitPush({
projectPath: '/test/project',
validateDeploymentReadiness: true,
environment: 'production',
});
expect(result.content[0].text).toContain('Status');
});
it('should handle cross-language project validation', async () => {
const { smartGitPush } = await import('../../src/tools/smart-git-push-tool.js');
const result = await smartGitPush({
projectPath: '/test/multilang-project',
languageValidation: true,
supportedLanguages: ['typescript', 'python', 'go'],
});
expect(result).toHaveProperty('content');
});
it('should generate language-specific validation commands', async () => {
const validationCommands = {
'package.json': ['npm test', 'npm run lint', 'npm run build'],
'requirements.txt': ['python -m pytest', 'flake8', 'mypy'],
'Cargo.toml': ['cargo test', 'cargo clippy', 'cargo build'],
'go.mod': ['go test', 'go vet', 'go build'],
'pom.xml': ['mvn test', 'mvn checkstyle:check', 'mvn compile'],
};
Object.entries(validationCommands).forEach(([_file, commands]) => {
expect(commands).toHaveLength(3);
expect(commands.every(cmd => cmd.length > 0)).toBe(true);
});
});
});
describe('Error Handling and Safety', () => {
it('should handle git repository validation errors', async () => {
const { smartGitPush } = await import('../../src/tools/smart-git-push-tool.js');
const result = await smartGitPush({
projectPath: '/not/a/git/repo',
validateRepository: true,
});
expect(result).toHaveProperty('content');
});
it('should prevent dangerous operations on protected branches', async () => {
const { smartGitPush } = await import('../../src/tools/smart-git-push-tool.js');
const result = await smartGitPush({
projectPath: '/test/project',
branch: 'main',
forcePush: true,
protectedBranches: ['main', 'master'],
});
expect(result.content[0].text).toContain('Status');
});
it('should handle network connectivity issues', async () => {
const { smartGitPush } = await import('../../src/tools/smart-git-push-tool.js');
const result = await smartGitPush({
projectPath: '/test/project',
checkConnectivity: true,
retryOnFailure: true,
});
expect(result).toHaveProperty('content');
});
it('should validate commit message formats', async () => {
const { smartGitPush } = await import('../../src/tools/smart-git-push-tool.js');
const result = await smartGitPush({
projectPath: '/test/project',
validateCommitMessage: true,
commitMessageFormat: 'conventional',
});
expect(result.content[0].text).toContain('Status');
});
});
describe('Performance and Optimization', () => {
it('should handle large repository operations efficiently', async () => {
const { smartGitPush } = await import('../../src/tools/smart-git-push-tool.js');
const result = await smartGitPush({
projectPath: '/test/large-repo',
optimizeForLargeRepo: true,
batchOperations: true,
});
expect(result).toHaveProperty('content');
});
it('should support parallel validation execution', async () => {
const { smartGitPush } = await import('../../src/tools/smart-git-push-tool.js');
const result = await smartGitPush({
projectPath: '/test/project',
parallelValidation: true,
maxConcurrency: 4,
});
expect(result).toHaveProperty('content');
});
it('should cache validation results for efficiency', async () => {
const { smartGitPush } = await import('../../src/tools/smart-git-push-tool.js');
const result = await smartGitPush({
projectPath: '/test/project',
useValidationCache: true,
cacheValidityDuration: 3600,
});
expect(result).toHaveProperty('content');
});
});
});