Files
gh-codeql-report/src/__tests__/git.test.ts
2025-09-30 22:34:56 +03:00

149 lines
4.9 KiB
TypeScript

import type { SimpleGit } from 'simple-git';
import simpleGit from 'simple-git';
import { describe, expect, it, vi } from 'vitest';
import { getGitHubRepoFromRemote, parseGitHubUrl } from '../lib/git.js';
vi.mock('simple-git');
describe('parseGitHubUrl', () => {
it('should parse HTTPS URL', () => {
const result = parseGitHubUrl('https://github.com/owner/repo.git');
expect(result).toEqual({ owner: 'owner', repo: 'repo' });
});
it('should parse HTTPS URL without .git', () => {
const result = parseGitHubUrl('https://github.com/owner/repo');
expect(result).toEqual({ owner: 'owner', repo: 'repo' });
});
it('should parse SSH URL', () => {
const result = parseGitHubUrl('git@github.com:owner/repo.git');
expect(result).toEqual({ owner: 'owner', repo: 'repo' });
});
it('should parse git:// URL', () => {
const result = parseGitHubUrl('git://github.com/owner/repo.git');
expect(result).toEqual({ owner: 'owner', repo: 'repo' });
});
it('should return null for invalid URL', () => {
const result = parseGitHubUrl('not-a-valid-url');
expect(result).toBeNull();
});
it('should handle URLs with hyphens and underscores', () => {
const result = parseGitHubUrl('https://github.com/my-org_name/my-repo_name.git');
expect(result).toEqual({ owner: 'my-org_name', repo: 'my-repo_name' });
});
});
describe('getGitHubRepoFromRemote', () => {
it('should extract repo from origin remote', async () => {
const mockGit = {
getRemotes: vi
.fn()
.mockResolvedValue([
{ name: 'origin', refs: { fetch: 'https://github.com/owner/repo.git', push: '' } },
]),
};
vi.mocked(simpleGit).mockReturnValue(mockGit as unknown as SimpleGit);
const result = await getGitHubRepoFromRemote();
expect(result).toEqual({ owner: 'owner', repo: 'repo' });
expect(mockGit.getRemotes).toHaveBeenCalledWith(true);
});
it('should use first remote if origin not found', async () => {
const mockGit = {
getRemotes: vi
.fn()
.mockResolvedValue([
{ name: 'upstream', refs: { fetch: 'https://github.com/other/repo.git', push: '' } },
]),
};
vi.mocked(simpleGit).mockReturnValue(mockGit as unknown as SimpleGit);
const result = await getGitHubRepoFromRemote();
expect(result).toEqual({ owner: 'other', repo: 'repo' });
});
it('should use push URL if fetch URL not available', async () => {
const mockGit = {
getRemotes: vi
.fn()
.mockResolvedValue([
{ name: 'origin', refs: { fetch: '', push: 'git@github.com:owner/repo.git' } },
]),
};
vi.mocked(simpleGit).mockReturnValue(mockGit as unknown as SimpleGit);
const result = await getGitHubRepoFromRemote();
expect(result).toEqual({ owner: 'owner', repo: 'repo' });
});
it('should throw error if no remotes found', async () => {
const mockGit = {
getRemotes: vi.fn().mockResolvedValue([]),
};
vi.mocked(simpleGit).mockReturnValue(mockGit as unknown as SimpleGit);
await expect(getGitHubRepoFromRemote()).rejects.toThrow('No git remotes found');
});
it('should throw error if remote has no valid URL', async () => {
const mockGit = {
getRemotes: vi.fn().mockResolvedValue([{ name: 'origin', refs: { fetch: '', push: '' } }]),
};
vi.mocked(simpleGit).mockReturnValue(mockGit as unknown as SimpleGit);
await expect(getGitHubRepoFromRemote()).rejects.toThrow('No valid remote URL found');
});
it('should throw error if URL cannot be parsed', async () => {
const mockGit = {
getRemotes: vi
.fn()
.mockResolvedValue([{ name: 'origin', refs: { fetch: 'not-a-github-url', push: '' } }]),
};
vi.mocked(simpleGit).mockReturnValue(mockGit as unknown as SimpleGit);
await expect(getGitHubRepoFromRemote()).rejects.toThrow('Unable to parse GitHub repository');
});
it('should handle git errors', async () => {
const mockGit = {
getRemotes: vi.fn().mockRejectedValue(new Error('Git error')),
};
vi.mocked(simpleGit).mockReturnValue(mockGit as unknown as SimpleGit);
await expect(getGitHubRepoFromRemote()).rejects.toThrow('Git error');
});
it('should handle non-Error exceptions', async () => {
const mockGit = {
getRemotes: vi.fn().mockRejectedValue('string error'),
};
vi.mocked(simpleGit).mockReturnValue(mockGit as unknown as SimpleGit);
await expect(getGitHubRepoFromRemote()).rejects.toThrow('Failed to get git remote information');
});
it('should pass cwd parameter to simpleGit', async () => {
const mockGit = {
getRemotes: vi
.fn()
.mockResolvedValue([
{ name: 'origin', refs: { fetch: 'https://github.com/owner/repo.git', push: '' } },
]),
};
vi.mocked(simpleGit).mockReturnValue(mockGit as unknown as SimpleGit);
await getGitHubRepoFromRemote('/custom/path');
expect(simpleGit).toHaveBeenCalledWith('/custom/path');
});
});