/** * Smoke tests for dns-propagation.js * Verifies DNS propagation checker module loads, exposes the expected * interface, and basic methods (verifyRecord, startVerification, * getVerificationStatus, getAllVerifications, cleanup) work without throwing. */ // The module does `const dns = require('dns').promises;` then `new dns.Resolver()`. // We mock the dns module so that .promises exposes our Resolver class. jest.mock('dns', () => { class MockResolver { setServers() { return this; } setTimeout() { return this; } resolve4(domain) { if (domain === 'propagated.sami') { return Promise.resolve(['1.2.3.4']); } return Promise.resolve(['9.9.9.9']); } } return { promises: { Resolver: MockResolver }, Resolver: MockResolver, }; }); const DNSPropagationChecker = require('../src/dns/dns-propagation'); describe('DNSPropagationChecker', () => { let checker; beforeEach(() => { const ctx = { log: { error: jest.fn(), info: jest.fn(), warn: jest.fn() }, notification: { send: jest.fn().mockResolvedValue({ success: true }) }, }; checker = new DNSPropagationChecker(ctx); }); test('is an EventEmitter', () => { expect(typeof checker.on).toBe('function'); expect(typeof checker.emit).toBe('function'); }); test('starts with an empty verifications map', () => { expect(checker.verifications).toBeInstanceOf(Map); expect(checker.verifications.size).toBe(0); }); test('verifyRecord returns expected shape and detects propagated domain', async () => { const result = await checker.verifyRecord('propagated.sami', '1.2.3.4', { timeout: 5000, interval: 100, resolvers: ['1.1.1.1'], }); expect(result).toHaveProperty('domain', 'propagated.sami'); expect(result).toHaveProperty('expectedIp', '1.2.3.4'); expect(result).toHaveProperty('propagated', true); expect(Array.isArray(result.results)).toBe(true); expect(result.results.length).toBeGreaterThan(0); expect(typeof result.totalTime).toBe('number'); expect(typeof result.checkedAt).toBe('string'); }); test('verifyRecord reports not-propagated when IP does not match', async () => { const result = await checker.verifyRecord('notpropagated.sami', '5.6.7.8', { timeout: 200, interval: 50, resolvers: ['1.1.1.1'], }); expect(result.propagated).toBe(false); }); test('startVerification returns a job object with running status', () => { const job = checker.startVerification('job.sami', '1.1.1.1', { timeout: 100, interval: 50, resolvers: ['1.1.1.1'], }); expect(job).toMatchObject({ domain: 'job.sami', expectedIp: '1.1.1.1', status: 'running', }); expect(job.startedAt).toBeDefined(); }); test('startVerification returns the same job when called twice for one domain', () => { const a = checker.startVerification('dup.sami', '1.1.1.1', { timeout: 5000, interval: 1000 }); const b = checker.startVerification('dup.sami', '1.1.1.1', { timeout: 5000, interval: 1000 }); expect(a).toBe(b); }); test('getVerificationStatus returns null for unknown domain', () => { expect(checker.getVerificationStatus('nope.sami')).toBeNull(); }); test('getAllVerifications returns an array', () => { expect(Array.isArray(checker.getAllVerifications())).toBe(true); }); test('cleanup is a no-op on empty verifications', () => { expect(() => checker.cleanup()).not.toThrow(); expect(checker.verifications.size).toBe(0); }); });