/ tests / utils / tld-detector.test.js
tld-detector.test.js
  1  /**
  2   * TLD Detector Tests
  3   *
  4   * Tests for detectCountryFromTLD() and parseCountryFromGoogleDomain().
  5   * Pure functions, no external dependencies.
  6   */
  7  
  8  import { test, describe } from 'node:test';
  9  import assert from 'node:assert/strict';
 10  
 11  import {
 12    detectCountryFromTLD,
 13    parseCountryFromGoogleDomain,
 14  } from '../../src/utils/tld-detector.js';
 15  
 16  // ─── detectCountryFromTLD ──────────────────────────────────────────────────────
 17  
 18  describe('detectCountryFromTLD', () => {
 19    test('returns null for null/empty domain', () => {
 20      const result = detectCountryFromTLD(null);
 21      assert.equal(result.countryCode, null);
 22      assert.equal(result.confidence, 'low');
 23      assert.equal(result.source, 'unknown');
 24    });
 25  
 26    test('returns null for empty string', () => {
 27      const result = detectCountryFromTLD('');
 28      assert.equal(result.countryCode, null);
 29    });
 30  
 31    test('detects .com.au → AU (multi-part TLD)', () => {
 32      const result = detectCountryFromTLD('example.com.au');
 33      assert.equal(result.countryCode, 'AU');
 34      assert.equal(result.confidence, 'high');
 35      assert.equal(result.source, 'cctld');
 36    });
 37  
 38    test('detects .co.uk → UK (multi-part TLD)', () => {
 39      const result = detectCountryFromTLD('example.co.uk');
 40      assert.equal(result.countryCode, 'UK');
 41      assert.equal(result.confidence, 'high');
 42    });
 43  
 44    test('detects .co.nz → NZ', () => {
 45      const result = detectCountryFromTLD('business.co.nz');
 46      assert.equal(result.countryCode, 'NZ');
 47    });
 48  
 49    test('detects single-part ccTLDs', () => {
 50      const cases = [
 51        ['example.ca', 'CA'],
 52        ['site.de', 'DE'],
 53        ['page.fr', 'FR'],
 54        ['shop.it', 'IT'],
 55        ['store.es', 'ES'],
 56        ['site.nl', 'NL'],
 57        ['example.be', 'BE'],
 58        ['company.ch', 'CH'],
 59        ['firm.at', 'AT'],
 60        ['biz.se', 'SE'],
 61        ['site.no', 'NO'],
 62        ['page.dk', 'DK'],
 63        ['site.fi', 'FI'],
 64        ['company.ie', 'IE'],
 65        ['site.pl', 'PL'],
 66        ['site.jp', 'JP'],
 67        ['shop.kr', 'KR'],
 68        ['example.cn', 'CN'],
 69        ['business.in', 'IN'],
 70        ['site.mx', 'MX'],
 71      ];
 72      for (const [domain, expected] of cases) {
 73        const result = detectCountryFromTLD(domain);
 74        assert.equal(result.countryCode, expected, `Failed for ${domain}`);
 75        assert.equal(result.confidence, 'high');
 76      }
 77    });
 78  
 79    test('generic TLDs return null (low confidence)', () => {
 80      const generics = ['example.com', 'site.net', 'app.io', 'company.org', 'startup.ai'];
 81      for (const domain of generics) {
 82        const result = detectCountryFromTLD(domain);
 83        assert.equal(result.countryCode, null, `Expected null for ${domain}`);
 84        assert.equal(result.confidence, 'low');
 85        assert.equal(result.source, 'unknown');
 86      }
 87    });
 88  
 89    test('detects .uk directly', () => {
 90      const result = detectCountryFromTLD('example.uk');
 91      assert.equal(result.countryCode, 'UK');
 92    });
 93  
 94    test('detects .au directly', () => {
 95      const result = detectCountryFromTLD('example.au');
 96      assert.equal(result.countryCode, 'AU');
 97    });
 98  
 99    test('returns high confidence for all detected TLDs', () => {
100      const detected = [
101        detectCountryFromTLD('a.com.au'),
102        detectCountryFromTLD('a.co.uk'),
103        detectCountryFromTLD('a.ca'),
104        detectCountryFromTLD('a.de'),
105      ];
106      for (const result of detected) {
107        assert.equal(result.confidence, 'high');
108        assert.equal(result.source, 'cctld');
109      }
110    });
111  });
112  
113  // ─── parseCountryFromGoogleDomain ─────────────────────────────────────────────
114  
115  describe('parseCountryFromGoogleDomain', () => {
116    test('google.com → US (default)', () => {
117      assert.equal(parseCountryFromGoogleDomain('google.com'), 'US');
118    });
119  
120    test('unknown domain falls back to US', () => {
121      assert.equal(parseCountryFromGoogleDomain('google.unknown'), 'US');
122    });
123  
124    test('google.com.au → AU', () => {
125      assert.equal(parseCountryFromGoogleDomain('google.com.au'), 'AU');
126    });
127  
128    test('google.co.uk → UK', () => {
129      assert.equal(parseCountryFromGoogleDomain('google.co.uk'), 'UK');
130    });
131  
132    test('google.co.nz → NZ', () => {
133      assert.equal(parseCountryFromGoogleDomain('google.co.nz'), 'NZ');
134    });
135  
136    test('known Google domains', () => {
137      const cases = [
138        ['google.ca', 'CA'],
139        ['google.de', 'DE'],
140        ['google.fr', 'FR'],
141        ['google.it', 'IT'],
142        ['google.es', 'ES'],
143        ['google.pt', 'PT'],
144        ['google.nl', 'NL'],
145        ['google.be', 'BE'],
146        ['google.ch', 'CH'],
147        ['google.at', 'AT'],
148        ['google.se', 'SE'],
149        ['google.no', 'NO'],
150        ['google.dk', 'DK'],
151        ['google.fi', 'FI'],
152        ['google.ie', 'IE'],
153        ['google.pl', 'PL'],
154        ['google.co.jp', 'JP'],
155        ['google.jp', 'JP'],
156        ['google.co.kr', 'KR'],
157        ['google.kr', 'KR'],
158        ['google.cn', 'CN'],
159        ['google.co.in', 'IN'],
160        ['google.in', 'IN'],
161        ['google.com.mx', 'MX'],
162      ];
163      for (const [domain, expected] of cases) {
164        assert.equal(parseCountryFromGoogleDomain(domain), expected, `Failed for ${domain}`);
165      }
166    });
167  });