Skip to main content
Glama
quality-metrics.mapper.test.ts8.42 kB
/** * @fileoverview Tests for QualityMetricsMapper */ import { describe, it, expect } from 'vitest'; import { QualityMetricsMapper } from '../quality-metrics.mapper.js'; import { RepositoryMetric, MetricShortcode, MetricDirection, MetricThresholdStatus, } from '../../../models/metrics.js'; import { QualityMetrics } from '../../../domain/aggregates/quality-metrics/quality-metrics.aggregate.js'; describe('QualityMetricsMapper', () => { const mockApiMetric: RepositoryMetric = { name: 'Line Coverage', shortcode: MetricShortcode.LCV, description: 'Percentage of lines covered by tests', positiveDirection: MetricDirection.UPWARD, unit: '%', minValueAllowed: 0, maxValueAllowed: 100, isReported: true, isThresholdEnforced: true, items: [ { id: 'item-1', key: 'AGGREGATE', threshold: 80, latestValue: 85.5, latestValueDisplay: '85.5%', thresholdStatus: MetricThresholdStatus.PASSING, }, { id: 'item-2', key: 'PYTHON', threshold: 75, latestValue: 70, latestValueDisplay: '70%', thresholdStatus: MetricThresholdStatus.FAILING, }, ], }; describe('toDomainList', () => { it('should map API metric with multiple items to multiple domain aggregates', () => { const projectKey = 'test-project'; const repositoryId = 'repo-123'; const metrics = QualityMetricsMapper.toDomainList(mockApiMetric, projectKey, repositoryId); expect(metrics).toHaveLength(2); expect(metrics[0]).toBeInstanceOf(QualityMetrics); expect(metrics[1]).toBeInstanceOf(QualityMetrics); expect(metrics[0].configuration.metricKey).toBe('AGGREGATE'); expect(metrics[1].configuration.metricKey).toBe('PYTHON'); }); it('should handle empty items array', () => { const emptyMetric = { ...mockApiMetric, items: [] }; const metrics = QualityMetricsMapper.toDomainList(emptyMetric, 'test-project', 'repo-123'); expect(metrics).toEqual([]); }); }); describe('toDomain', () => { it('should map API metric item to domain aggregate', () => { const projectKey = 'test-project'; const repositoryId = 'repo-123'; const item = mockApiMetric.items[0]; const metrics = QualityMetricsMapper.toDomain(mockApiMetric, item, projectKey, repositoryId); expect(metrics).toBeInstanceOf(QualityMetrics); expect(metrics.projectKey).toBe(projectKey); expect(metrics.repositoryId).toBe(repositoryId); expect(metrics.configuration.name).toBe('Line Coverage'); expect(metrics.configuration.shortcode).toBe(MetricShortcode.LCV); expect(metrics.configuration.metricKey).toBe('AGGREGATE'); }); it('should map threshold correctly', () => { const item = mockApiMetric.items[0]; const metrics = QualityMetricsMapper.toDomain( mockApiMetric, item, 'test-project', 'repo-123' ); expect(metrics.configuration.threshold).not.toBeNull(); expect(metrics.configuration.threshold?.value).toBe(80); }); it('should handle null threshold', () => { const itemNoThreshold = { ...mockApiMetric.items[0], threshold: null }; const metrics = QualityMetricsMapper.toDomain( mockApiMetric, itemNoThreshold, 'test-project', 'repo-123' ); expect(metrics.configuration.threshold).toBeNull(); }); it('should map current value correctly', () => { const item = mockApiMetric.items[0]; const metrics = QualityMetricsMapper.toDomain( mockApiMetric, item, 'test-project', 'repo-123' ); expect(metrics.currentValue).not.toBeNull(); expect(metrics.currentValue?.value).toBe(85.5); expect(metrics.currentValue?.unit).toBe('%'); }); it('should handle null latest value', () => { const itemNoValue = { ...mockApiMetric.items[0], latestValue: null }; const metrics = QualityMetricsMapper.toDomain( mockApiMetric, itemNoValue, 'test-project', 'repo-123' ); expect(metrics.currentValue).toBeNull(); }); it('should map configuration properties correctly', () => { const item = mockApiMetric.items[0]; const metrics = QualityMetricsMapper.toDomain( mockApiMetric, item, 'test-project', 'repo-123' ); expect(metrics.configuration.unit).toBe('%'); expect(metrics.configuration.minAllowed).toBe(0); expect(metrics.configuration.maxAllowed).toBe(100); expect(metrics.configuration.positiveDirection).toBe('UPWARD'); expect(metrics.configuration.isReported).toBe(true); expect(metrics.configuration.isThresholdEnforced).toBe(true); }); }); describe('mapThresholdStatus', () => { it('should map API status to domain status', () => { expect(QualityMetricsMapper.mapThresholdStatus('PASSING')).toBe('PASSING'); expect(QualityMetricsMapper.mapThresholdStatus('FAILING')).toBe('FAILING'); expect(QualityMetricsMapper.mapThresholdStatus('UNKNOWN')).toBe('UNKNOWN'); }); it('should default to UNKNOWN for unmapped status', () => { expect(QualityMetricsMapper.mapThresholdStatus('INVALID')).toBe('UNKNOWN'); }); }); describe('toPersistence', () => { it('should map domain aggregate to persistence format', () => { const item = mockApiMetric.items[0]; const metrics = QualityMetricsMapper.toDomain( mockApiMetric, item, 'test-project', 'repo-123' ); const persistence = QualityMetricsMapper.toPersistence(metrics); expect(persistence.id).toBe(metrics.id); expect(persistence.projectKey).toBe('test-project'); expect(persistence.repositoryId).toBe('repo-123'); expect(persistence.configuration).toEqual(metrics.configuration); expect(persistence.currentValue).toEqual(metrics.currentValue); }); }); describe('createHistoryEntry', () => { it('should create a history entry with threshold', () => { const entry = QualityMetricsMapper.createHistoryEntry( 85.5, 80, 'commit-123', new Date('2024-01-15T10:00:00Z'), '%' ); expect(entry.value.value).toBe(85.5); expect(entry.value.unit).toBe('%'); expect(entry.threshold?.value).toBe(80); expect(entry.thresholdStatus).toBe('PASSING'); expect(entry.commitOid).toBe('commit-123'); expect(entry.recordedAt).toEqual(new Date('2024-01-15T10:00:00Z')); }); it('should create a history entry without threshold', () => { const entry = QualityMetricsMapper.createHistoryEntry( 85.5, null, 'commit-123', new Date('2024-01-15T10:00:00Z'), '%' ); expect(entry.threshold).toBeNull(); expect(entry.thresholdStatus).toBe('UNKNOWN'); }); it('should determine failing status when value is below threshold', () => { const entry = QualityMetricsMapper.createHistoryEntry( 75, 80, 'commit-123', new Date('2024-01-15T10:00:00Z'), '%' ); expect(entry.thresholdStatus).toBe('FAILING'); }); }); describe('toDomainFromList', () => { it('should map multiple API metrics to domain aggregates', () => { const apiMetrics = [ mockApiMetric, { ...mockApiMetric, shortcode: MetricShortcode.BCV, name: 'Branch Coverage', items: [ { id: 'item-3', key: 'AGGREGATE', threshold: 70, latestValue: 75, latestValueDisplay: '75%', thresholdStatus: MetricThresholdStatus.PASSING, }, ], }, ]; const metrics = QualityMetricsMapper.toDomainFromList(apiMetrics, 'test-project', 'repo-123'); expect(metrics).toHaveLength(3); // 2 from first metric, 1 from second expect(metrics[0].configuration.shortcode).toBe(MetricShortcode.LCV); expect(metrics[2].configuration.shortcode).toBe(MetricShortcode.BCV); }); it('should handle empty metrics list', () => { const metrics = QualityMetricsMapper.toDomainFromList([], 'test-project', 'repo-123'); expect(metrics).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