|
| 1 | +/** |
| 2 | + * @vitest-environment node |
| 3 | + */ |
| 4 | +import { createHash } from 'node:crypto' |
| 5 | +import { renderToStaticMarkup } from 'react-dom/server' |
| 6 | +import { describe, expect, it } from 'vitest' |
| 7 | +import { GoogleIcon } from '@/components/icons' |
| 8 | + |
| 9 | +const PNG_DATA_URI_PATTERN = /href="data:image\/png;base64,([^"]+)"/g |
| 10 | +const GOOGLE_ICON_PNG_SHA256 = 'd1ce9c2af0b10a7333abc99bc706f9a6a199e5b65bf3e3009624f076b8638e6a' |
| 11 | + |
| 12 | +function getEmbeddedPng(markup: string): Buffer { |
| 13 | + const match = PNG_DATA_URI_PATTERN.exec(markup) |
| 14 | + expect(match).not.toBeNull() |
| 15 | + PNG_DATA_URI_PATTERN.lastIndex = 0 |
| 16 | + return Buffer.from(match?.[1] ?? '', 'base64') |
| 17 | +} |
| 18 | + |
| 19 | +describe('GoogleIcon', () => { |
| 20 | + it('renders the exact official transparent artwork and forwards SVG props', () => { |
| 21 | + const markup = renderToStaticMarkup( |
| 22 | + <GoogleIcon className='google-icon' data-testid='google-icon' aria-label='Google' /> |
| 23 | + ) |
| 24 | + |
| 25 | + expect(markup).toContain('viewBox="0 0 204 204"') |
| 26 | + expect(markup).toContain('width="24"') |
| 27 | + expect(markup).toContain('height="24"') |
| 28 | + expect(markup).toContain('class="google-icon"') |
| 29 | + expect(markup).toContain('data-testid="google-icon"') |
| 30 | + expect(markup).toContain('aria-label="Google"') |
| 31 | + expect(markup).toContain('<image') |
| 32 | + expect(markup).toContain('width="200"') |
| 33 | + expect(markup).toContain('height="204"') |
| 34 | + expect(markup).toContain('preserveAspectRatio="xMinYMin meet"') |
| 35 | + |
| 36 | + const png = getEmbeddedPng(markup) |
| 37 | + expect(png).toHaveLength(33_661) |
| 38 | + expect(png.subarray(0, 8)).toEqual(Buffer.from([137, 80, 78, 71, 13, 10, 26, 10])) |
| 39 | + expect(png.readUInt32BE(16)).toBe(200) |
| 40 | + expect(png.readUInt32BE(20)).toBe(204) |
| 41 | + expect(createHash('sha256').update(png).digest('hex')).toBe(GOOGLE_ICON_PNG_SHA256) |
| 42 | + }) |
| 43 | + |
| 44 | + it('avoids the WebKit-fragile SVG paint stack across multiple instances', () => { |
| 45 | + const markup = renderToStaticMarkup( |
| 46 | + <> |
| 47 | + <GoogleIcon /> |
| 48 | + <GoogleIcon /> |
| 49 | + </> |
| 50 | + ) |
| 51 | + |
| 52 | + expect(markup.match(/<svg\b/g)).toHaveLength(2) |
| 53 | + expect(markup.match(/<image\b/g)).toHaveLength(2) |
| 54 | + expect(markup.match(PNG_DATA_URI_PATTERN)).toHaveLength(2) |
| 55 | + expect(markup).not.toMatch(/<(?:foreignObject|mask|filter|clipPath)\b/) |
| 56 | + expect(markup).not.toContain('conic-gradient') |
| 57 | + expect(markup).not.toContain('url(#') |
| 58 | + expect(markup).not.toMatch(/\sid=/) |
| 59 | + }) |
| 60 | +}) |
0 commit comments