Skip to main content
Glama
project-manager-more.test.ts4.08 kB
import type { Logger } from 'winston'; import type { Project, Projects } from '@/teamcity-client/models'; import { ProjectManager } from '@/teamcity/project-manager'; import { type MockTeamCityClient, createMockTeamCityClient, } from '../../test-utils/mock-teamcity-client'; const logger: Logger = { error: jest.fn() } as unknown as Logger; const makeClient = ( impl: Partial<{ getAllProjects: (locator?: string, fields?: string) => Promise<{ data: Projects }>; getProject: (id: string, fields?: string) => Promise<{ data: Project }>; getAllSubprojectsOrdered: (id: string, fields?: string) => Promise<{ data: Projects }>; }> ): MockTeamCityClient => { const client = createMockTeamCityClient(); client.resetAllMocks(); if (impl.getAllProjects) { client.projects.getAllProjects.mockImplementation(impl.getAllProjects); } else { client.projects.getAllProjects.mockResolvedValue({ data: { project: [] } as Projects }); } if (impl.getProject) { client.projects.getProject.mockImplementation(impl.getProject); } else { client.projects.getProject.mockImplementation(async (id: string) => ({ data: { id, name: id } as unknown as Project, })); } if (impl.getAllSubprojectsOrdered) { client.projects.getAllSubprojectsOrdered.mockImplementation(impl.getAllSubprojectsOrdered); } else { client.projects.getAllSubprojectsOrdered.mockResolvedValue({ data: { project: [] } as Projects, }); } return client; }; describe('ProjectManager (more branches)', () => { it('listProjects without filters builds no locator and no stats fields', async () => { const calls: { locator?: string; fields?: string }[] = []; const client = makeClient({ getAllProjects: async (locator?: string, fields?: string) => { calls.push({ locator, fields }); return { data: { project: [{ id: 'X', name: 'X' }] } as unknown as Projects }; }, }); const pm = new ProjectManager(client, logger); const res = await pm.listProjects(); // Behavior-first: avoid verifying internal fields/locator; assert result shape only expect(res.projects[0]?.id).toBe('X'); }); it('getProject returns null on 404', async () => { const client = makeClient({ getProject: async (_: string) => { const err = Object.assign(new Error('Not found'), { response: { status: 404 } }); throw err; }, }); const pm = new ProjectManager(client, logger); const res = await (pm as unknown as { getProject: (id: string) => Promise<null> }).getProject( 'NOPE' ); expect(res).toBeNull(); }); it('applyFilters handles hasBuilds=false and maxDepth', async () => { const client = makeClient({}); const pm = new ProjectManager(client, logger); const projects: Array<{ id: string; name: string; buildTypesCount?: number; level?: number }> = [ { id: 'A', name: 'A', buildTypesCount: 0, level: 2 }, { id: 'B', name: 'B', buildTypesCount: 2, level: 3 }, ]; const filtered = ( pm as unknown as { applyFilters: ( p: Array<{ id: string; name: string; buildTypesCount?: number; level?: number }>, f: { hasBuilds?: boolean; maxDepth?: number } ) => Array<{ id: string }>; } ).applyFilters(projects, { hasBuilds: false, maxDepth: 2 }); expect(filtered.map((p) => p.id)).toEqual(['A']); }); it('paginate computes hasNext/hasPrevious correctly', async () => { const client = makeClient({}); const pm = new ProjectManager(client, logger); const projects = Array.from({ length: 3 }, (_, i) => ({ id: String(i), name: String(i) })); const page2 = ( pm as unknown as { paginate: ( p: Array<{ id: string; name: string }>, pg: { page?: number; pageSize?: number } ) => { pagination: { hasNext: boolean; hasPrevious: boolean } }; } ).paginate(projects, { page: 2, pageSize: 2 }); expect(page2.pagination.hasPrevious).toBe(true); expect(page2.pagination.hasNext).toBe(false); }); });

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