chadtmiller.com/pds.js
An atproto PDS in JavaScript, for Cloudflare Workers and Node
0
0
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([]);
});
});
});