UNPKG

@tiberriver256/mcp-server-azure-devops

Version:

Azure DevOps reference server for the Model Context Protocol (MCP)

255 lines 10.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const feature_1 = require("./feature"); const GitInterfaces_1 = require("azure-devops-node-api/interfaces/GitInterfaces"); const errors_1 = require("../../../shared/errors"); // Unit tests should only focus on isolated logic // No real connections, HTTP requests, or dependencies describe('getRepositoryDetails unit', () => { // Mock repository data const mockRepository = { id: 'repo-id', name: 'test-repo', url: 'https://dev.azure.com/org/project/_apis/git/repositories/repo-id', project: { id: 'project-id', name: 'test-project', }, defaultBranch: 'refs/heads/main', size: 1024, remoteUrl: 'https://dev.azure.com/org/project/_git/test-repo', sshUrl: 'git@ssh.dev.azure.com:v3/org/project/test-repo', webUrl: 'https://dev.azure.com/org/project/_git/test-repo', }; // Mock branch stats data const mockBranchStats = [ { name: 'refs/heads/main', aheadCount: 0, behindCount: 0, isBaseVersion: true, commit: { commitId: 'commit-id', author: { name: 'Test User', email: 'test@example.com', date: new Date(), }, committer: { name: 'Test User', email: 'test@example.com', date: new Date(), }, comment: 'Test commit', }, }, ]; // Mock refs data const mockRefs = [ { name: 'refs/heads/main', objectId: 'commit-id', creator: { displayName: 'Test User', id: 'user-id', }, url: 'https://dev.azure.com/org/project/_apis/git/repositories/repo-id/refs/heads/main', }, ]; test('should return basic repository information when no additional options are specified', async () => { // Arrange const mockConnection = { getGitApi: jest.fn().mockImplementation(() => ({ getRepository: jest.fn().mockResolvedValue(mockRepository), })), }; // Act const result = await (0, feature_1.getRepositoryDetails)(mockConnection, { projectId: 'test-project', repositoryId: 'test-repo', }); // Assert expect(result).toBeDefined(); expect(result.repository).toEqual(mockRepository); expect(result.statistics).toBeUndefined(); expect(result.refs).toBeUndefined(); }); test('should include branch statistics when includeStatistics is true', async () => { // Arrange const mockConnection = { getGitApi: jest.fn().mockImplementation(() => ({ getRepository: jest.fn().mockResolvedValue(mockRepository), getBranches: jest.fn().mockResolvedValue(mockBranchStats), })), }; // Act const result = await (0, feature_1.getRepositoryDetails)(mockConnection, { projectId: 'test-project', repositoryId: 'test-repo', includeStatistics: true, }); // Assert expect(result).toBeDefined(); expect(result.repository).toEqual(mockRepository); expect(result.statistics).toBeDefined(); expect(result.statistics?.branches).toEqual(mockBranchStats); expect(result.refs).toBeUndefined(); }); test('should include refs when includeRefs is true', async () => { // Arrange const mockConnection = { getGitApi: jest.fn().mockImplementation(() => ({ getRepository: jest.fn().mockResolvedValue(mockRepository), getRefs: jest.fn().mockResolvedValue(mockRefs), })), }; // Act const result = await (0, feature_1.getRepositoryDetails)(mockConnection, { projectId: 'test-project', repositoryId: 'test-repo', includeRefs: true, }); // Assert expect(result).toBeDefined(); expect(result.repository).toEqual(mockRepository); expect(result.statistics).toBeUndefined(); expect(result.refs).toBeDefined(); expect(result.refs?.value).toEqual(mockRefs); expect(result.refs?.count).toBe(mockRefs.length); }); test('should include both statistics and refs when both options are true', async () => { // Arrange const mockConnection = { getGitApi: jest.fn().mockImplementation(() => ({ getRepository: jest.fn().mockResolvedValue(mockRepository), getBranches: jest.fn().mockResolvedValue(mockBranchStats), getRefs: jest.fn().mockResolvedValue(mockRefs), })), }; // Act const result = await (0, feature_1.getRepositoryDetails)(mockConnection, { projectId: 'test-project', repositoryId: 'test-repo', includeStatistics: true, includeRefs: true, }); // Assert expect(result).toBeDefined(); expect(result.repository).toEqual(mockRepository); expect(result.statistics).toBeDefined(); expect(result.statistics?.branches).toEqual(mockBranchStats); expect(result.refs).toBeDefined(); expect(result.refs?.value).toEqual(mockRefs); expect(result.refs?.count).toBe(mockRefs.length); }); test('should pass refFilter to getRefs when provided', async () => { // Arrange const getRefs = jest.fn().mockResolvedValue(mockRefs); const mockConnection = { getGitApi: jest.fn().mockImplementation(() => ({ getRepository: jest.fn().mockResolvedValue(mockRepository), getRefs, })), }; // Act await (0, feature_1.getRepositoryDetails)(mockConnection, { projectId: 'test-project', repositoryId: 'test-repo', includeRefs: true, refFilter: 'heads/', }); // Assert expect(getRefs).toHaveBeenCalledWith(mockRepository.id, 'test-project', 'heads/'); }); test('should pass branchName to getBranches when provided', async () => { // Arrange const getBranches = jest.fn().mockResolvedValue(mockBranchStats); const mockConnection = { getGitApi: jest.fn().mockImplementation(() => ({ getRepository: jest.fn().mockResolvedValue(mockRepository), getBranches, })), }; // Act await (0, feature_1.getRepositoryDetails)(mockConnection, { projectId: 'test-project', repositoryId: 'test-repo', includeStatistics: true, branchName: 'main', }); // Assert expect(getBranches).toHaveBeenCalledWith(mockRepository.id, 'test-project', { version: 'main', versionType: GitInterfaces_1.GitVersionType.Branch, }); }); test('should propagate resource not found errors', async () => { // Arrange const mockConnection = { getGitApi: jest.fn().mockImplementation(() => ({ getRepository: jest.fn().mockResolvedValue(null), // Simulate repository not found })), }; // Act & Assert await expect((0, feature_1.getRepositoryDetails)(mockConnection, { projectId: 'test-project', repositoryId: 'non-existent-repo', })).rejects.toThrow(errors_1.AzureDevOpsResourceNotFoundError); await expect((0, feature_1.getRepositoryDetails)(mockConnection, { projectId: 'test-project', repositoryId: 'non-existent-repo', })).rejects.toThrow("Repository 'non-existent-repo' not found in project 'test-project'"); }); test('should propagate custom errors when thrown internally', async () => { // Arrange const mockConnection = { getGitApi: jest.fn().mockImplementation(() => { throw new errors_1.AzureDevOpsError('Custom error'); }), }; // Act & Assert await expect((0, feature_1.getRepositoryDetails)(mockConnection, { projectId: 'test-project', repositoryId: 'test-repo', })).rejects.toThrow(errors_1.AzureDevOpsError); await expect((0, feature_1.getRepositoryDetails)(mockConnection, { projectId: 'test-project', repositoryId: 'test-repo', })).rejects.toThrow('Custom error'); }); test('should wrap unexpected errors in a friendly error message', async () => { // Arrange const mockConnection = { getGitApi: jest.fn().mockImplementation(() => { throw new Error('Unexpected error'); }), }; // Act & Assert await expect((0, feature_1.getRepositoryDetails)(mockConnection, { projectId: 'test-project', repositoryId: 'test-repo', })).rejects.toThrow('Failed to get repository details: Unexpected error'); }); test('should handle null refs gracefully', async () => { // Arrange const mockConnection = { getGitApi: jest.fn().mockImplementation(() => ({ getRepository: jest.fn().mockResolvedValue(mockRepository), getRefs: jest.fn().mockResolvedValue(null), // Simulate null refs })), }; // Act const result = await (0, feature_1.getRepositoryDetails)(mockConnection, { projectId: 'test-project', repositoryId: 'test-repo', includeRefs: true, }); // Assert expect(result).toBeDefined(); expect(result.repository).toEqual(mockRepository); expect(result.refs).toBeDefined(); expect(result.refs?.value).toEqual([]); expect(result.refs?.count).toBe(0); }); }); //# sourceMappingURL=feature.spec.unit.js.map