719032b19f
Update Schema / Update configuration json schema (push) Has been cancelled
Memory Benchmark / Memory Test (Full Analysis) (push) Has been cancelled
CI Quality / Lint GitHub Actions (actionlint) (push) Has been cancelled
CI Quality / Lint GitHub Actions (zizmor) (push) Has been cancelled
CI Quality / Check typos (push) Has been cancelled
CI / Test coverage (push) Has been cancelled
CI / Test (22.x, windows-latest) (push) Has been cancelled
CI / Test (24.x, macos-latest) (push) Has been cancelled
CI / Test (24.x, ubuntu-latest) (push) Has been cancelled
CI / Test (24.x, windows-latest) (push) Has been cancelled
CI / Test (26.x, macos-latest) (push) Has been cancelled
CI / Test (26.x, ubuntu-latest) (push) Has been cancelled
CI / Test (26.x, windows-latest) (push) Has been cancelled
CI / Test with Bun (latest, macos-latest) (push) Has been cancelled
CI / Test with Bun (latest, ubuntu-latest) (push) Has been cancelled
CI / Test with Bun (latest, windows-latest) (push) Has been cancelled
CI / Build and run (22.x, macos-latest) (push) Has been cancelled
CI / Build and run (22.x, ubuntu-latest) (push) Has been cancelled
CI / Build and run (22.x, windows-latest) (push) Has been cancelled
autofix.ci / autofix (push) Has been cancelled
CI Browser Extension / Lint Browser Extension (push) Has been cancelled
CI Browser Extension / Test Browser Extension (push) Has been cancelled
Memory Benchmark / Memory Test (push) Has been cancelled
CI Website / Lint Website Client (push) Has been cancelled
CI Website / Lint Website Server (push) Has been cancelled
CI Website / Test Website Server (push) Has been cancelled
CI Website / Bundle Website Server (push) Has been cancelled
CI / Lint Biome (push) Has been cancelled
CI / Lint oxlint (push) Has been cancelled
CI / Lint TypeScript (push) Has been cancelled
CI / Lint Secretlint (push) Has been cancelled
CI / Test (22.x, macos-latest) (push) Has been cancelled
CI / Test (22.x, ubuntu-latest) (push) Has been cancelled
CI / Build and run (24.x, macos-latest) (push) Has been cancelled
CI / Build and run (24.x, ubuntu-latest) (push) Has been cancelled
CI / Build and run (24.x, windows-latest) (push) Has been cancelled
CI / Build and run (26.x, macos-latest) (push) Has been cancelled
CI / Build and run (26.x, ubuntu-latest) (push) Has been cancelled
CI / Build and run (26.x, windows-latest) (push) Has been cancelled
CI / Build and run with Bun (latest, macos-latest) (push) Has been cancelled
CI / Build and run with Bun (latest, ubuntu-latest) (push) Has been cancelled
CI / Build and run with Bun (latest, windows-latest) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Docker / build (linux/amd64, ubuntu-latest) (push) Has been cancelled
Docker / build (linux/arm/v7, ubuntu-24.04-arm) (push) Has been cancelled
Docker / build (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Docker / merge (push) Has been cancelled
Pack repository with Repomix / pack-repo (push) Has been cancelled
Performance Benchmark History / Benchmark (macos-latest) (push) Has been cancelled
Performance Benchmark History / Benchmark (ubuntu-latest) (push) Has been cancelled
Performance Benchmark History / Benchmark (windows-latest) (push) Has been cancelled
Performance Benchmark History / Store Results (push) Has been cancelled
Test Repomix Action / Test Node.js 22 (push) Has been cancelled
Test Repomix Action / Test Node.js 24 (push) Has been cancelled
Test Repomix Action / Test Node.js 26 (push) Has been cancelled
127 lines
4.9 KiB
TypeScript
127 lines
4.9 KiB
TypeScript
import { beforeEach, describe, expect, test, vi } from 'vitest';
|
|
import { checkRemoteRepoExists, getRemoteRefs } from '../../../src/core/git/gitRemoteHandle.js';
|
|
import { logger } from '../../../src/shared/logger.js';
|
|
|
|
vi.mock('../../../src/shared/logger');
|
|
|
|
describe('gitRemoteHandle', () => {
|
|
beforeEach(() => {
|
|
vi.resetAllMocks();
|
|
});
|
|
|
|
describe('checkRemoteRepoExists', () => {
|
|
test('should return true when the repository is reachable', async () => {
|
|
const mockExecLsRemoteHead = vi.fn().mockResolvedValue('a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6\tHEAD');
|
|
|
|
const result = await checkRemoteRepoExists('https://github.com/user/repo.git', {
|
|
execLsRemoteHead: mockExecLsRemoteHead,
|
|
});
|
|
|
|
expect(result).toBe(true);
|
|
expect(mockExecLsRemoteHead).toHaveBeenCalledWith('https://github.com/user/repo.git');
|
|
});
|
|
|
|
test('should return false when the repository is not reachable', async () => {
|
|
const mockExecLsRemoteHead = vi.fn().mockRejectedValue(new Error('Repository not found'));
|
|
|
|
const result = await checkRemoteRepoExists('https://github.com/user/nonexistent.git', {
|
|
execLsRemoteHead: mockExecLsRemoteHead,
|
|
});
|
|
|
|
expect(result).toBe(false);
|
|
expect(logger.trace).toHaveBeenCalledWith(
|
|
'Remote repository not reachable: https://github.com/user/nonexistent.git:',
|
|
'Repository not found',
|
|
);
|
|
});
|
|
|
|
test('should reject dangerous URLs before probing', async () => {
|
|
const mockExecLsRemoteHead = vi.fn();
|
|
|
|
await expect(
|
|
checkRemoteRepoExists('https://github.com/user/repo.git --upload-pack=evil-command', {
|
|
execLsRemoteHead: mockExecLsRemoteHead,
|
|
}),
|
|
).rejects.toThrow('Invalid repository URL. URL contains potentially dangerous parameters');
|
|
expect(mockExecLsRemoteHead).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('getRemoteRefs', () => {
|
|
test('should return refs when URL is valid', async () => {
|
|
const mockOutput = `
|
|
a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6 refs/heads/main
|
|
b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7 refs/heads/develop
|
|
c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8 refs/tags/v1.0.0
|
|
`.trim();
|
|
const mockExecLsRemote = vi.fn().mockResolvedValue(mockOutput);
|
|
|
|
const result = await getRemoteRefs('https://github.com/user/repo.git', {
|
|
execLsRemote: mockExecLsRemote,
|
|
});
|
|
|
|
expect(result).toEqual(['main', 'develop', 'v1.0.0']);
|
|
expect(mockExecLsRemote).toHaveBeenCalledWith('https://github.com/user/repo.git');
|
|
expect(logger.trace).toHaveBeenCalledWith('Found 3 refs in repository: https://github.com/user/repo.git');
|
|
});
|
|
|
|
test('should return empty array when no refs found', async () => {
|
|
const mockExecLsRemote = vi.fn().mockResolvedValue('');
|
|
|
|
const result = await getRemoteRefs('https://github.com/user/repo.git', {
|
|
execLsRemote: mockExecLsRemote,
|
|
});
|
|
|
|
expect(result).toEqual([]);
|
|
expect(mockExecLsRemote).toHaveBeenCalledWith('https://github.com/user/repo.git');
|
|
expect(logger.trace).toHaveBeenCalledWith('Found 0 refs in repository: https://github.com/user/repo.git');
|
|
});
|
|
|
|
test('should throw error when ls-remote fails', async () => {
|
|
const mockExecLsRemote = vi.fn().mockRejectedValue(new Error('Repository not found'));
|
|
|
|
await expect(
|
|
getRemoteRefs('https://github.com/user/nonexistent.git', {
|
|
execLsRemote: mockExecLsRemote,
|
|
}),
|
|
).rejects.toThrow('Failed to get remote refs: Repository not found');
|
|
|
|
expect(mockExecLsRemote).toHaveBeenCalledWith('https://github.com/user/nonexistent.git');
|
|
expect(logger.trace).toHaveBeenCalledWith('Failed to get remote refs:', 'Repository not found');
|
|
});
|
|
|
|
test('should handle malformed output lines', async () => {
|
|
const mockOutput = `
|
|
a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6 refs/heads/main
|
|
invalid-line-without-tab
|
|
b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7 refs/heads/develop
|
|
`.trim();
|
|
const mockExecLsRemote = vi.fn().mockResolvedValue(mockOutput);
|
|
|
|
const result = await getRemoteRefs('https://github.com/user/repo.git', {
|
|
execLsRemote: mockExecLsRemote,
|
|
});
|
|
|
|
expect(result).toEqual(['main', 'develop']);
|
|
expect(mockExecLsRemote).toHaveBeenCalledWith('https://github.com/user/repo.git');
|
|
expect(logger.trace).toHaveBeenCalledWith('Found 2 refs in repository: https://github.com/user/repo.git');
|
|
});
|
|
|
|
test('should throw error for invalid URL', async () => {
|
|
await expect(
|
|
getRemoteRefs('invalid-url', {
|
|
execLsRemote: vi.fn(),
|
|
}),
|
|
).rejects.toThrow('Invalid URL protocol');
|
|
});
|
|
|
|
test('should throw error for dangerous URL parameters', async () => {
|
|
await expect(
|
|
getRemoteRefs('https://github.com/user/repo.git --upload-pack=evil', {
|
|
execLsRemote: vi.fn(),
|
|
}),
|
|
).rejects.toThrow('Invalid repository URL. URL contains potentially dangerous parameters');
|
|
});
|
|
});
|
|
});
|