UNPKG

kwgit

Version:

A command-line utility to help with cleaning up git branches. This tool provides a safe and efficient way to manage your git branches, helping you keep your repository clean and organized.

133 lines (100 loc) 5.32 kB
import { staleCommand } from './stale.js'; import { vi, describe, it, expect, beforeEach } from 'vitest'; import * as gitService from '../services/gitService.js'; import * as prompts from '../utils/prompts.js'; const now = Math.floor(Date.now() / 1000); // current time in seconds describe('staleCommand', () => { beforeEach(() => { vi.resetAllMocks(); }); it('should skip deletion in dry-run mode', async () => { vi.spyOn(gitService, 'getLocalBranches').mockResolvedValue(['old-branch', 'recent-branch']); vi.spyOn(gitService, 'getLastCommitTimestamp').mockImplementation(branch => { if (branch === 'old-branch') return now - (60 * 86400); // 60 days ago if (branch === 'recent-branch') return now - (10 * 86400); // 10 days ago }); const deleteSpy = vi.spyOn(gitService, 'deleteBranch'); await staleCommand.handler({ days: 30, maxDays: 365, base: 'main', dryRun: true, force: false }); expect(deleteSpy).not.toHaveBeenCalled(); }); it('should delete stale branches with force', async () => { vi.spyOn(gitService, 'getLocalBranches').mockResolvedValue(['ancient']); vi.spyOn(gitService, 'getLastCommitTimestamp').mockResolvedValue(now - (120 * 86400)); const deleteSpy = vi.spyOn(gitService, 'deleteBranch').mockResolvedValue(); await staleCommand.handler({ days: 30, maxDays: 365, base: 'main', dryRun: false, force: true }); expect(deleteSpy).toHaveBeenCalledWith('ancient', true); }); it('should prompt before deleting if not forced', async () => { vi.spyOn(gitService, 'getLocalBranches').mockResolvedValue(['prompt-me']); vi.spyOn(gitService, 'getLastCommitTimestamp').mockResolvedValue(now - (90 * 86400)); vi.spyOn(prompts, 'confirmBranchDeletion').mockResolvedValue(true); const deleteSpy = vi.spyOn(gitService, 'deleteBranch').mockResolvedValue(); await staleCommand.handler({ days: 30, maxDays: 365, base: 'main', dryRun: false, force: false }); expect(deleteSpy).toHaveBeenCalledWith('prompt-me', true); }); it('should skip branches younger than "days"', async () => { vi.spyOn(gitService, 'getLocalBranches').mockResolvedValue(['young']); vi.spyOn(gitService, 'getLastCommitTimestamp').mockResolvedValue(now - (5 * 86400)); // 5 days old const deleteSpy = vi.spyOn(gitService, 'deleteBranch'); await staleCommand.handler({ days: 10, maxDays: 365, base: 'main', dryRun: false, force: true }); expect(deleteSpy).not.toHaveBeenCalled(); }); it('should skip branches older than "max-days"', async () => { vi.spyOn(gitService, 'getLocalBranches').mockResolvedValue(['ancient']); vi.spyOn(gitService, 'getLastCommitTimestamp').mockResolvedValue(now - (400 * 86400)); // 400 days const deleteSpy = vi.spyOn(gitService, 'deleteBranch'); await staleCommand.handler({ days: 30, maxDays: 365, base: 'main', dryRun: false, force: true }); expect(deleteSpy).not.toHaveBeenCalled(); }); it('should skip protected branches and only delete unprotected ones', async () => { process.env.KWGIT_PROTECTED_BRANCHES = 'main,staging'; vi.spyOn(gitService, 'getLocalBranches').mockResolvedValue(['main', 'staging', 'old-temp']); vi.spyOn(gitService, 'getLastCommitTimestamp').mockResolvedValue(now - (90 * 86400)); // 90 days ago const deleteSpy = vi.spyOn(gitService, 'deleteBranch').mockResolvedValue(); vi.spyOn(prompts, 'confirmBranchDeletion').mockResolvedValue(true); await staleCommand.handler({ days: 30, maxDays: 365, base: 'main', dryRun: false, force: false, remote: false, }); expect(deleteSpy).toHaveBeenCalledTimes(1); expect(deleteSpy).toHaveBeenCalledWith('old-temp', true); }); }); it('should delete remote branches if --remote is passed and remote branch exists', async () => { vi.spyOn(gitService, 'getLocalBranches').mockResolvedValue(['feature/x']); vi.spyOn(gitService, 'getLastCommitTimestamp').mockResolvedValue(now - (100 * 86400)); // 100 days ago vi.spyOn(prompts, 'confirmBranchDeletion').mockResolvedValue(true); vi.spyOn(gitService, 'remoteBranchExists').mockResolvedValue(true); const remoteDeleteSpy = vi.spyOn(gitService, 'deleteRemoteBranch').mockResolvedValue(); const localDeleteSpy = vi.spyOn(gitService, 'deleteBranch').mockResolvedValue(); await staleCommand.handler({ days: 30, maxDays: 365, base: 'main', dryRun: false, force: false, remote: true, }); expect(localDeleteSpy).toHaveBeenCalledWith('feature/x', true); expect(remoteDeleteSpy).toHaveBeenCalledWith('feature/x'); }); it('should skip remote deletion if remote branch does not exist', async () => { vi.spyOn(gitService, 'getLocalBranches').mockResolvedValue(['ghost']); vi.spyOn(gitService, 'getLastCommitTimestamp').mockResolvedValue(now - (80 * 86400)); vi.spyOn(gitService, 'remoteBranchExists').mockResolvedValue(false); vi.spyOn(gitService, 'deleteBranch').mockResolvedValue(); const remoteDeleteSpy = vi.spyOn(gitService, 'deleteRemoteBranch'); await staleCommand.handler({ days: 30, maxDays: 365, base: 'main', dryRun: false, force: true, remote: true, }); expect(remoteDeleteSpy).not.toHaveBeenCalled(); });