f8c82902a5
- Config-driven gates via .codegov.yml/.codegov.json - disclosure gate: requires AI-GENERATED/AI-ASSISTED markers on changed files - rfc gate: requires issue/RFC reference in commit message or PR description - checklist gate: requires all items checked in REQUIREMENTS.md - quality gate: runs configurable lint/test/typecheck commands - CLI with readable reports and non-zero exit on violations - 41 tests covering all gates, config loading, and integration - Zero skeletons, no fake features, deferred items honestly documented
76 lines
2.2 KiB
TypeScript
76 lines
2.2 KiB
TypeScript
import { describe, it, expect, vi } from 'vitest';
|
|
import { execSync } from 'child_process';
|
|
import { getChangedFiles, getCommitMessage, getPrDescription } from '../src/git';
|
|
|
|
vi.mock('child_process', () => ({
|
|
execSync: vi.fn(),
|
|
}));
|
|
|
|
describe('git', () => {
|
|
beforeEach(() => {
|
|
vi.resetAllMocks();
|
|
});
|
|
|
|
it('returns changed files from git diff', () => {
|
|
vi.mocked(execSync).mockReturnValue('src/a.ts\nsrc/b.ts\n');
|
|
const files = getChangedFiles();
|
|
expect(files).toEqual(['src/a.ts', 'src/b.ts']);
|
|
});
|
|
|
|
it('returns empty array when no changes', () => {
|
|
vi.mocked(execSync).mockReturnValue('');
|
|
const files = getChangedFiles();
|
|
expect(files).toEqual([]);
|
|
});
|
|
|
|
it('uses fromRef and toRef when provided', () => {
|
|
vi.mocked(execSync).mockReturnValue('file.ts');
|
|
getChangedFiles('main', 'HEAD');
|
|
expect(vi.mocked(execSync)).toHaveBeenCalledWith(
|
|
'git diff --name-only --diff-filter=ACM main...HEAD',
|
|
expect.any(Object)
|
|
);
|
|
});
|
|
|
|
it('throws on invalid git ref', () => {
|
|
vi.mocked(execSync).mockImplementation(() => {
|
|
const err = new Error('fatal: bad revision');
|
|
throw err;
|
|
});
|
|
expect(() => getChangedFiles('bad-ref')).toThrow('Invalid git ref');
|
|
});
|
|
|
|
it('throws when not a git repo', () => {
|
|
vi.mocked(execSync).mockImplementation(() => {
|
|
const err = new Error('fatal: not a git repository');
|
|
throw err;
|
|
});
|
|
expect(() => getChangedFiles()).toThrow('Not a git repository');
|
|
});
|
|
|
|
it('returns commit message', () => {
|
|
vi.mocked(execSync).mockReturnValue('feat: add thing\n');
|
|
expect(getCommitMessage()).toBe('feat: add thing');
|
|
});
|
|
|
|
it('returns empty string when commit message fails', () => {
|
|
vi.mocked(execSync).mockImplementation(() => {
|
|
throw new Error('fail');
|
|
});
|
|
expect(getCommitMessage()).toBe('');
|
|
});
|
|
|
|
it('reads PR description from env', () => {
|
|
process.env.GITHUB_EVENT_PATH = 'pr-desc';
|
|
expect(getPrDescription()).toBe('pr-desc');
|
|
delete process.env.GITHUB_EVENT_PATH;
|
|
});
|
|
|
|
it('returns empty string when no PR env', () => {
|
|
delete process.env.GITHUB_EVENT_PATH;
|
|
delete process.env.CI_MERGE_REQUEST_DESCRIPTION;
|
|
delete process.env.BITBUCKET_PR_DESCRIPTION;
|
|
expect(getPrDescription()).toBe('');
|
|
});
|
|
});
|