Skip to main content
Glama
build-results-manager.test.ts3.98 kB
import { BuildResultsManager } from '@/teamcity/build-results-manager'; import type { TeamCityUnifiedClient } from '@/teamcity/types/client'; jest.mock('@/utils/logger', () => ({ debug: jest.fn(), info: jest.fn(), warn: jest.fn(), error: jest.fn(), })); const createManager = () => new BuildResultsManager({ getApiConfig: () => ({ baseUrl: 'https://teamcity.example/' }), modules: { builds: { downloadFileOfBuild: jest.fn(), }, }, } as unknown as TeamCityUnifiedClient); describe('BuildResultsManager utilities', () => { afterEach(() => { jest.restoreAllMocks(); }); it('buildAbsoluteUrl normalizes relative paths', () => { const manager = createManager(); const internals = manager as unknown as { buildAbsoluteUrl: (path: string) => string; }; expect(internals.buildAbsoluteUrl('https://external.example/build')).toBe( 'https://external.example/build' ); expect(internals.buildAbsoluteUrl('/app/rest/builds')).toBe( 'https://teamcity.example/app/rest/builds' ); expect(internals.buildAbsoluteUrl('app/rest/builds')).toBe( 'https://teamcity.example/app/rest/builds' ); }); it('parseTeamCityDate handles canonical and ISO formats', () => { const manager = createManager(); const internals = manager as unknown as { parseTeamCityDate: (value: string) => number; }; const canonical = internals.parseTeamCityDate('20250112T121314+0000'); expect(canonical).toBe(new Date(2025, 0, 12, 12, 13, 14).getTime()); const iso = internals.parseTeamCityDate('2025-01-12T12:13:14.000Z'); expect(iso).toBe(Date.parse('2025-01-12T12:13:14.000Z')); }); it('getCacheKey combines build id and options', () => { const manager = createManager(); const internals = manager as unknown as { getCacheKey: (id: string, options: Record<string, unknown>) => string; }; expect(internals.getCacheKey('123', { includeArtifacts: true })).toBe( '123:{"includeArtifacts":true}' ); }); it('isAxiosNotFound detects axios 404 errors', () => { const manager = createManager(); const internals = manager as unknown as { isAxiosNotFound: (error: unknown) => boolean; }; expect(internals.isAxiosNotFound({ response: { status: 404 } })).toBe(true); expect(internals.isAxiosNotFound({ response: { status: 500 } })).toBe(false); expect(internals.isAxiosNotFound({})).toBe(false); }); it('caches results and expires them based on TTL', () => { const manager = createManager(); const internals = manager as unknown as { cacheResult: (key: string, result: unknown) => void; getFromCache: (key: string) => unknown; }; const cacheTtl = (BuildResultsManager as unknown as { cacheTtlMs: number }).cacheTtlMs; const nowSpy = jest.spyOn(Date, 'now').mockReturnValue(0); internals.cacheResult('build:1', { build: { id: 1 } }); expect(internals.getFromCache('build:1')).toEqual({ build: { id: 1 } }); nowSpy.mockReturnValue(cacheTtl + 1); expect(internals.getFromCache('build:1')).toBeNull(); }); it('cleanCache removes expired entries while preserving recent ones', () => { const manager = createManager(); const internals = manager as unknown as { cacheResult: (key: string, result: unknown) => void; cleanCache: () => void; getFromCache: (key: string) => unknown; }; const cacheTtl = (BuildResultsManager as unknown as { cacheTtlMs: number }).cacheTtlMs; const nowSpy = jest.spyOn(Date, 'now'); nowSpy.mockReturnValue(0); internals.cacheResult('old', { build: { id: 1 } }); nowSpy.mockReturnValue(cacheTtl - 1000); internals.cacheResult('fresh', { build: { id: 2 } }); nowSpy.mockReturnValue(cacheTtl + 1000); internals.cleanCache(); expect(internals.getFromCache('old')).toBeNull(); expect(internals.getFromCache('fresh')).toEqual({ build: { id: 2 } }); }); });

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/Daghis/teamcity-mcp'

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