Skip to main content
Glama
build-query-builder.test.ts9.63 kB
/** * Tests for BuildQueryBuilder */ import { BuildQueryBuilder, type BuildStatus } from '@/teamcity/build-query-builder'; describe('BuildQueryBuilder', () => { let builder: BuildQueryBuilder; beforeEach(() => { builder = new BuildQueryBuilder(); }); describe('Basic Filters', () => { it('should create locator for project filter', () => { const locator = builder.withProject('MyProject').build(); expect(locator).toBe('project:MyProject'); }); it('should create locator for build type filter', () => { const locator = builder.withBuildType('MyBuildConfig').build(); expect(locator).toBe('buildType:MyBuildConfig'); }); it('should create locator for status filter', () => { const locator = builder.withStatus('SUCCESS').build(); expect(locator).toBe('status:SUCCESS'); }); it('should create locator for branch filter', () => { const locator = builder.withBranch('main').build(); expect(locator).toBe('branch:main'); }); it('should create locator for tag filter', () => { const locator = builder.withTag('release').build(); expect(locator).toBe('tag:release'); }); }); describe('Date Filters', () => { it('should convert ISO date to TeamCity format for sinceDate', () => { const locator = builder.withSinceDate('2025-08-29T12:00:00Z').build(); expect(locator).toBe('sinceDate:20250829T120000+0000'); }); it('should convert ISO date to TeamCity format for untilDate', () => { const locator = builder.withUntilDate('2025-08-30T18:30:00Z').build(); expect(locator).toBe('untilDate:20250830T183000+0000'); }); it('should handle date-only format', () => { const locator = builder.withSinceDate('2025-08-29').build(); expect(locator).toBe('sinceDate:20250829T000000+0000'); }); it('should handle various ISO date formats', () => { const locator = builder.withSinceDate('2025-08-29T12:00:00.000Z').build(); expect(locator).toBe('sinceDate:20250829T120000+0000'); }); it('should throw error for invalid date format', () => { expect(() => { builder.withSinceDate('invalid-date').build(); }).toThrow('Invalid date format'); }); }); describe('Boolean Filters', () => { it('should add running filter', () => { const locator = builder.withRunning(true).build(); expect(locator).toBe('running:true'); }); it('should add canceled filter', () => { const locator = builder.withCanceled(false).build(); expect(locator).toBe('canceled:false'); }); it('should add personal filter', () => { const locator = builder.withPersonal(true).build(); expect(locator).toBe('personal:true'); }); it('should add failedToStart filter', () => { const locator = builder.withFailedToStart(false).build(); expect(locator).toBe('failedToStart:false'); }); }); describe('Numeric Filters', () => { it('should add sinceBuild filter', () => { const locator = builder.withSinceBuild(12345).build(); expect(locator).toBe('sinceBuild:12345'); }); it('should add count limit', () => { const locator = builder.withCount(50).build(); expect(locator).toBe('count:50'); }); it('should add start offset', () => { const locator = builder.withStart(100).build(); expect(locator).toBe('start:100'); }); }); describe('Wildcard Patterns', () => { it('should support wildcard in branch filter', () => { const locator = builder.withBranch('feature/*').build(); expect(locator).toBe('branch:feature/*'); }); it('should support wildcard in tag filter', () => { const locator = builder.withTag('v*').build(); expect(locator).toBe('tag:v*'); }); it('should support complex wildcard patterns', () => { const locator = builder.withBranch('release/*/hotfix').build(); expect(locator).toBe('branch:release/*/hotfix'); }); }); describe('Special Character Escaping', () => { it('should escape special characters in values', () => { const locator = builder.withProject('My:Project').build(); expect(locator).toBe('project:(My:Project)'); }); it('should escape parentheses in values', () => { const locator = builder.withBranch('feature/(test)').build(); expect(locator).toBe('branch:(feature/(test))'); }); it('should escape commas in values', () => { const locator = builder.withTag('version,1.0').build(); expect(locator).toBe('tag:(version,1.0)'); }); it('should escape branch values containing slashes without wildcards', () => { const locator = builder.withBranch('refs/heads/main').build(); expect(locator).toBe('branch:(refs/heads/main)'); }); it('should escape branch values containing whitespace', () => { const locator = builder.withBranch('feature branch').build(); expect(locator).toBe('branch:(feature branch)'); }); it('should not escape wildcards', () => { const locator = builder.withBranch('feature/*:test').build(); expect(locator).toBe('branch:(feature/*:test)'); }); }); describe('Combining Multiple Filters', () => { it('should combine two filters with comma', () => { const locator = builder.withProject('MyProject').withStatus('SUCCESS').build(); expect(locator).toBe('project:MyProject,status:SUCCESS'); }); it('should combine multiple filters', () => { const locator = builder .withProject('MyProject') .withBuildType('MyBuildConfig') .withStatus('FAILURE') .withBranch('main') .build(); expect(locator).toBe('project:MyProject,buildType:MyBuildConfig,status:FAILURE,branch:main'); }); it('should combine date filters with other filters', () => { const locator = builder .withProject('MyProject') .withSinceDate('2025-08-29T00:00:00Z') .withStatus('SUCCESS') .build(); expect(locator).toBe('project:MyProject,status:SUCCESS,sinceDate:20250829T000000+0000'); }); it('should combine boolean and numeric filters', () => { const locator = builder .withRunning(false) .withCanceled(false) .withCount(100) .withStart(50) .build(); expect(locator).toBe('running:false,canceled:false,count:100,start:50'); }); }); describe('Complex Scenarios', () => { it('should handle all filter types together', () => { const locator = builder .withProject('MyProject') .withBuildType('MyBuildConfig') .withStatus('SUCCESS') .withBranch('feature/*') .withTag('release') .withSinceDate('2025-08-01T00:00:00Z') .withUntilDate('2025-08-31T23:59:59Z') .withRunning(false) .withPersonal(false) .withCount(50) .build(); expect(locator).toBe( 'project:MyProject,buildType:MyBuildConfig,status:SUCCESS,' + 'branch:feature/*,tag:release,' + 'sinceDate:20250801T000000+0000,untilDate:20250831T235959+0000,' + 'running:false,personal:false,count:50' ); }); it('should handle filters with special characters and escaping', () => { const locator = builder .withProject('My:Special,Project') .withBranch('feature/(test)*') .withTag('v1.0,beta') .build(); expect(locator).toBe('project:(My:Special,Project),branch:(feature/(test)*),tag:(v1.0,beta)'); }); }); describe('Reset and Reuse', () => { it('should reset builder state', () => { builder.withProject('MyProject').withStatus('SUCCESS'); const locator1 = builder.build(); expect(locator1).toBe('project:MyProject,status:SUCCESS'); builder.reset(); const locator2 = builder.build(); expect(locator2).toBe(''); }); it('should allow reuse after reset', () => { builder.withProject('Project1').build(); builder.reset(); const locator = builder.withProject('Project2').withStatus('FAILURE').build(); expect(locator).toBe('project:Project2,status:FAILURE'); }); }); describe('Validation', () => { it('should validate status values', () => { expect(() => { builder.withStatus('INVALID' as unknown as BuildStatus).build(); }).toThrow('Invalid status value'); }); it('should validate date range logic', () => { expect(() => { builder.withSinceDate('2025-08-30T00:00:00Z').withUntilDate('2025-08-29T00:00:00Z').build(); }).toThrow('sinceDate must be before untilDate'); }); it('should validate count limit', () => { expect(() => { builder.withCount(0).build(); }).toThrow('Count must be between 1 and 10000'); expect(() => { builder.withCount(10001).build(); }).toThrow('Count must be between 1 and 10000'); }); it('should validate start offset', () => { expect(() => { builder.withStart(-1).build(); }).toThrow('Start offset must be non-negative'); }); }); describe('Empty Locator', () => { it('should return empty string for no filters', () => { const locator = builder.build(); expect(locator).toBe(''); }); it('should handle undefined values gracefully', () => { const locator = builder .withProject(undefined as unknown as string) .withStatus(undefined as unknown as BuildStatus) .build(); expect(locator).toBe(''); }); }); });

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