@@ -1525,3 +1525,47 @@ describe('deterministicRandom', () => {
15251525 expect ( a ) . not . toBe ( b ) ;
15261526 } ) ;
15271527} ) ;
1528+
1529+ describe ( 'SVG Structural Validity and Cleanliness' , ( ) => {
1530+ const mockStats : StreakStats = {
1531+ currentStreak : 5 ,
1532+ longestStreak : 10 ,
1533+ totalContributions : 100 ,
1534+ todayDate : '2024-06-12' ,
1535+ } ;
1536+ const mockCalendar = {
1537+ weeks : [
1538+ {
1539+ contributionDays : [
1540+ { contributionCount : 0 , date : '2024-06-10' } ,
1541+ { contributionCount : 5 , date : '2024-06-11' } ,
1542+ { contributionCount : 15 , date : '2024-06-12' } ,
1543+ ] ,
1544+ } ,
1545+ ] ,
1546+ } as ContributionCalendar ;
1547+
1548+ it ( 'generateSVG output contains exactly one root <svg> element and exactly one closing </svg> tag' , ( ) => {
1549+ const svg = generateSVG ( mockStats , { user : 'avi' } as unknown as BadgeParams , mockCalendar ) ;
1550+ const openCount = ( svg . match ( / < s v g / gi) || [ ] ) . length ;
1551+ const closeCount = ( svg . match ( / < \/ s v g > / gi) || [ ] ) . length ;
1552+ expect ( openCount ) . toBe ( 1 ) ;
1553+ expect ( closeCount ) . toBe ( 1 ) ;
1554+ } ) ;
1555+
1556+ it ( 'generateSVG output contains exactly one style block' , ( ) => {
1557+ const svg = generateSVG ( mockStats , { user : 'avi' } as unknown as BadgeParams , mockCalendar ) ;
1558+ const styleOpenCount = ( svg . match ( / < s t y l e > / gi) || [ ] ) . length ;
1559+ const styleCloseCount = ( svg . match ( / < \/ s t y l e > / gi) || [ ] ) . length ;
1560+ expect ( styleOpenCount ) . toBe ( 1 ) ;
1561+ expect ( styleCloseCount ) . toBe ( 1 ) ;
1562+ } ) ;
1563+
1564+ it ( 'generateSVG does not contain duplicate renderHeader or renderStyle outputs' , ( ) => {
1565+ const svg = generateSVG ( mockStats , { user : 'avi' } as unknown as BadgeParams , mockCalendar ) ;
1566+ const titleCount = ( svg . match ( / < t i t l e i d = " c p - t i t l e - a v i " > / g) || [ ] ) . length ;
1567+ expect ( titleCount ) . toBe ( 1 ) ;
1568+ const styleImportCount = ( svg . match ( / @ i m p o r t u r l / g) || [ ] ) . length ;
1569+ expect ( styleImportCount ) . toBe ( 1 ) ;
1570+ } ) ;
1571+ } ) ;
0 commit comments