Skip to main content
Glama

firewalla-mcp-server

timestamp.test.ts17.8 kB
/** * Comprehensive unit tests for timestamp utility functions * Tests edge cases, boundary conditions, and error handling */ import { unixToISOString, safeUnixToISOString, unixToISOStringOrNow, getCurrentTimestamp, detectAndConvertTimestamp, convertTimestampWithDetection, isValidTimestamp, parseFlexibleTimestamp } from '../../src/utils/timestamp.js'; describe('Timestamp Utilities - Edge Cases', () => { describe('unixToISOString', () => { test('should convert valid Unix timestamp to ISO string', () => { const timestamp = 1672531200; // 2023-01-01T00:00:00.000Z const result = unixToISOString(timestamp); expect(result).toBe('2023-01-01T00:00:00.000Z'); }); test('should handle string timestamps', () => { const timestamp = '1672531200'; const result = unixToISOString(timestamp); expect(result).toBe('2023-01-01T00:00:00.000Z'); }); test('should throw error for null timestamp', () => { expect(() => unixToISOString(null)).toThrow('Timestamp cannot be null or undefined'); }); test('should throw error for undefined timestamp', () => { expect(() => unixToISOString(undefined)).toThrow('Timestamp cannot be null or undefined'); }); test('should throw error for NaN timestamp', () => { expect(() => unixToISOString(NaN)).toThrow('Invalid timestamp: NaN'); }); test('should throw error for Infinity timestamp', () => { expect(() => unixToISOString(Infinity)).toThrow('Invalid timestamp: Infinity'); }); test('should throw error for negative timestamp', () => { expect(() => unixToISOString(-1)).toThrow('Invalid timestamp: -1'); }); test('should throw error for invalid string timestamp', () => { expect(() => unixToISOString('invalid')).toThrow('Invalid timestamp: invalid'); }); test('should handle empty string timestamp as invalid', () => { // Empty string cannot be parsed as a valid timestamp expect(() => unixToISOString('')).toThrow('Invalid timestamp:'); }); test('should handle zero timestamp (Unix epoch)', () => { // Zero is outside the valid range (2000-2100) in detectAndConvertTimestamp expect(() => unixToISOString(0)).toThrow('Invalid timestamp: 0'); }); test('should handle large valid timestamp', () => { const timestamp = 2147483647; // Max 32-bit signed integer const result = unixToISOString(timestamp); expect(result).toBe('2038-01-19T03:14:07.000Z'); }); test('should handle float timestamp (should work)', () => { const timestamp = 1672531200.5; const result = unixToISOString(timestamp); expect(result).toBe('2023-01-01T00:00:00.500Z'); }); }); describe('safeUnixToISOString', () => { test('should return ISO string for valid timestamp', () => { const timestamp = 1672531200; const result = safeUnixToISOString(timestamp); expect(result).toBe('2023-01-01T00:00:00.000Z'); }); test('should return default fallback for null timestamp', () => { const result = safeUnixToISOString(null); expect(result).toBe('Never'); }); test('should return default fallback for undefined timestamp', () => { const result = safeUnixToISOString(undefined); expect(result).toBe('Never'); }); test('should return custom fallback for invalid timestamp', () => { const result = safeUnixToISOString(null, 'Custom Fallback'); expect(result).toBe('Custom Fallback'); }); test('should return fallback for NaN timestamp', () => { const result = safeUnixToISOString(NaN, 'Invalid'); expect(result).toBe('Invalid'); }); test('should return fallback for negative timestamp', () => { const result = safeUnixToISOString(-1, 'Negative'); expect(result).toBe('Negative'); }); test('should return fallback for invalid string', () => { const result = safeUnixToISOString('invalid', 'Bad String'); expect(result).toBe('Bad String'); }); test('should handle zero timestamp', () => { const result = safeUnixToISOString(0); expect(result).toBe('Never'); }); test('should handle empty string as invalid', () => { const result = safeUnixToISOString('', 'Empty'); // Empty string is invalid and should return fallback expect(result).toBe('Empty'); }); test('should handle object input gracefully', () => { const result = safeUnixToISOString({} as any, 'Object'); expect(result).toBe('Object'); }); test('should handle array input gracefully', () => { const result = safeUnixToISOString([] as any, 'Array'); expect(result).toBe('Array'); }); }); describe('unixToISOStringOrNow', () => { test('should return ISO string for valid timestamp', () => { const timestamp = 1672531200; const result = unixToISOStringOrNow(timestamp); expect(result).toBe('2023-01-01T00:00:00.000Z'); }); test('should return current time for null timestamp', () => { const result = unixToISOStringOrNow(null); // Should return a valid ISO timestamp string expect(result).toMatch(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/); }); test('should return current time for undefined timestamp', () => { const result = unixToISOStringOrNow(undefined); // Should return a valid ISO timestamp string expect(result).toMatch(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/); }); test('should return current time for invalid timestamp', () => { const result = unixToISOStringOrNow(NaN); // Should return a valid ISO timestamp string expect(result).toMatch(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/); }); test('should return current time for negative timestamp', () => { const result = unixToISOStringOrNow(-1); // Should return a valid ISO timestamp string expect(result).toMatch(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/); }); }); describe('getCurrentTimestamp', () => { test('should return ISO timestamp string', () => { const result = getCurrentTimestamp(); expect(result).toMatch(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/); }); test('should return different timestamps when called multiple times', async () => { const timestamp1 = getCurrentTimestamp(); await new Promise(resolve => setTimeout(resolve, 10)); // Wait 10ms to ensure different timestamps const timestamp2 = getCurrentTimestamp(); expect(timestamp1).not.toBe(timestamp2); }); test('should return valid Date-parseable string', () => { const result = getCurrentTimestamp(); const parsed = new Date(result); expect(parsed.toISOString()).toBe(result); }); }); describe('Boundary Value Analysis', () => { test('should handle minimum safe Unix timestamp', () => { const result = safeUnixToISOString(0); expect(result).toBe('Never'); }); test('should handle maximum safe Unix timestamp', () => { const maxSafeTimestamp = 8640000000000; // Year 275760 - outside valid range const result = safeUnixToISOString(maxSafeTimestamp); // This timestamp is outside the valid range, should return fallback expect(result).toBe('Never'); }); test('should handle timestamp at edge of 32-bit integer', () => { const result = safeUnixToISOString(2147483647); expect(result).toBe('2038-01-19T03:14:07.000Z'); }); test('should handle timestamp just beyond 32-bit integer', () => { const result = safeUnixToISOString(2147483648); expect(result).toBe('2038-01-19T03:14:08.000Z'); }); }); describe('Type Safety Edge Cases', () => { test('should handle boolean input safely', () => { const result = safeUnixToISOString(true as any, 'Boolean'); expect(result).toBe('Boolean'); }); test('should handle function input safely', () => { const result = safeUnixToISOString((() => {}) as any, 'Function'); expect(result).toBe('Function'); }); test('should handle symbol input safely', () => { const result = safeUnixToISOString(Symbol('test') as any, 'Symbol'); expect(result).toBe('Symbol'); }); test('should handle bigint input safely', () => { const result = safeUnixToISOString(BigInt(1672531200) as any, 'BigInt'); expect(result).toBe('BigInt'); }); }); describe('Performance Edge Cases', () => { test('should handle very large array of timestamps efficiently', () => { const timestamps = Array.from({ length: 1000 }, (_, i) => 1672531200 + i); const start = Date.now(); timestamps.forEach(ts => safeUnixToISOString(ts)); const duration = Date.now() - start; expect(duration).toBeLessThan(100); // Should complete in less than 100ms }); test('should handle concurrent timestamp conversions', async () => { const promises = Array.from({ length: 100 }, (_, i) => Promise.resolve(safeUnixToISOString(1672531200 + i)) ); const results = await Promise.all(promises); expect(results).toHaveLength(100); expect(results.every(result => result.includes('2023-01-01'))).toBe(true); }); }); describe('detectAndConvertTimestamp', () => { test('should detect and convert ISO string', () => { const result = detectAndConvertTimestamp('2023-01-01T00:00:00.000Z'); expect(result).toMatchObject({ timestamp: 1672531200000, format: 'iso_string', confidence: 1.0 }); }); test('should detect Unix seconds timestamp', () => { const result = detectAndConvertTimestamp(1672531200); expect(result).toMatchObject({ timestamp: 1672531200000, format: 'unix_seconds', confidence: expect.any(Number) }); expect(result!.confidence).toBeGreaterThan(0.5); }); test('should detect Unix milliseconds timestamp', () => { const result = detectAndConvertTimestamp(1672531200000); expect(result).toMatchObject({ timestamp: 1672531200000, format: 'unix_milliseconds', confidence: expect.any(Number) }); }); test('should return null for null input', () => { expect(detectAndConvertTimestamp(null)).toBeNull(); }); test('should return null for undefined input', () => { expect(detectAndConvertTimestamp(undefined)).toBeNull(); }); test('should handle string numbers', () => { const result = detectAndConvertTimestamp('1672531200'); expect(result).toMatchObject({ timestamp: 1672531200000, format: 'unix_seconds' }); }); test('should return null for invalid string', () => { expect(detectAndConvertTimestamp('not-a-number')).toBeNull(); }); test('should return null for negative numbers', () => { expect(detectAndConvertTimestamp(-1)).toBeNull(); }); test('should return null for non-finite numbers', () => { expect(detectAndConvertTimestamp(Infinity)).toBeNull(); expect(detectAndConvertTimestamp(NaN)).toBeNull(); }); test('should return null for timestamps outside valid range', () => { expect(detectAndConvertTimestamp(100)).toBeNull(); // Too small expect(detectAndConvertTimestamp(5000000000000)).toBeNull(); // Too large }); test('should have high confidence for recent timestamps', () => { const now = Math.floor(Date.now() / 1000); const result = detectAndConvertTimestamp(now); expect(result!.confidence).toBe(0.9); }); test('should have lower confidence for distant timestamps', () => { const futureTimestamp = 4000000000; // Year ~2096 const result = detectAndConvertTimestamp(futureTimestamp); expect(result!.confidence).toBe(0.7); }); }); describe('convertTimestampWithDetection', () => { test('should convert valid timestamp without detection info', () => { const result = convertTimestampWithDetection(1672531200); expect(result).toBe('2023-01-01T00:00:00.000Z'); }); test('should include detection info when requested', () => { const result = convertTimestampWithDetection(1672531200, { includeDetectionInfo: true }); expect(result).toMatchObject({ result: '2023-01-01T00:00:00.000Z', detection: { timestamp: 1672531200000, format: 'unix_seconds', confidence: expect.any(Number) } }); }); test('should use fallback for null/undefined', () => { expect(convertTimestampWithDetection(null)).toBe('Never'); expect(convertTimestampWithDetection(undefined, { fallback: 'N/A' })).toBe('N/A'); }); test('should use fallback for low confidence', () => { const result = convertTimestampWithDetection(100, { minimumConfidence: 0.8 }); expect(result).toBe('Never'); }); test('should include detection info for failed conversion', () => { const result = convertTimestampWithDetection(null, { includeDetectionInfo: true }); expect(result).toMatchObject({ result: 'Never', detection: { timestamp: 0, format: 'unknown', confidence: 0 } }); }); test('should handle detection failure with info', () => { const result = convertTimestampWithDetection(-1, { includeDetectionInfo: true }); expect(result).toMatchObject({ result: 'Never', detection: { timestamp: 0, format: 'unknown', confidence: 0 } }); }); test('should handle exceptions gracefully', () => { // Force an exception by mocking Date constructor const originalDate = global.Date; global.Date = jest.fn().mockImplementation(() => { throw new Error('Date error'); }) as any; const result = convertTimestampWithDetection(1672531200, { includeDetectionInfo: true }); expect(result).toMatchObject({ result: 'Never', detection: { timestamp: 0, format: 'unknown', confidence: 0 } }); global.Date = originalDate; }); }); describe('isValidTimestamp', () => { test('should return true for valid timestamps', () => { expect(isValidTimestamp(1672531200)).toBe(true); expect(isValidTimestamp(1672531200000)).toBe(true); expect(isValidTimestamp('2023-01-01T00:00:00.000Z')).toBe(true); }); test('should return false for invalid timestamps', () => { expect(isValidTimestamp(null)).toBe(false); expect(isValidTimestamp(undefined)).toBe(false); expect(isValidTimestamp('invalid')).toBe(false); expect(isValidTimestamp(-1)).toBe(false); expect(isValidTimestamp(0)).toBe(false); }); test('should handle various input types', () => { expect(isValidTimestamp({})).toBe(false); expect(isValidTimestamp([])).toBe(false); expect(isValidTimestamp(true)).toBe(false); expect(isValidTimestamp(false)).toBe(false); }); }); describe('parseFlexibleTimestamp', () => { test('should parse Date objects', () => { const date = new Date('2023-01-01T00:00:00.000Z'); const result = parseFlexibleTimestamp(date); expect(result?.toISOString()).toBe('2023-01-01T00:00:00.000Z'); }); test('should return null for invalid Date objects', () => { const invalidDate = new Date('invalid'); expect(parseFlexibleTimestamp(invalidDate)).toBeNull(); }); test('should parse Unix timestamps', () => { const result = parseFlexibleTimestamp(1672531200); expect(result?.toISOString()).toBe('2023-01-01T00:00:00.000Z'); }); test('should parse ISO strings', () => { const result = parseFlexibleTimestamp('2023-01-01T00:00:00.000Z'); expect(result?.toISOString()).toBe('2023-01-01T00:00:00.000Z'); }); test('should return null for invalid inputs', () => { expect(parseFlexibleTimestamp(null)).toBeNull(); expect(parseFlexibleTimestamp(undefined)).toBeNull(); expect(parseFlexibleTimestamp('invalid')).toBeNull(); expect(parseFlexibleTimestamp({})).toBeNull(); }); test('should handle low confidence detections', () => { // Timestamp outside valid range expect(parseFlexibleTimestamp(100)).toBeNull(); }); test('should handle exceptions gracefully', () => { // This should handle any internal errors and return null const badInput = { toString: () => { throw new Error('toString error'); } }; expect(parseFlexibleTimestamp(badInput)).toBeNull(); }); }); describe('Additional edge cases for coverage', () => { test('should handle millisecond timestamps with high confidence for recent dates', () => { const now = Date.now(); const result = detectAndConvertTimestamp(now); expect(result).toMatchObject({ format: 'unix_milliseconds', confidence: 0.9 }); }); test('should handle millisecond timestamps with lower confidence for distant dates', () => { const futureMs = 4000000000000; // Year ~2096 in milliseconds const result = detectAndConvertTimestamp(futureMs); expect(result).toMatchObject({ format: 'unix_milliseconds', confidence: 0.7 }); }); test('should handle non-string, non-number inputs in detectAndConvertTimestamp', () => { expect(detectAndConvertTimestamp({} as any)).toBeNull(); expect(detectAndConvertTimestamp([] as any)).toBeNull(); expect(detectAndConvertTimestamp(true as any)).toBeNull(); }); test('should handle very small positive numbers', () => { expect(detectAndConvertTimestamp(0.1)).toBeNull(); expect(detectAndConvertTimestamp(1)).toBeNull(); }); }); });

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/amittell/firewalla-mcp-server'

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