From b9c594f34f205fd6bccfe462bb60e4e1cab51936 Mon Sep 17 00:00:00 2001 From: Sourav Jha Date: Fri, 29 May 2026 10:22:40 +0530 Subject: [PATCH 1/5] test(ComparisonStatsCard): verify progress bar split for equal values --- components/dashboard/ComparisonStatsCard.test.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/components/dashboard/ComparisonStatsCard.test.tsx b/components/dashboard/ComparisonStatsCard.test.tsx index 6931b59b..ca527fc3 100644 --- a/components/dashboard/ComparisonStatsCard.test.tsx +++ b/components/dashboard/ComparisonStatsCard.test.tsx @@ -138,6 +138,11 @@ describe('ComparisonStatsCard', () => { /> ); +const progressSegments = container.querySelectorAll( + '.w-full.bg-gray-700\\/50 div, .relative div' + ); + + const allDivs = Array.from(container.querySelectorAll('div')); const emeraldElement = container.querySelector('[className*="emerald"]') || container.querySelector('.text-emerald-400'); From 8fa91c7f56ee5788fa4ef141a0d6e7c72e118e2a Mon Sep 17 00:00:00 2001 From: KANISHKA GUPTA Date: Fri, 29 May 2026 12:26:35 +0530 Subject: [PATCH 2/5] final resolved --- components/dashboard/DashboardClient.test.tsx | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/components/dashboard/DashboardClient.test.tsx b/components/dashboard/DashboardClient.test.tsx index cc9e5bf7..a31a8d7e 100644 --- a/components/dashboard/DashboardClient.test.tsx +++ b/components/dashboard/DashboardClient.test.tsx @@ -202,6 +202,22 @@ const mockPeriod = { year: '2026', }; +const initialDataWithHigherStreak = { + ...mockInitialData, + stats: { + ...mockInitialData.stats, + peakStreak: 50, + }, +}; + +const secondDataWithLowerStreak = { + ...mockSecondData, + stats: { + ...mockSecondData.stats, + peakStreak: 10, + }, +}; + describe('DashboardClient', () => { beforeEach(() => { vi.restoreAllMocks(); @@ -444,3 +460,27 @@ it('shows Most Consistent badge for profile with higher peak streak in compare m expect(screen.getByText(/Most Consistent/i)).toBeDefined(); }); +it('shows Most Consistent badge for profile with higher peak streak in compare mode', async () => { + const mockFetch = vi.fn().mockResolvedValue({ + ok: true, + json: async () => secondDataWithLowerStreak, + }); + + vi.stubGlobal('fetch', mockFetch); + + render(); + + fireEvent.click(screen.getByText('Compare Profile')); + + fireEvent.change(screen.getByPlaceholderText('Enter GitHub Username'), { + target: { value: 'JhaSourav07' }, + }); + + fireEvent.click(screen.getByText('Compare')); + + await waitFor(() => { + expect(screen.getByText('Exit Compare Mode')).toBeDefined(); + }); + + expect(screen.getByText(/Most Consistent/i)).toBeDefined(); +}); From 7dab07a197e4fd1c687d34f86b7e6dacc6837ed6 Mon Sep 17 00:00:00 2001 From: Abduldiyan Deshmukh Date: Fri, 29 May 2026 11:45:42 +0530 Subject: [PATCH 3/5] test(dashboard): verified that compare modal input can be cleared --- components/dashboard/DashboardClient.test.tsx | 86 ++++++------------- 1 file changed, 24 insertions(+), 62 deletions(-) diff --git a/components/dashboard/DashboardClient.test.tsx b/components/dashboard/DashboardClient.test.tsx index a31a8d7e..2489da61 100644 --- a/components/dashboard/DashboardClient.test.tsx +++ b/components/dashboard/DashboardClient.test.tsx @@ -178,22 +178,6 @@ const mockSecondData = { graphData: { nodes: [], links: [] }, }; -const initialDataWithHigherStreak = { - ...mockInitialData, - stats: { - ...mockInitialData.stats, - peakStreak: 50, - }, -}; - -const secondDataWithLowerStreak = { - ...mockSecondData, - stats: { - ...mockSecondData.stats, - peakStreak: 10, - }, -}; - const mockPeriod = { kind: 'year' as const, label: '2026', @@ -343,6 +327,7 @@ describe('DashboardClient', () => { const generateLink = screen.getByRole('link', { name: /generate your own/i }); expect(generateLink.getAttribute('href')).toBe('/'); }); + // ========================================================================= // ISSUE OBJECTIVE: Verify error is shown when comparing with same username // ========================================================================= @@ -429,58 +414,35 @@ describe('DashboardClient', () => { const tags = screen.getAllByText(/Consistency Beast/i); expect(tags).toHaveLength(2); }); -}); -it('shows Most Consistent badge for profile with higher peak streak in compare mode', async () => { - const mockFetch = vi.fn().mockResolvedValue({ - ok: true, - json: async () => secondDataWithLowerStreak, - }); - - vi.stubGlobal('fetch', mockFetch); - - render( - - ); - - fireEvent.click(screen.getByText('Compare Profile')); - - fireEvent.change(screen.getByPlaceholderText('Enter GitHub Username'), { - target: { value: 'JhaSourav07' }, - }); - - fireEvent.click(screen.getByText('Compare')); - await waitFor(() => { - expect(screen.getByText('Exit Compare Mode')).toBeDefined(); - }); + it('shows Most Consistent badge for profile with higher peak streak in compare mode', async () => { + const mockFetch = vi.fn().mockResolvedValue({ + ok: true, + json: async () => secondDataWithLowerStreak, + }); - expect(screen.getByText(/Most Consistent/i)).toBeDefined(); -}); -it('shows Most Consistent badge for profile with higher peak streak in compare mode', async () => { - const mockFetch = vi.fn().mockResolvedValue({ - ok: true, - json: async () => secondDataWithLowerStreak, - }); + vi.stubGlobal('fetch', mockFetch); - vi.stubGlobal('fetch', mockFetch); + render( + + ); - render(); + fireEvent.click(screen.getByText('Compare Profile')); - fireEvent.click(screen.getByText('Compare Profile')); + fireEvent.change(screen.getByPlaceholderText('Enter GitHub Username'), { + target: { value: 'JhaSourav07' }, + }); - fireEvent.change(screen.getByPlaceholderText('Enter GitHub Username'), { - target: { value: 'JhaSourav07' }, - }); + fireEvent.click(screen.getByText('Compare')); - fireEvent.click(screen.getByText('Compare')); + await waitFor(() => { + expect(screen.getByText('Exit Compare Mode')).toBeDefined(); + }); - await waitFor(() => { - expect(screen.getByText('Exit Compare Mode')).toBeDefined(); + expect(screen.getByText(/Most Consistent/i)).toBeDefined(); }); - - expect(screen.getByText(/Most Consistent/i)).toBeDefined(); -}); +}); \ No newline at end of file From 5f9a0997dbb376000da643ac8f4d82985692db22 Mon Sep 17 00:00:00 2001 From: Naveen-9-9 Date: Fri, 29 May 2026 13:08:14 +0530 Subject: [PATCH 4/5] feat(ui): add parallax background effect for card preview --- app/components/navbar.tsx | 10 +++++----- components/InteractiveViewer.test.tsx | 2 +- components/InteractiveViewer.tsx | 5 +++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/app/components/navbar.tsx b/app/components/navbar.tsx index 5b466f9b..7af72fae 100644 --- a/app/components/navbar.tsx +++ b/app/components/navbar.tsx @@ -154,10 +154,10 @@ export default function Navbar() { > {mounted ? ( isDark ? ( - + ) : ( {mounted ? ( isDark ? ( - + ) : ( ) diff --git a/components/InteractiveViewer.test.tsx b/components/InteractiveViewer.test.tsx index db2e52ac..009538cf 100644 --- a/components/InteractiveViewer.test.tsx +++ b/components/InteractiveViewer.test.tsx @@ -600,4 +600,4 @@ describe('InteractiveViewer', () => { expect(glowLayer).toBeTruthy(); }); }); -}); +}); \ No newline at end of file diff --git a/components/InteractiveViewer.tsx b/components/InteractiveViewer.tsx index 8fb8d314..dcedb4d1 100644 --- a/components/InteractiveViewer.tsx +++ b/components/InteractiveViewer.tsx @@ -22,7 +22,7 @@ interface ParallaxParticle { } /** Builds a stable set of contribution-square particles for the parallax layer. - * Deterministic math prevents random values from causing SSR/CSR mismatches. */ + * Deterministic math prevents random values from causing SSR/CSR mismatches. */ function buildParticles(): ParallaxParticle[] { const colors = ['#10b981', '#8b5cf6', '#06b6d4', '#3b82f6', '#f59e0b']; return Array.from( @@ -110,6 +110,7 @@ export default function InteractiveViewer({ const activeTooltipRef = useRef(null); const startPointerPos = useRef({ x: 0, y: 0 }); const [mounted, setMounted] = useState(false); + useEffect(() => { // eslint-disable-next-line react-hooks/set-state-in-effect setMounted(true); @@ -455,4 +456,4 @@ export default function InteractiveViewer({ )} ); -} +} \ No newline at end of file From adb7eabda7c0057b813e50ab0c73192ac9b733c6 Mon Sep 17 00:00:00 2001 From: swarupio Date: Sun, 31 May 2026 01:08:56 +0530 Subject: [PATCH 5/5] test(cache): verify TTLCache behavior for infinite TTL value (#1400) --- lib/cache.test.ts | 56 ++++++++++++++++++++--------------------------- 1 file changed, 24 insertions(+), 32 deletions(-) diff --git a/lib/cache.test.ts b/lib/cache.test.ts index 82953239..ae99b622 100644 --- a/lib/cache.test.ts +++ b/lib/cache.test.ts @@ -226,11 +226,9 @@ describe('TTLCache', () => { const cache = new TTLCache(); cache.set('user', 'octocat', 5_000); - // Check at 1 second (before expiry at 5 seconds) vi.advanceTimersByTime(1_000); expect(cache.get('user')).toBe('octocat'); - // Check at 4 seconds (still before expiry) vi.advanceTimersByTime(3_000); expect(cache.get('user')).toBe('octocat'); @@ -242,28 +240,24 @@ describe('TTLCache', () => { const cache = new TTLCache(); cache.set('user', 'octocat', 5_000); - // Advance exactly to TTL expiry time - // At this point Date.now() === expiresAt, so > check fails and value is returned vi.advanceTimersByTime(5_000); expect(cache.get('user')).toBe('octocat'); cache.destroy(); }); + it('returns correct values around the exact TTL boundary', () => { vi.useFakeTimers(); const cache = new TTLCache(); cache.set('key', 'value', 1000); - // 999ms -> still valid vi.advanceTimersByTime(999); expect(cache.get('key')).toBe('value'); - // 1000ms exact boundary -> still valid vi.advanceTimersByTime(1); expect(cache.get('key')).toBe('value'); - // 1001ms -> expired vi.advanceTimersByTime(1); expect(cache.get('key')).toBeNull(); @@ -275,7 +269,6 @@ describe('TTLCache', () => { const cache = new TTLCache(); cache.set('user', 'octocat', 5_000); - // Advance just past TTL expiry time vi.advanceTimersByTime(5_001); expect(cache.get('user')).toBeNull(); @@ -329,18 +322,11 @@ describe('TTLCache', () => { const cache = new TTLCache(); cache.set('user', 'octocat', 5_000); - // Advance to 3 seconds (before expiry) vi.advanceTimersByTime(3_000); - - // Overwrite the key with a new 5-second TTL cache.set('user', 'new-octocat', 5_000); - - // Advance another 3 seconds (total 6 seconds, but only 3 since last set) vi.advanceTimersByTime(3_000); - // Should still be available because TTL was reset expect(cache.get('user')).toBe('new-octocat'); - cache.destroy(); }); @@ -349,18 +335,11 @@ describe('TTLCache', () => { const cache = new TTLCache(); cache.set('user', 'octocat', 5_000); - // Advance to 3 seconds vi.advanceTimersByTime(3_000); - - // Overwrite with new 2-second TTL cache.set('user', 'new-octocat', 2_000); - - // Advance another 3 seconds (total 6 from start, 3 from new set) vi.advanceTimersByTime(3_000); - // Should be expired because new TTL (2s) has passed expect(cache.get('user')).toBeNull(); - cache.destroy(); }); }); @@ -515,7 +494,7 @@ describe('TTLCache', () => { }); describe('edge cases and error handling', () => { - // FIX: New test explicitly targeting the -5000 boundary for Issue #1398 + // FIX: Test targeting the -5000 boundary for Issue #1398 it('throws RangeError when setting a value with -5000 TTL', () => { const cache = new TTLCache(); expect(() => cache.set('key', 'value', -5000)).toThrow(RangeError); @@ -529,6 +508,26 @@ describe('TTLCache', () => { cache.set(null as unknown as string, 'value', 60_000); }).toThrow(TypeError); expect(cache.size()).toBe(0); + cache.destroy(); + }); + + // FIX: New test targeting the Infinity boundary for Issue #1400 + it('caps Infinity TTL to a realistic maximum threshold without throwing', () => { + vi.useFakeTimers(); + const cache = new TTLCache(); + + // Should handle Infinity gracefully without throwing errors + expect(() => cache.set('infinity-key', 'value', Infinity)).not.toThrow(); + + // The item should be successfully stored and retrievable + expect(cache.get('infinity-key')).toBe('value'); + + // Advance by a large safe amount (e.g., 30 days) to ensure it stays valid + // or gets capped safely without overflowing internal Date math + vi.advanceTimersByTime(1000 * 60 * 60 * 24 * 30); + + // Assert it didn't break down internally and returns a clean result (either still alive or gracefully expired) + expect(['value', null]).toContain(cache.get('infinity-key')); cache.destroy(); }); @@ -598,12 +597,8 @@ describe('TTLCache', () => { vi.useFakeTimers(); const cache = new TTLCache(); cache.set('short', 'lived', 1); - // Immediately at creation time, should exist expect(cache.get('short')).toBe('lived'); - // Advance 1ms vi.advanceTimersByTime(1); - // Now it should be expired or at boundary - // (depends on exact timing, but get() should handle it gracefully) const result = cache.get('short'); expect([null, 'lived']).toContain(result); cache.destroy(); @@ -611,21 +606,17 @@ describe('TTLCache', () => { it('does not throw when ttlMs is Number.EPSILON', () => { const cache = new TTLCache(); - expect(() => { cache.set('key', 'value', Number.EPSILON); }).not.toThrow(); - cache.destroy(); }); it('does not throw when ttlMs is a very small positive number', () => { const cache = new TTLCache(); - expect(() => { cache.set('key', 'value', 0.0001); }).not.toThrow(); - cache.destroy(); }); @@ -641,6 +632,7 @@ describe('TTLCache', () => { cache.destroy(); }); + // FIX: New test targeting the NaN boundary for Issue #1399 it('resolves NaN TTL to the default standard TTL duration', () => { vi.useFakeTimers(); @@ -795,4 +787,4 @@ describe('DistributedCache', () => { ); cache.destroy(); }); -}); +}); \ No newline at end of file