128 lines
5.3 KiB
TypeScript
128 lines
5.3 KiB
TypeScript
|
|
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
||
|
|
import * as smartnetwork from '../ts/index.js';
|
||
|
|
|
||
|
|
let testSmartNetwork: smartnetwork.SmartNetwork;
|
||
|
|
|
||
|
|
tap.test('should create a SmartNetwork instance', async () => {
|
||
|
|
testSmartNetwork = new smartnetwork.SmartNetwork();
|
||
|
|
expect(testSmartNetwork).toBeInstanceOf(smartnetwork.SmartNetwork);
|
||
|
|
});
|
||
|
|
|
||
|
|
tap.test('should get domain intelligence for google.com', async () => {
|
||
|
|
const result = await testSmartNetwork.getDomainIntelligence('google.com');
|
||
|
|
console.log('Domain Intelligence for google.com:', JSON.stringify(result, null, 2));
|
||
|
|
|
||
|
|
// RDAP fields
|
||
|
|
expect(result.domain).toEqual('google.com');
|
||
|
|
expect(result.registrarName).toBeTruthy();
|
||
|
|
expect(result.nameservers).toBeTruthy();
|
||
|
|
expect(Array.isArray(result.nameservers)).toBeTrue();
|
||
|
|
expect(result.nameservers!.length).toBeGreaterThan(0);
|
||
|
|
expect(result.registrationDate).toBeTruthy();
|
||
|
|
expect(result.expirationDate).toBeTruthy();
|
||
|
|
expect(Array.isArray(result.status)).toBeTrue();
|
||
|
|
expect(result.nameserversSource).toEqual('rdap');
|
||
|
|
|
||
|
|
// DNS enrichment fields
|
||
|
|
expect(result.resolvedIpv4).toBeTruthy();
|
||
|
|
expect(result.resolvedIpv4!.length).toBeGreaterThan(0);
|
||
|
|
expect(result.mxRecords).toBeTruthy();
|
||
|
|
expect(result.mxRecords!.length).toBeGreaterThan(0);
|
||
|
|
expect(result.txtRecords).toBeTruthy();
|
||
|
|
expect(result.txtRecords!.length).toBeGreaterThan(0);
|
||
|
|
});
|
||
|
|
|
||
|
|
tap.test('should get domain intelligence for cloudflare.com', async () => {
|
||
|
|
const result = await testSmartNetwork.getDomainIntelligence('cloudflare.com');
|
||
|
|
console.log('Domain Intelligence for cloudflare.com:', JSON.stringify(result, null, 2));
|
||
|
|
|
||
|
|
expect(result.domain).toEqual('cloudflare.com');
|
||
|
|
expect(result.registrarName).toBeTruthy();
|
||
|
|
expect(result.nameservers).toBeTruthy();
|
||
|
|
expect(result.nameservers!.length).toBeGreaterThan(0);
|
||
|
|
expect(result.registrationDate).toBeTruthy();
|
||
|
|
});
|
||
|
|
|
||
|
|
tap.test('should get domain intelligence for wikipedia.org (.org TLD)', async () => {
|
||
|
|
const result = await testSmartNetwork.getDomainIntelligence('wikipedia.org');
|
||
|
|
console.log('Domain Intelligence for wikipedia.org:', JSON.stringify(result, null, 2));
|
||
|
|
|
||
|
|
expect(result.domain).toEqual('wikipedia.org');
|
||
|
|
expect(result.registrarName).toBeTruthy();
|
||
|
|
expect(result.nameservers).toBeTruthy();
|
||
|
|
expect(result.nameservers!.length).toBeGreaterThan(0);
|
||
|
|
});
|
||
|
|
|
||
|
|
tap.test('should normalize an FQDN with trailing dot', async () => {
|
||
|
|
const result = await testSmartNetwork.getDomainIntelligence('Google.Com.');
|
||
|
|
expect(result.domain).toEqual('google.com');
|
||
|
|
});
|
||
|
|
|
||
|
|
tap.test('should normalize an IDN to ASCII (punycode)', async () => {
|
||
|
|
// The IDN "münchen.de" → "xn--mnchen-3ya.de"
|
||
|
|
const result = await testSmartNetwork.getDomainIntelligence('münchen.de');
|
||
|
|
console.log('IDN normalized to:', result.domain);
|
||
|
|
// Even if the lookup fails (e.g. .de RDAP behavior), the normalization should still produce the ASCII form
|
||
|
|
expect(result.domain).toEqual('xn--mnchen-3ya.de');
|
||
|
|
});
|
||
|
|
|
||
|
|
tap.test('should handle unknown TLD gracefully', async () => {
|
||
|
|
const result = await testSmartNetwork.getDomainIntelligence('foo.invalidtld12345');
|
||
|
|
console.log('Unknown TLD result:', JSON.stringify(result, null, 2));
|
||
|
|
expect(result).toBeTruthy();
|
||
|
|
expect(result.registrarName).toBeNull();
|
||
|
|
expect(result.nameservers).toBeNull();
|
||
|
|
});
|
||
|
|
|
||
|
|
tap.test('should handle malformed input gracefully', async () => {
|
||
|
|
const r1 = await testSmartNetwork.getDomainIntelligence('');
|
||
|
|
expect(r1).toBeTruthy();
|
||
|
|
expect(r1.domain).toBeNull();
|
||
|
|
|
||
|
|
const r2 = await testSmartNetwork.getDomainIntelligence('not a domain at all');
|
||
|
|
expect(r2).toBeTruthy();
|
||
|
|
expect(r2.domain).toBeNull();
|
||
|
|
|
||
|
|
const r3 = await testSmartNetwork.getDomainIntelligence('nodot');
|
||
|
|
expect(r3).toBeTruthy();
|
||
|
|
expect(r3.domain).toBeNull();
|
||
|
|
});
|
||
|
|
|
||
|
|
tap.test('should parse MX records with priority and exchange', async () => {
|
||
|
|
const result = await testSmartNetwork.getDomainIntelligence('google.com');
|
||
|
|
expect(result.mxRecords).toBeTruthy();
|
||
|
|
for (const mx of result.mxRecords!) {
|
||
|
|
expect(typeof mx.exchange).toEqual('string');
|
||
|
|
expect(mx.exchange.length).toBeGreaterThan(0);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
tap.test('should populate nameservers via DNS for RDAP-less .de TLD', async () => {
|
||
|
|
const result = await testSmartNetwork.getDomainIntelligence('bund.de');
|
||
|
|
console.log('Domain Intelligence for bund.de:', JSON.stringify(result, null, 2));
|
||
|
|
// .de has no RDAP in the IANA bootstrap, so RDAP fields are null
|
||
|
|
expect(result.registrarName).toBeNull();
|
||
|
|
// DNS layer should fill in nameservers + resolved IPs
|
||
|
|
expect(result.nameservers).toBeTruthy();
|
||
|
|
expect(result.nameservers!.length).toBeGreaterThan(0);
|
||
|
|
expect(result.nameserversSource).toEqual('dns');
|
||
|
|
expect(result.resolvedIpv4).toBeTruthy();
|
||
|
|
});
|
||
|
|
|
||
|
|
tap.test('should use cache when cacheTtl is set', async () => {
|
||
|
|
const cached = new smartnetwork.SmartNetwork({ cacheTtl: 60000 });
|
||
|
|
const r1 = await cached.getDomainIntelligence('google.com');
|
||
|
|
const r2 = await cached.getDomainIntelligence('google.com');
|
||
|
|
expect(r1.registrarName).toEqual(r2.registrarName);
|
||
|
|
expect(r1.registrationDate).toEqual(r2.registrationDate);
|
||
|
|
await cached.stop();
|
||
|
|
});
|
||
|
|
|
||
|
|
tap.test('should stop cleanly (tears down shared smartdns client)', async () => {
|
||
|
|
// If the Rust-backed smartdns bridge wasn't destroyed, this test process
|
||
|
|
// would hang at exit instead of completing.
|
||
|
|
await testSmartNetwork.stop();
|
||
|
|
});
|
||
|
|
|
||
|
|
export default tap.start();
|