tldts-tests 7.3.1 → 7.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -65,6 +65,7 @@ export default function test(
65
65
  getPublicSuffix: (url: string, options?: Options) => string | null;
66
66
  getHostname: (url: string, options?: Options) => string | null;
67
67
  getDomain: (url: string, options?: Options) => string | null;
68
+ getFullDomain: (url: string, options?: Options) => string | null;
68
69
  getSubdomain: (url: string, options?: Options) => string | null;
69
70
  parse: (
70
71
  url: string,
@@ -434,6 +435,134 @@ export default function test(
434
435
  });
435
436
  });
436
437
 
438
+ describe('#getFullDomain', () => {
439
+ it('returns the full hostname (subdomain + domain) for a registrable domain', () => {
440
+ expect(tldts.getFullDomain('foo.bar.example.co.uk')).to.equal(
441
+ 'foo.bar.example.co.uk',
442
+ );
443
+ expect(
444
+ tldts.getFullDomain('https://foo.bar.example.co.uk:8080/path?q=1'),
445
+ ).to.equal('foo.bar.example.co.uk');
446
+ });
447
+
448
+ it('equals the domain when there is no subdomain', () => {
449
+ expect(tldts.getFullDomain('example.com')).to.equal('example.com');
450
+ });
451
+
452
+ it('normalises like the other extractors (lowercase, trailing dot, userinfo/port)', () => {
453
+ expect(tldts.getFullDomain('FOO.Example.COM.')).to.equal(
454
+ 'foo.example.com',
455
+ );
456
+ expect(tldts.getFullDomain('https://user@a.b.example.com:443/')).to.equal(
457
+ 'a.b.example.com',
458
+ );
459
+ });
460
+
461
+ it('returns null when there is no registrable domain', () => {
462
+ expect(tldts.getFullDomain('1.2.3.4')).to.equal(null); // IP
463
+ expect(tldts.getFullDomain('localhost')).to.equal(null); // single label
464
+ expect(tldts.getFullDomain('co.uk')).to.equal(null); // public suffix only
465
+ });
466
+
467
+ it('keeps subdomains that are not valid hostnames (#2322 DNS-record use case)', () => {
468
+ expect(
469
+ tldts.getFullDomain('___sip___._tcp.sipdbw06.rcs01.5gm.example.com'),
470
+ ).to.equal('___sip___._tcp.sipdbw06.rcs01.5gm.example.com');
471
+ });
472
+
473
+ it('validateHostname:false skips character checks but still requires a public suffix', () => {
474
+ // '!' is rejected by the default hostname validation...
475
+ expect(tldts.getFullDomain('a!b.example.com')).to.equal(null);
476
+ // ...but the registrable domain is still found when validation is off.
477
+ expect(
478
+ tldts.getFullDomain('a!b.example.com', { validateHostname: false }),
479
+ ).to.equal('a!b.example.com');
480
+ // A bare label has no registrable domain either way.
481
+ expect(
482
+ tldts.getFullDomain('foo_bar', { validateHostname: false }),
483
+ ).to.equal(null);
484
+ });
485
+
486
+ it('is consistent with getHostname gated on getDomain', () => {
487
+ for (const input of [
488
+ 'foo.bar.example.co.uk',
489
+ 'https://a.b.c.example.com:8080/p',
490
+ 'example.com',
491
+ '1.2.3.4',
492
+ 'localhost',
493
+ 'co.uk',
494
+ ]) {
495
+ const expected =
496
+ tldts.getDomain(input) === null ? null : tldts.getHostname(input);
497
+ expect(tldts.getFullDomain(input)).to.equal(expected);
498
+ }
499
+ });
500
+
501
+ it('avoids the getSubdomain + getDomain join footgun', () => {
502
+ // The naive `getSubdomain(x) + '.' + getDomain(x)` recipe emits a spurious
503
+ // leading dot when there is no subdomain; getFullDomain does not.
504
+ expect(tldts.getFullDomain('example.com')).to.equal('example.com');
505
+ expect(
506
+ `${tldts.getSubdomain('example.com')}.${tldts.getDomain('example.com')}`,
507
+ ).to.equal('.example.com'); // the footgun, shown for contrast
508
+ });
509
+
510
+ it('honors the validHosts option', () => {
511
+ expect(
512
+ tldts.getFullDomain('vhost.intranet', { validHosts: ['intranet'] }),
513
+ ).to.equal('vhost.intranet');
514
+ expect(
515
+ tldts.getFullDomain('intranet', { validHosts: ['intranet'] }),
516
+ ).to.equal('intranet');
517
+ // Without it, a bare unknown single label has no registrable domain.
518
+ expect(tldts.getFullDomain('intranet')).to.equal(null);
519
+ });
520
+
521
+ it('honors allowPrivateDomains (private-suffix gating)', () => {
522
+ // github.io is in the PRIVATE section: by default it is a registrable
523
+ // domain in every build.
524
+ expect(tldts.getFullDomain('github.io')).to.equal('github.io');
525
+ // Once private suffixes count it becomes a bare suffix (=> null). Only
526
+ // meaningful for builds that ship the PRIVATE section (not tldts-icann).
527
+ if (includePrivate) {
528
+ expect(
529
+ tldts.getFullDomain('github.io', { allowPrivateDomains: true }),
530
+ ).to.equal(null);
531
+ expect(
532
+ tldts.getFullDomain('user.github.io', { allowPrivateDomains: true }),
533
+ ).to.equal('user.github.io');
534
+ }
535
+ });
536
+
537
+ it('handles wildcard and exception public-suffix rules', () => {
538
+ expect(tldts.getFullDomain('foo.bar.ck')).to.equal('foo.bar.ck'); // *.ck
539
+ expect(tldts.getFullDomain('foo.ck')).to.equal(null); // bare *.ck suffix
540
+ expect(tldts.getFullDomain('a.www.ck')).to.equal('a.www.ck'); // !www.ck
541
+ });
542
+
543
+ it('preserves IDN / punycode labels without conversion', () => {
544
+ expect(tldts.getFullDomain('a.münchen.de')).to.equal('a.münchen.de');
545
+ expect(tldts.getFullDomain('a.xn--mnchen-3ya.de')).to.equal(
546
+ 'a.xn--mnchen-3ya.de',
547
+ );
548
+ });
549
+
550
+ it('returns null for IP addresses (no registrable domain)', () => {
551
+ expect(tldts.getFullDomain('http://[2a01:e35::1]:443/x')).to.equal(null);
552
+ expect(tldts.getFullDomain('2a01:e35::1')).to.equal(null);
553
+ });
554
+
555
+ it('respects the 255-character hostname length limit', () => {
556
+ const label = 'a'.repeat(63);
557
+ const max = `${label}.${label}.${label}.${'a'.repeat(59)}.com`;
558
+ expect(max).to.have.lengthOf(255);
559
+ expect(tldts.getFullDomain(max)).to.equal(max);
560
+ const tooLong = `${label}.${label}.${label}.${'a'.repeat(60)}.com`;
561
+ expect(tooLong).to.have.lengthOf(256);
562
+ expect(tldts.getFullDomain(tooLong)).to.equal(null);
563
+ });
564
+ });
565
+
437
566
  describe('#getPublicSuffix', () => {
438
567
  if (includePrivate) {
439
568
  describe('allowPrivateDomains', () => {
@@ -1741,6 +1870,7 @@ export default function test(
1741
1870
  expect(tldts.parse(url)).to.deep.equal(tldts.parse(url, {}));
1742
1871
  expect(tldts.getHostname(url)).to.equal(tldts.getHostname(url, {}));
1743
1872
  expect(tldts.getDomain(url)).to.equal(tldts.getDomain(url, {}));
1873
+ expect(tldts.getFullDomain(url)).to.equal(tldts.getFullDomain(url, {}));
1744
1874
  expect(tldts.getPublicSuffix(url)).to.equal(
1745
1875
  tldts.getPublicSuffix(url, {}),
1746
1876
  );