From a7c70d34bcf99459873021feb351c7c2eb1d48cb Mon Sep 17 00:00:00 2001 From: Aditya8369 Date: Sun, 9 Aug 2026 19:31:13 +0530 Subject: [PATCH 1/2] feat: Interactive SVG Tower Tooltips --- .../generator.interactive-tooltips.test.ts | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 lib/svg/generator.interactive-tooltips.test.ts diff --git a/lib/svg/generator.interactive-tooltips.test.ts b/lib/svg/generator.interactive-tooltips.test.ts new file mode 100644 index 000000000..1a7d15e8b --- /dev/null +++ b/lib/svg/generator.interactive-tooltips.test.ts @@ -0,0 +1,68 @@ +// lib/svg/generator.interactive-tooltips.test.ts + +import { describe, it, expect } from 'vitest'; +import { generateSVG } from './generator'; +import type { BadgeParams, ContributionCalendar, StreakStats } from '../types'; + +const mockStats: StreakStats = { + currentStreak: 5, + longestStreak: 12, + totalContributions: 150, + todayDate: '2024-10-26', +}; + +const mockCalendar: ContributionCalendar = { + weeks: [ + { + contributionDays: [ + { contributionCount: 5, date: '2024-10-26', locAdditions: 100, locDeletions: 20 }, + { contributionCount: 0, date: '2024-10-27', locAdditions: 0, locDeletions: 0 }, + ], + }, + ], +}; + +describe('Interactive SVG Tower Tooltips', () => { + it('wraps each tower within a group tag with cp-tower and interactive-tower classes', () => { + const svg = generateSVG(mockStats, { user: 'octocat' } as unknown as BadgeParams, mockCalendar); + + expect(svg).toContain('class="cp-tower interactive-tower"'); + expect(svg).toMatch(/data-date="2024-10-26"/); + expect(svg).toMatch(/data-count="5"/); + }); + + it('includes a native tooltip element inside each tower group displaying date and contributions', () => { + const svg = generateSVG(mockStats, { user: 'octocat' } as unknown as BadgeParams, mockCalendar); + + expect(svg).toContain('<title>TODAY: Oct 26: 5 commits'); + }); + + it('escapes XML reserved characters in tower tooltip elements', () => { + const calendarWithUnsafeDate: ContributionCalendar = { + weeks: [ + { + contributionDays: [ + { contributionCount: 3, date: '2024-06-12 & ', locAdditions: 0, locDeletions: 0 }, + ], + }, + ], + }; + + const svg = generateSVG( + mockStats, + { user: 'octocat' } as unknown as BadgeParams, + calendarWithUnsafeDate + ); + + expect(svg).toContain('data-date="2024-06-12 & <bad>"'); + expect(svg).toContain('TODAY: Jun 12: 3 commits'); + }); + + it('includes interactive CSS hover rules (.interactive-tower:hover) in SVG style block', () => { + const svg = generateSVG(mockStats, { user: 'octocat' } as unknown as BadgeParams, mockCalendar); + + expect(svg).toContain('.interactive-tower'); + expect(svg).toContain('.interactive-tower:hover'); + expect(svg).toContain('transform: translateY(-4px)'); + }); +}); From aaf06f4ce4a5b0301f524a7ab8aab9509d6c7962 Mon Sep 17 00:00:00 2001 From: Aditya8369 Date: Sun, 9 Aug 2026 20:26:17 +0530 Subject: [PATCH 2/2] fixes --- lib/svg/generator.interactive-tooltips.test.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/svg/generator.interactive-tooltips.test.ts b/lib/svg/generator.interactive-tooltips.test.ts index 1a7d15e8b..d33d000c8 100644 --- a/lib/svg/generator.interactive-tooltips.test.ts +++ b/lib/svg/generator.interactive-tooltips.test.ts @@ -2,7 +2,7 @@ import { describe, it, expect } from 'vitest'; import { generateSVG } from './generator'; -import type { BadgeParams, ContributionCalendar, StreakStats } from '../types'; +import type { BadgeParams, ContributionCalendar, StreakStats } from '../../types'; const mockStats: StreakStats = { currentStreak: 5, @@ -12,6 +12,7 @@ const mockStats: StreakStats = { }; const mockCalendar: ContributionCalendar = { + totalContributions: 5, weeks: [ { contributionDays: [ @@ -39,6 +40,7 @@ describe('Interactive SVG Tower Tooltips', () => { it('escapes XML reserved characters in tower tooltip elements', () => { const calendarWithUnsafeDate: ContributionCalendar = { + totalContributions: 3, weeks: [ { contributionDays: [