diff --git a/lib/validations.test.ts b/lib/validations.test.ts index 1aa1b4e90..8d406b166 100644 --- a/lib/validations.test.ts +++ b/lib/validations.test.ts @@ -26,6 +26,7 @@ describe('streakParamsSchema — grace fallback behavior', () => { expect(parse({}).grace).toBe(1); }); }); + describe('githubParamsSchema', () => { it('should pass when username is valid', () => { const result = githubParamsSchema.safeParse({ @@ -76,6 +77,7 @@ describe('githubParamsSchema', () => { } }); }); + describe('streakParamsSchema user validation', () => { it('should pass when user is valid', () => { const result = streakParamsSchema.safeParse({ @@ -295,6 +297,7 @@ describe('streakParamsSchema', () => { expect(result.error.issues[0]?.message).toBe('Invalid GitHub username'); } }); + it('should accept delta_format percent', () => { const result = streakParamsSchema.safeParse({ user: 'octocat', @@ -450,6 +453,7 @@ describe('streakParamsSchema — size fallback behavior', () => { it('falls back to "medium" for empty string', () => { expect(parse({ size: '' }).size).toBe('medium'); }); + it('should accept org parameter when provided', () => { const result = streakParamsSchema.safeParse({ user: 'octocat', @@ -737,16 +741,23 @@ describe('streakParamsSchema — accent parameter HEX color validation', () => { }); }); +/* ========================================================================== + * DATE RANGE BOUNDARY ROBUSTNESS (VARIATION 1) + * ========================================================================== */ + describe('streakParamsSchema — Date Range Boundary Robustness (Variation 1)', () => { it('should process validation safely and fallback when partial or missing year parameters are passed', () => { + // Arrange: Provide a mock payload missing a full YYYY format sequence const partialYearPayload = { user: 'octocat', from: '05-12', to: '05-30', }; + // Act: Pass the object through the validator schema matrix const result = streakParamsSchema.safeParse(partialYearPayload); + // Assert: The validator handles it safely using implicit date engine fallbacks expect(result.success).toBe(true); if (result.success) { expect(result.data.from).toBeDefined(); @@ -755,12 +766,15 @@ describe('streakParamsSchema — Date Range Boundary Robustness (Variation 1)', }); it('should pass cleanly and fallback to default ranges when date bounds are completely omitted', () => { + // Arrange: Pass only the bare minimum required parameters const minimalPayload = { user: 'octocat', }; + // Act const result = streakParamsSchema.safeParse(minimalPayload); + // Assert: Verify that omitted range options return undefined to use downstream defaults smoothly expect(result.success).toBe(true); if (result.success) { expect(result.data.from).toBeUndefined(); diff --git a/utils/time.test.ts b/utils/time.test.ts index 14e9bfb99..6505c7410 100644 --- a/utils/time.test.ts +++ b/utils/time.test.ts @@ -221,6 +221,38 @@ describe('getSecondsUntilMidnightInTimezone', () => { expect(secondsUTC).toBe(86400); expect(secondsLondon).toBe(86400); }); + + it('should handle extreme negative timezone offset boundary (-12:00)', () => { + // Arrange: Etc/GMT+12 is UTC-12 (Baker Island / Howland Island). + // When UTC is Jan 1, 11:59:50, Baker Island is Dec 31, 23:59:50 (10 seconds to midnight) + const boundaryTime = new Date(Date.UTC(2024, 0, 1, 11, 59, 50)); + vi.setSystemTime(boundaryTime); + + // Act + const seconds = getSecondsUntilMidnightInTimezone('Etc/GMT+12'); + + // Assert: Should correctly calculate 10 seconds without calendar shifting + expect(seconds).toBe(10); + }); + + it('should handle extreme timezone offsets without calendar date shifting', () => { + // Arrange: Test the most extreme offsets to ensure no calendar date shifting occurs + const extremeOffsets = [ + { tz: 'Etc/GMT+12', offset: -12, utcHour: 12, expectedLocalHour: 0 }, // UTC-12 + { tz: 'Etc/GMT-14', offset: 14, utcHour: 10, expectedLocalHour: 0 }, // UTC+14 + ]; + + for (const { tz, utcHour, expectedLocalHour } of extremeOffsets) { + // Set UTC time such that local time is exactly midnight + vi.setSystemTime(new Date(Date.UTC(2024, 6, 15, utcHour, 0, 0))); + + // Act: Get seconds until midnight in this timezone + const seconds = getSecondsUntilMidnightInTimezone(tz); + + // Assert: At local midnight, should return exactly 86400 seconds (full day) + expect(seconds).toBe(86400); + } + }); }); describe('getSecondsUntilUTCMidnight — sliding window boundary robustness', () => {