import { describe, test, expect } from 'vitest'; import { Gallery } from './Gallery'; const toHtml = (Gallery as any).toHtml; describe('Gallery.toHtml lightbox uses a delegated listener, not per-item onclick (A4.3)', () => { test('no per-item inline onclick with interpolated src', () => { const { html } = toHtml({ images: [{ src: '/a.jpg', alt: 'a' }], lightbox: true }, ''); expect(html).not.toMatch(/onclick="[^"]*_open\(/); expect(html).toContain('data-lb-src="/a.jpg"'); }); test('a single-quote in src cannot break the handler (no per-item onclick at all)', () => { const { html } = toHtml({ images: [{ src: "/a'.jpg", alt: 'a' }], lightbox: true }, ''); // no per-item onclick handler exists at all (delegated listener only) expect(html).not.toMatch(/onclick="[^"]*_open\(/); // the quote in src is entity-escaped in the data attribute, not raw expect(html).toContain('data-lb-src="/a'.jpg"'); expect(html).not.toContain(`data-lb-src="/a'.jpg"`); }); test('emits exactly one delegated click listener', () => { const { html } = toHtml({ images: [{ src: '/a.jpg' }, { src: '/b.jpg' }], lightbox: true }, ''); const matches = html.match(/addEventListener\(['"]click['"]/g) || []; expect(matches.length).toBe(1); }); test('lightbox=false: no data-lb-src, no script', () => { const { html } = toHtml({ images: [{ src: '/a.jpg' }], lightbox: false }, ''); expect(html).not.toContain('data-lb-src'); expect(html).not.toContain('