57 lines
1.8 KiB
TypeScript
57 lines
1.8 KiB
TypeScript
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');
|
|
});
|
|
});
|