import { describe, it } from 'node:test'; import assert from 'node:assert/strict'; import { dedupFavicons, dedupObservations, dedupPeersByInfoHash, } from '../src/services/dedup.util.js'; describe('dedupObservations', () => { it('keeps newest row per port', () => { const rows = [ { port: 80, banner: 'old', observedAt: new Date('2024-01-01') }, { port: 80, banner: 'new', observedAt: new Date('2024-06-01') }, { port: 443, banner: 'tls', observedAt: new Date('2024-01-01') }, ]; const out = dedupObservations(rows); assert.equal(out.length, 2); assert.equal(out.find((r) => r.port === 80)?.banner, 'new'); }); it('is order-independent', () => { const rows = [ { port: 22, banner: 'new', observedAt: new Date('2024-06-01') }, { port: 22, banner: 'old', observedAt: new Date('2024-01-01') }, ]; assert.equal(dedupObservations(rows)[0]?.banner, 'new'); }); it('handles empty input', () => { assert.deepEqual(dedupObservations([]), []); }); }); describe('dedupFavicons', () => { it('collapses identical perceptual hashes', () => { const rows = [ { perceptualHash: 'ab', createdAt: new Date('2024-01-01') }, { perceptualHash: 'ab', createdAt: new Date('2024-02-01') }, { perceptualHash: 'cd', createdAt: new Date('2024-01-01') }, ]; const out = dedupFavicons(rows); assert.equal(out.length, 2); }); }); describe('dedupPeersByInfoHash', () => { it('dedups case-insensitively, keeps first (newest)', () => { const rows = [ { infoHash: 'AABB', address: '1.1.1.1' }, { infoHash: 'aabb', address: '2.2.2.2' }, { infoHash: 'ccdd', address: '3.3.3.3' }, ]; const out = dedupPeersByInfoHash(rows); assert.equal(out.length, 2); assert.equal(out[0]?.address, '1.1.1.1'); }); });