Skip to main content
Glama
metric-value.test.ts10.1 kB
/** * @fileoverview Tests for MetricValue value object */ import { describe, it, expect, beforeEach } from 'vitest'; import { MetricValue } from '../metric-value.js'; describe('MetricValue', () => { let baseDate: Date; beforeEach(() => { baseDate = new Date('2024-01-01T00:00:00Z'); }); describe('create', () => { it('should create a metric value with all parameters', () => { const metric = MetricValue.create(42.5, '%', '42.5%', baseDate); expect(metric.value).toBe(42.5); expect(metric.unit).toBe('%'); expect(metric.displayValue).toBe('42.5%'); expect(metric.measuredAt).toEqual(baseDate); }); it('should create a metric value with default display value', () => { const metric = MetricValue.create(100, 'ms'); expect(metric.value).toBe(100); expect(metric.unit).toBe('ms'); expect(metric.displayValue).toBe('100ms'); }); it('should create a metric value with current timestamp by default', () => { const before = new Date(); const metric = MetricValue.create(50, 'count'); const after = new Date(); expect(metric.measuredAt.getTime()).toBeGreaterThanOrEqual(before.getTime()); expect(metric.measuredAt.getTime()).toBeLessThanOrEqual(after.getTime()); }); it('should throw error for non-finite values', () => { expect(() => MetricValue.create(Infinity, '%')).toThrow( 'Metric value must be a finite number' ); expect(() => MetricValue.create(NaN, '%')).toThrow('Metric value must be a finite number'); }); it('should throw error for empty unit', () => { expect(() => MetricValue.create(50, '')).toThrow('Unit cannot be empty'); }); it('should handle zero values', () => { const metric = MetricValue.create(0, 'count'); expect(metric.value).toBe(0); }); it('should handle negative values', () => { const metric = MetricValue.create(-10, 'delta'); expect(metric.value).toBe(-10); }); it('should use custom display value when provided', () => { const metric = MetricValue.create(12, 'points', '12/20'); expect(metric.displayValue).toBe('12/20'); }); }); describe('createPercentage', () => { it('should create a percentage metric with default decimal places', () => { const metric = MetricValue.createPercentage(85.567); expect(metric.value).toBe(85.567); expect(metric.unit).toBe('%'); expect(metric.displayValue).toBe('85.6%'); expect(metric.isPercentage).toBe(true); }); it('should create a percentage metric with custom decimal places', () => { const metric = MetricValue.createPercentage(85.567, 2); expect(metric.displayValue).toBe('85.57%'); }); it('should handle zero decimal places', () => { const metric = MetricValue.createPercentage(85.567, 0); expect(metric.displayValue).toBe('86%'); }); it('should handle 0%', () => { const metric = MetricValue.createPercentage(0); expect(metric.value).toBe(0); expect(metric.displayValue).toBe('0.0%'); }); it('should handle 100%', () => { const metric = MetricValue.createPercentage(100); expect(metric.value).toBe(100); expect(metric.displayValue).toBe('100.0%'); }); }); describe('createUnknown', () => { it('should create an unknown metric value', () => { const metric = MetricValue.createUnknown('count'); expect(metric.value).toBe(0); expect(metric.unit).toBe('count'); expect(metric.displayValue).toBe('N/A'); expect(metric.isUnknown).toBe(true); }); it('should handle different units', () => { const metric = MetricValue.createUnknown('%'); expect(metric.unit).toBe('%'); expect(metric.isUnknown).toBe(true); }); }); describe('getters', () => { it('should provide access to all properties', () => { const metric = MetricValue.create(42, 'count', 'Custom: 42', baseDate); expect(metric.value).toBe(42); expect(metric.unit).toBe('count'); expect(metric.displayValue).toBe('Custom: 42'); expect(metric.measuredAt).toEqual(baseDate); }); it('should correctly identify percentage metrics', () => { const percentage = MetricValue.createPercentage(50); const other = MetricValue.create(50, 'ratio'); expect(percentage.isPercentage).toBe(true); expect(other.isPercentage).toBe(false); }); it('should correctly identify unknown metrics', () => { const unknown = MetricValue.createUnknown('count'); const known = MetricValue.create(0, 'count'); expect(unknown.isUnknown).toBe(true); expect(known.isUnknown).toBe(false); }); }); describe('difference', () => { it('should calculate difference between metrics with same unit', () => { const metric1 = MetricValue.create(100, 'count'); const metric2 = MetricValue.create(75, 'count'); expect(metric1.difference(metric2)).toBe(25); expect(metric2.difference(metric1)).toBe(-25); }); it('should throw error for metrics with different units', () => { const metric1 = MetricValue.create(100, 'count'); const metric2 = MetricValue.create(75, '%'); expect(() => metric1.difference(metric2)).toThrow( 'Cannot calculate difference between metrics with different units' ); }); it('should handle zero differences', () => { const metric1 = MetricValue.create(50, 'count'); const metric2 = MetricValue.create(50, 'count'); expect(metric1.difference(metric2)).toBe(0); }); it('should handle negative values', () => { const metric1 = MetricValue.create(-10, 'delta'); const metric2 = MetricValue.create(-20, 'delta'); expect(metric1.difference(metric2)).toBe(10); }); }); describe('percentageChange', () => { it('should calculate positive percentage change', () => { const previous = MetricValue.create(100, 'count'); const current = MetricValue.create(150, 'count'); expect(current.percentageChange(previous)).toBe(50); }); it('should calculate negative percentage change', () => { const previous = MetricValue.create(100, 'count'); const current = MetricValue.create(75, 'count'); expect(current.percentageChange(previous)).toBe(-25); }); it('should handle zero previous value', () => { const previous = MetricValue.create(0, 'count'); const current = MetricValue.create(100, 'count'); expect(current.percentageChange(previous)).toBe(100); }); it('should return 0 when current is 0 and previous is 0', () => { const previous = MetricValue.create(0, 'count'); const current = MetricValue.create(0, 'count'); expect(current.percentageChange(previous)).toBe(0); }); it('should throw error for metrics with different units', () => { const previous = MetricValue.create(100, 'count'); const current = MetricValue.create(150, '%'); expect(() => current.percentageChange(previous)).toThrow( 'Cannot calculate percentage change between metrics with different units' ); }); it('should handle decimal changes', () => { const previous = MetricValue.create(10, 'count'); const current = MetricValue.create(12.5, 'count'); expect(current.percentageChange(previous)).toBe(25); }); it('should handle very small values', () => { const previous = MetricValue.create(0.01, 'ratio'); const current = MetricValue.create(0.02, 'ratio'); expect(current.percentageChange(previous)).toBe(100); }); }); describe('toString', () => { it('should return the display value', () => { const metric = MetricValue.create(42, 'count', 'Custom Display'); expect(metric.toString()).toBe('Custom Display'); }); it('should return default formatted value', () => { const metric = MetricValue.create(100, 'ms'); expect(metric.toString()).toBe('100ms'); }); it('should return N/A for unknown values', () => { const metric = MetricValue.createUnknown('count'); expect(metric.toString()).toBe('N/A'); }); }); describe('equals', () => { it('should return true for metrics with same properties', () => { const date = new Date(); const metric1 = MetricValue.create(42, 'count', '42 items', date); const metric2 = MetricValue.create(42, 'count', '42 items', date); expect(metric1.equals(metric2)).toBe(true); }); it('should return false for metrics with different values', () => { const metric1 = MetricValue.create(42, 'count'); const metric2 = MetricValue.create(43, 'count'); expect(metric1.equals(metric2)).toBe(false); }); it('should return false for metrics with different units', () => { const metric1 = MetricValue.create(42, 'count'); const metric2 = MetricValue.create(42, '%'); expect(metric1.equals(metric2)).toBe(false); }); it('should return false for metrics with different display values', () => { const metric1 = MetricValue.create(42, 'count', 'Display 1'); const metric2 = MetricValue.create(42, 'count', 'Display 2'); expect(metric1.equals(metric2)).toBe(false); }); it('should return false for metrics with different timestamps', () => { const date1 = new Date('2024-01-01'); const date2 = new Date('2024-01-02'); const metric1 = MetricValue.create(42, 'count', undefined, date1); const metric2 = MetricValue.create(42, 'count', undefined, date2); expect(metric1.equals(metric2)).toBe(false); }); }); describe('immutability', () => { it('should be immutable after creation', () => { const metric = MetricValue.create(42, 'count'); // Properties should be readonly // @ts-expect-error - Testing immutability expect(() => { metric.value = 50; }).toThrow(); // @ts-expect-error - Testing immutability expect(() => { metric.unit = '%'; }).toThrow(); }); }); });

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