import { describe, expect, test, vi } from 'vitest'; import { lookupTxt, parseDidFromTxt } from '../src/dns.js'; describe('dns', () => { describe('parseDidFromTxt', () => { test('extracts DID from TXT record value', () => { expect(parseDidFromTxt('did=did:plc:xyz123')).toBe('did:plc:xyz123'); }); test('handles quoted TXT record', () => { expect(parseDidFromTxt('"did=did:plc:xyz123"')).toBe('did:plc:xyz123'); }); test('returns null for invalid format', () => { expect(parseDidFromTxt('invalid')).toBeNull(); }); test('returns null for empty string', () => { expect(parseDidFromTxt('')).toBeNull(); }); test('returns null for invalid DID format', () => { expect(parseDidFromTxt('did=not-a-valid-did')).toBeNull(); expect(parseDidFromTxt('did=did:')).toBeNull(); // Missing method and specific-id expect(parseDidFromTxt('did=did:plc:')).toBeNull(); // Missing specific-id }); test('accepts valid did:web format', () => { expect(parseDidFromTxt('did=did:web:example.com')).toBe( 'did:web:example.com', ); }); }); describe('lookupTxt', () => { test('fetches TXT records via DoH', async () => { const mockFetch = vi.fn().mockResolvedValue({ ok: true, json: () => Promise.resolve({ Answer: [ { type: 16, data: '"did=did:plc:z72i7hdynmk6r22z27h6tvur"' }, ], }), }); const records = await lookupTxt('_atproto.bsky.app', { fetch: mockFetch, }); expect(mockFetch).toHaveBeenCalledWith( 'https://cloudflare-dns.com/dns-query?name=_atproto.bsky.app&type=TXT', expect.objectContaining({ headers: { Accept: 'application/dns-json' }, }), ); expect(records).toEqual(['did=did:plc:z72i7hdynmk6r22z27h6tvur']); }); test('returns empty array on network error', async () => { const mockFetch = vi.fn().mockRejectedValue(new Error('Network error')); const records = await lookupTxt('_atproto.example.com', { fetch: mockFetch, }); expect(records).toEqual([]); }); test('returns empty array when no Answer', async () => { const mockFetch = vi.fn().mockResolvedValue({ ok: true, json: () => Promise.resolve({}), }); const records = await lookupTxt('_atproto.example.com', { fetch: mockFetch, }); expect(records).toEqual([]); }); test('returns empty array on HTTP error response', async () => { const mockFetch = vi.fn().mockResolvedValue({ ok: false, status: 500, }); const records = await lookupTxt('_atproto.example.com', { fetch: mockFetch, }); expect(records).toEqual([]); }); }); });