test(24-04): add failing test for NS normalization and delegation comparison

- normalizeNsList: lowercase, strip trailing dot, dedupe, sort, [] for non-arrays
- compareNsDelegation: set-diff mismatch detection with unjudgeable-empty-authoritative guard
This commit is contained in:
lorentz 2026-08-05 20:20:41 -04:00
parent ecd4dabd67
commit 7396f07f2e

View file

@ -0,0 +1,87 @@
import { describe, it, expect } from 'vitest';
import { normalizeNsList, compareNsDelegation } from './route53-dns-delegation';
describe('normalizeNsList', () => {
it('lowercases and strips trailing dots', () => {
expect(normalizeNsList(['NS-123.AWSDNS-45.com.', 'ns-999.awsdns-01.org'])).toEqual([
'ns-123.awsdns-45.com',
'ns-999.awsdns-01.org',
]);
});
it('returns [] for null', () => {
expect(normalizeNsList(null)).toEqual([]);
});
it('returns [] for undefined', () => {
expect(normalizeNsList(undefined)).toEqual([]);
});
it('returns [] for a non-array input', () => {
expect(normalizeNsList('not-an-array')).toEqual([]);
expect(normalizeNsList(42)).toEqual([]);
expect(normalizeNsList({})).toEqual([]);
});
it('de-duplicates and sorts so ordering differences never register as a mismatch', () => {
expect(normalizeNsList(['ns-2.awsdns.com.', 'ns-1.awsdns.com', 'ns-1.awsdns.com.'])).toEqual([
'ns-1.awsdns.com',
'ns-2.awsdns.com',
]);
});
it('drops empty strings after trimming', () => {
expect(normalizeNsList([' ', 'ns-1.awsdns.com', ''])).toEqual(['ns-1.awsdns.com']);
});
});
describe('compareNsDelegation', () => {
it('returns mismatch: false with empty diffs when sets are identical', () => {
const result = compareNsDelegation(
['ns-1.awsdns.com', 'ns-2.awsdns.com'],
['NS-1.AWSDNS.com.', 'ns-2.awsdns.com.'],
);
expect(result.mismatch).toBe(false);
expect(result.missingFromLive).toEqual([]);
expect(result.extraInLive).toEqual([]);
});
it('returns mismatch: true with populated missingFromLive when an authoritative NS is absent from the live answer', () => {
const result = compareNsDelegation(
['ns-1.awsdns.com', 'ns-2.awsdns.com'],
['ns-1.awsdns.com'],
);
expect(result.mismatch).toBe(true);
expect(result.missingFromLive).toEqual(['ns-2.awsdns.com']);
expect(result.extraInLive).toEqual([]);
});
it('returns mismatch: true with populated extraInLive when the live answer contains an NS Route 53 does not consider authoritative', () => {
const result = compareNsDelegation(
['ns-1.awsdns.com'],
['ns-1.awsdns.com', 'ns-rogue.example.com'],
);
expect(result.mismatch).toBe(true);
expect(result.extraInLive).toEqual(['ns-rogue.example.com']);
expect(result.missingFromLive).toEqual([]);
});
it('returns mismatch: true when live has no answer but authoritative is non-empty (delegation problem, not a pass)', () => {
const result = compareNsDelegation(['ns1.example.com'], []);
expect(result.mismatch).toBe(true);
});
it('returns mismatch: false when authoritative is empty (unjudgeable, must not false-alarm)', () => {
const result = compareNsDelegation([], ['ns1.example.com']);
expect(result.mismatch).toBe(false);
});
it('is case-insensitive and trailing-dot-insensitive on both sides', () => {
const result = compareNsDelegation(['NS-1.AWSDNS.COM.'], ['ns-1.awsdns.com']);
expect(result.mismatch).toBe(false);
});
it('handles null/undefined inputs on both sides without throwing', () => {
expect(compareNsDelegation(null, undefined)).toMatchObject({ mismatch: false });
});
});