|
1 | 1 | import { describe, it, expect } from 'vitest'; |
2 | | -import { generateSVG, generateMonthlySVG, particleCount } from './generator'; |
| 2 | +import { generateSVG, generateMonthlySVG, particleCount, escapeXML } from './generator'; |
3 | 3 | import type { BadgeParams, ContributionCalendar, StreakStats, MonthlyStats } from '../../types'; |
4 | 4 |
|
5 | 5 | describe('generateSVG', () => { |
@@ -483,6 +483,39 @@ describe('generateMonthlySVG', () => { |
483 | 483 | }); |
484 | 484 | }); |
485 | 485 |
|
| 486 | +describe('escapeXML', () => { |
| 487 | + it('escapes ampersands (&)', () => { |
| 488 | + expect(escapeXML('foo & bar')).toBe('foo & bar'); |
| 489 | + }); |
| 490 | + |
| 491 | + it('escapes less-than signs (<)', () => { |
| 492 | + expect(escapeXML('<div>')).toBe('<div>'); |
| 493 | + }); |
| 494 | + |
| 495 | + it('escapes greater-than signs (>)', () => { |
| 496 | + expect(escapeXML('a > b')).toBe('a > b'); |
| 497 | + }); |
| 498 | + |
| 499 | + it('escapes double quotes (")', () => { |
| 500 | + expect(escapeXML('class="btn"')).toBe('class="btn"'); |
| 501 | + }); |
| 502 | + |
| 503 | + it("escapes single quotes (')", () => { |
| 504 | + expect(escapeXML("it's working")).toBe('it's working'); |
| 505 | + }); |
| 506 | + |
| 507 | + it('escapes a string combining all five special characters', () => { |
| 508 | + const combined = `<element attr="val" data-quote='yes'>&</element>`; |
| 509 | + const expected = `<element attr="val" data-quote='yes'>&</element>`; |
| 510 | + expect(escapeXML(combined)).toBe(expected); |
| 511 | + }); |
| 512 | + |
| 513 | + it('leaves a safe string unchanged', () => { |
| 514 | + const safe = 'Hello World 123!@#%^*()_+-=[]{}|;:,./?`~'; |
| 515 | + expect(escapeXML(safe)).toBe(safe); |
| 516 | + }); |
| 517 | +}); |
| 518 | + |
486 | 519 | describe('particleCount', () => { |
487 | 520 | it('returns 0 when count is 0', () => { |
488 | 521 | expect(particleCount(0)).toBe(0); |
|
0 commit comments