Skip to main content
Glama
analysis-run.mapper.test.ts8.07 kB
/** * @fileoverview Tests for AnalysisRunMapper */ import { describe, it, expect } from 'vitest'; import { AnalysisRunMapper } from '../analysis-run.mapper.js'; import { DeepSourceRun, AnalysisRunStatus } from '../../../models/runs.js'; import { asRunId, asCommitOid, asBranchName, asAnalyzerShortcode, asGraphQLNodeId, } from '../../../types/branded.js'; import { AnalysisRun } from '../../../domain/aggregates/analysis-run/analysis-run.aggregate.js'; describe('AnalysisRunMapper', () => { const mockApiRun: DeepSourceRun = { id: asGraphQLNodeId('R_kgDOGHqVWg'), runUid: asRunId('run-123'), commitOid: asCommitOid('abc123def456'), branchName: asBranchName('main'), baseOid: asCommitOid('def456ghi789'), status: 'SUCCESS', createdAt: '2024-01-15T10:00:00Z', updatedAt: '2024-01-15T10:05:00Z', finishedAt: '2024-01-15T10:10:00Z', summary: { occurrencesIntroduced: 10, occurrencesResolved: 5, occurrencesSuppressed: 2, occurrenceDistributionByAnalyzer: [ { analyzerShortcode: asAnalyzerShortcode('python'), introduced: 7, }, { analyzerShortcode: asAnalyzerShortcode('javascript'), introduced: 3, }, ], occurrenceDistributionByCategory: [ { category: 'bug_risk', introduced: 4, }, { category: 'SECURITY', introduced: 3, }, { category: 'performance', introduced: 3, }, ], }, repository: { name: 'test-repo', id: asGraphQLNodeId('R_repo123'), }, }; describe('toDomain', () => { it('should map API run to domain aggregate', () => { const projectKey = 'test-project'; const run = AnalysisRunMapper.toDomain(mockApiRun, projectKey); expect(run).toBeInstanceOf(AnalysisRun); expect(run.runId).toBe('run-123'); expect(run.projectKey).toBe(projectKey); expect(run.repositoryId).toBe('R_repo123'); expect(run.status).toBe('SUCCESS'); }); it('should map commit information correctly', () => { const projectKey = 'test-project'; const run = AnalysisRunMapper.toDomain(mockApiRun, projectKey); expect(run.commitInfo.oid).toBe('abc123def456'); expect(run.commitInfo.branch).toBe('main'); expect(run.commitInfo.baseOid).toBe('def456ghi789'); }); it('should map timestamps correctly', () => { const projectKey = 'test-project'; const run = AnalysisRunMapper.toDomain(mockApiRun, projectKey); expect(run.timestamps.createdAt).toEqual(new Date('2024-01-15T10:00:00Z')); expect(run.timestamps.startedAt).toEqual(new Date('2024-01-15T10:05:00Z')); expect(run.timestamps.finishedAt).toEqual(new Date('2024-01-15T10:10:00Z')); }); it('should map issue summary correctly', () => { const projectKey = 'test-project'; const run = AnalysisRunMapper.toDomain(mockApiRun, projectKey); expect(run.summary).toBeDefined(); expect(run.summary.totalIntroduced.count).toBe(10); expect(run.summary.totalResolved.count).toBe(5); expect(run.summary.totalSuppressed.count).toBe(2); }); it('should map analyzer distributions', () => { const projectKey = 'test-project'; const run = AnalysisRunMapper.toDomain(mockApiRun, projectKey); expect(run.summary?.byAnalyzer).toHaveLength(2); expect(run.summary?.byAnalyzer[0].analyzerShortcode).toBe('python'); expect(run.summary?.byAnalyzer[0].introduced.count).toBe(7); expect(run.summary?.byAnalyzer[1].analyzerShortcode).toBe('javascript'); expect(run.summary?.byAnalyzer[1].introduced.count).toBe(3); }); it('should map category distributions with case normalization', () => { const projectKey = 'test-project'; const run = AnalysisRunMapper.toDomain(mockApiRun, projectKey); expect(run.summary?.byCategory).toHaveLength(3); expect(run.summary?.byCategory[0].category).toBe('BUG_RISK'); expect(run.summary?.byCategory[0].introduced.count).toBe(4); expect(run.summary?.byCategory[1].category).toBe('SECURITY'); expect(run.summary?.byCategory[1].introduced.count).toBe(3); expect(run.summary?.byCategory[2].category).toBe('PERFORMANCE'); expect(run.summary?.byCategory[2].introduced.count).toBe(3); }); it('should handle API status mapping', () => { const testCases = [ { apiStatus: 'PENDING', expectedStatus: 'PENDING' }, { apiStatus: 'READY', expectedStatus: 'RUNNING' }, { apiStatus: 'SUCCESS', expectedStatus: 'SUCCESS' }, { apiStatus: 'FAILURE', expectedStatus: 'FAILURE' }, { apiStatus: 'TIMEOUT', expectedStatus: 'TIMEOUT' }, { apiStatus: 'CANCEL', expectedStatus: 'CANCELLED' }, { apiStatus: 'SKIPPED', expectedStatus: 'SKIPPED' }, ]; for (const { apiStatus, expectedStatus } of testCases) { const apiRun = { ...mockApiRun, status: apiStatus as AnalysisRunStatus }; const run = AnalysisRunMapper.toDomain(apiRun, 'test-project'); expect(run.status).toBe(expectedStatus); } }); it('should handle unknown status by defaulting to FAILURE', () => { const apiRun = { ...mockApiRun, status: 'UNKNOWN_STATUS' as AnalysisRunStatus }; const run = AnalysisRunMapper.toDomain(apiRun, 'test-project'); expect(run.status).toBe('FAILURE'); }); it('should handle PENDING status timestamps', () => { const apiRun = { ...mockApiRun, status: 'PENDING', finishedAt: undefined }; const run = AnalysisRunMapper.toDomain(apiRun, 'test-project'); expect(run.timestamps.startedAt).toBeUndefined(); expect(run.timestamps.finishedAt).toBeUndefined(); }); it('should handle missing distributions', () => { const apiRun = { ...mockApiRun, summary: { occurrencesIntroduced: 10, occurrencesResolved: 5, occurrencesSuppressed: 2, }, }; const run = AnalysisRunMapper.toDomain(apiRun, 'test-project'); expect(run.summary?.byAnalyzer).toEqual([]); expect(run.summary?.byCategory).toEqual([]); }); it('should initialize issues as empty array', () => { const run = AnalysisRunMapper.toDomain(mockApiRun, 'test-project'); expect(run.issues).toEqual([]); }); }); describe('toPersistence', () => { it('should map domain aggregate to persistence format', () => { const run = AnalysisRun.create({ runId: asRunId('run-123'), projectKey: 'test-project', repositoryId: asGraphQLNodeId('R_repo123'), commitInfo: { oid: asCommitOid('abc123'), branch: asBranchName('main'), baseOid: asCommitOid('def456'), }, }); const persistence = AnalysisRunMapper.toPersistence(run); expect(persistence.runId).toBe('run-123'); expect(persistence.projectKey).toBe('test-project'); expect(persistence.repositoryId).toBe('R_repo123'); expect(persistence.status).toBe('PENDING'); expect(persistence.commitInfo.oid).toBe('abc123'); }); }); describe('toDomainList', () => { it('should map multiple API runs to domain aggregates', () => { const apiRuns = [ mockApiRun, { ...mockApiRun, runUid: asRunId('run-456'), status: 'FAILURE' }, { ...mockApiRun, runUid: asRunId('run-789'), status: 'READY' }, ]; const runs = AnalysisRunMapper.toDomainList(apiRuns, 'test-project'); expect(runs).toHaveLength(3); expect(runs[0].runId).toBe('run-123'); expect(runs[0].status).toBe('SUCCESS'); expect(runs[1].runId).toBe('run-456'); expect(runs[1].status).toBe('FAILURE'); expect(runs[2].runId).toBe('run-789'); expect(runs[2].status).toBe('RUNNING'); }); it('should handle empty list', () => { const runs = AnalysisRunMapper.toDomainList([], 'test-project'); expect(runs).toEqual([]); }); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/sapientpants/deepsource-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server