|
1 | 1 | import { Command } from 'commander'; |
2 | | -import { parseEnvironmentVariables, parseDomains, parseDomainsFile, escapeShellArg, joinShellArgs, parseVolumeMounts, isValidIPv4, isValidIPv6, parseDnsServers, validateAgentImage, isAgentImagePreset, AGENT_IMAGE_PRESETS, processAgentImageOption, processLocalhostKeyword, validateSkipPullWithBuildLocal, validateAllowHostPorts, parseMemoryLimit, validateFormat, validateApiProxyConfig, buildRateLimitConfig, validateRateLimitFlags, validateApiTargetInAllowedDomains, DEFAULT_OPENAI_API_TARGET, DEFAULT_ANTHROPIC_API_TARGET, emitApiProxyTargetWarnings, formatItem, program } from './cli'; |
| 2 | +import { parseEnvironmentVariables, parseDomains, parseDomainsFile, escapeShellArg, joinShellArgs, parseVolumeMounts, isValidIPv4, isValidIPv6, parseDnsServers, validateAgentImage, isAgentImagePreset, AGENT_IMAGE_PRESETS, processAgentImageOption, processLocalhostKeyword, validateSkipPullWithBuildLocal, validateAllowHostPorts, parseMemoryLimit, validateFormat, validateApiProxyConfig, buildRateLimitConfig, validateRateLimitFlags, validateApiTargetInAllowedDomains, DEFAULT_OPENAI_API_TARGET, DEFAULT_ANTHROPIC_API_TARGET, emitApiProxyTargetWarnings, formatItem, program, parseAgentTimeout, applyAgentTimeout } from './cli'; |
3 | 3 | import { redactSecrets } from './redact-secrets'; |
4 | 4 | import * as fs from 'fs'; |
5 | 5 | import * as path from 'path'; |
@@ -1783,4 +1783,102 @@ describe('cli', () => { |
1783 | 1783 | }); |
1784 | 1784 | }); |
1785 | 1785 |
|
| 1786 | + describe('parseAgentTimeout', () => { |
| 1787 | + it('should parse a valid positive integer', () => { |
| 1788 | + const result = parseAgentTimeout('30'); |
| 1789 | + expect(result).toEqual({ minutes: 30 }); |
| 1790 | + }); |
| 1791 | + |
| 1792 | + it('should parse single minute timeout', () => { |
| 1793 | + const result = parseAgentTimeout('1'); |
| 1794 | + expect(result).toEqual({ minutes: 1 }); |
| 1795 | + }); |
| 1796 | + |
| 1797 | + it('should return error for zero', () => { |
| 1798 | + const result = parseAgentTimeout('0'); |
| 1799 | + expect(result).toEqual({ error: '--agent-timeout must be a positive integer (minutes)' }); |
| 1800 | + }); |
| 1801 | + |
| 1802 | + it('should return error for negative value', () => { |
| 1803 | + const result = parseAgentTimeout('-5'); |
| 1804 | + expect(result).toEqual({ error: '--agent-timeout must be a positive integer (minutes)' }); |
| 1805 | + }); |
| 1806 | + |
| 1807 | + it('should return error for non-numeric string', () => { |
| 1808 | + const result = parseAgentTimeout('abc'); |
| 1809 | + expect(result).toEqual({ error: '--agent-timeout must be a positive integer (minutes)' }); |
| 1810 | + }); |
| 1811 | + |
| 1812 | + it('should return error for empty string', () => { |
| 1813 | + const result = parseAgentTimeout(''); |
| 1814 | + expect(result).toEqual({ error: '--agent-timeout must be a positive integer (minutes)' }); |
| 1815 | + }); |
| 1816 | + |
| 1817 | + it('should parse large timeout values', () => { |
| 1818 | + const result = parseAgentTimeout('1440'); |
| 1819 | + expect(result).toEqual({ minutes: 1440 }); |
| 1820 | + }); |
| 1821 | + |
| 1822 | + it('should return error for value with trailing non-numeric characters', () => { |
| 1823 | + const result = parseAgentTimeout('30m'); |
| 1824 | + expect(result).toEqual({ error: '--agent-timeout must be a positive integer (minutes)' }); |
| 1825 | + }); |
| 1826 | + |
| 1827 | + it('should return error for decimal value', () => { |
| 1828 | + const result = parseAgentTimeout('1.5'); |
| 1829 | + expect(result).toEqual({ error: '--agent-timeout must be a positive integer (minutes)' }); |
| 1830 | + }); |
| 1831 | + |
| 1832 | + it('should return error for value with leading zero', () => { |
| 1833 | + const result = parseAgentTimeout('030'); |
| 1834 | + expect(result).toEqual({ error: '--agent-timeout must be a positive integer (minutes)' }); |
| 1835 | + }); |
| 1836 | + }); |
| 1837 | + |
| 1838 | + describe('applyAgentTimeout', () => { |
| 1839 | + it('should do nothing when agentTimeout is undefined', () => { |
| 1840 | + const config: any = {}; |
| 1841 | + const logger = { error: jest.fn(), info: jest.fn() }; |
| 1842 | + applyAgentTimeout(undefined, config, logger); |
| 1843 | + expect(config.agentTimeout).toBeUndefined(); |
| 1844 | + expect(logger.info).not.toHaveBeenCalled(); |
| 1845 | + expect(logger.error).not.toHaveBeenCalled(); |
| 1846 | + }); |
| 1847 | + |
| 1848 | + it('should set agentTimeout on config for valid value', () => { |
| 1849 | + const config: any = {}; |
| 1850 | + const logger = { error: jest.fn(), info: jest.fn() }; |
| 1851 | + applyAgentTimeout('30', config, logger); |
| 1852 | + expect(config.agentTimeout).toBe(30); |
| 1853 | + expect(logger.info).toHaveBeenCalledWith('Agent timeout set to 30 minutes'); |
| 1854 | + }); |
| 1855 | + |
| 1856 | + it('should call process.exit for invalid value', () => { |
| 1857 | + const config: any = {}; |
| 1858 | + const logger = { error: jest.fn(), info: jest.fn() }; |
| 1859 | + const mockExit = jest.spyOn(process, 'exit').mockImplementation((() => {}) as any); |
| 1860 | + applyAgentTimeout('abc', config, logger); |
| 1861 | + expect(logger.error).toHaveBeenCalledWith('--agent-timeout must be a positive integer (minutes)'); |
| 1862 | + expect(mockExit).toHaveBeenCalledWith(1); |
| 1863 | + mockExit.mockRestore(); |
| 1864 | + }); |
| 1865 | + }); |
| 1866 | + |
| 1867 | + describe('formatItem', () => { |
| 1868 | + it('should format term with description when term fits within width', () => { |
| 1869 | + const result = formatItem('--flag', 'Description text', 20, 2, 2, 80); |
| 1870 | + expect(result).toBe(' --flag Description text'); |
| 1871 | + }); |
| 1872 | + |
| 1873 | + it('should wrap description to next line when term exceeds width', () => { |
| 1874 | + const result = formatItem('--very-long-flag-name-that-exceeds-width', 'Description', 10, 2, 2, 80); |
| 1875 | + expect(result).toContain('--very-long-flag-name-that-exceeds-width\n'); |
| 1876 | + expect(result).toContain('Description'); |
| 1877 | + }); |
| 1878 | + |
| 1879 | + it('should format term without description', () => { |
| 1880 | + const result = formatItem('--flag', '', 20, 2, 2, 80); |
| 1881 | + expect(result).toBe(' --flag'); |
| 1882 | + }); |
| 1883 | + }); |
1786 | 1884 | }); |
0 commit comments