import { describe, expect, it } from 'vitest'; import { safeLinkTargetUrl } from '../src/lib/url'; describe('safeLinkTargetUrl', () => { it('returns http and https URLs unchanged', () => { expect(safeLinkTargetUrl('https://example.com')).toBe('https://example.com'); expect(safeLinkTargetUrl('http://example.com/path?q=1')).toBe('http://example.com/path?q=1'); }); it('is case-insensitive for the scheme', () => { expect(safeLinkTargetUrl('HTTPS://Example.COM')).toBe('HTTPS://Example.COM'); expect(safeLinkTargetUrl('HtTp://example.com')).toBe('HtTp://example.com'); }); it('returns null for javascript: URLs', () => { expect(safeLinkTargetUrl('javascript:alert(1)')).toBeNull(); }); it('returns null for data: URLs', () => { expect(safeLinkTargetUrl('data:text/html,')).toBeNull(); }); it('returns null for other non-http schemes', () => { expect(safeLinkTargetUrl('mailto:foo@bar.com')).toBeNull(); expect(safeLinkTargetUrl('ftp://example.com')).toBeNull(); expect(safeLinkTargetUrl('file:///etc/passwd')).toBeNull(); }); it('returns null for scheme-relative and protocol-relative URLs', () => { expect(safeLinkTargetUrl('//example.com')).toBeNull(); expect(safeLinkTargetUrl('/local/path')).toBeNull(); }); it('returns null for null and empty input', () => { expect(safeLinkTargetUrl(null)).toBeNull(); expect(safeLinkTargetUrl('')).toBeNull(); }); it('returns null for whitespace-only or malformed input', () => { expect(safeLinkTargetUrl(' ')).toBeNull(); expect(safeLinkTargetUrl('example.com')).toBeNull(); }); });