tldts-tests 6.6.70 → 7.0.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.
@@ -0,0 +1,1035 @@
1
+ import { expect } from 'chai';
2
+ import 'mocha';
3
+
4
+ import { loadPublicSuffixList, parsePublicSuffixRules } from 'tldts-utils';
5
+
6
+ interface Options {
7
+ extractHostname?: boolean;
8
+ allowPrivateDomains?: boolean;
9
+ allowIcannDomains?: boolean;
10
+ validateHostname?: boolean;
11
+ mixedInputs?: boolean;
12
+ detectIp?: boolean;
13
+ validHosts?: string[];
14
+ }
15
+
16
+ export default function test(
17
+ tldts: {
18
+ getDomainWithoutSuffix: (url: string, options?: Options) => string | null;
19
+ getPublicSuffix: (url: string, options?: Options) => string | null;
20
+ getHostname: (url: string, options?: Options) => string | null;
21
+ getDomain: (url: string, options?: Options) => string | null;
22
+ getSubdomain: (url: string, options?: Options) => string | null;
23
+ parse: (
24
+ url: string,
25
+ options?: Options,
26
+ ) => {
27
+ domain: string | null;
28
+ hostname: string | null;
29
+ publicSuffix: string | null;
30
+ };
31
+ },
32
+ { includePrivate }: { includePrivate: boolean },
33
+ ): void {
34
+ describe('from https://github.com/rushmorem/publicsuffix/blob/master/src/tests.rs', () => {
35
+ // Copyright (c) 2016 Rushmore Mushambi
36
+ it('should allow parsing IDN email addresses', () => {
37
+ expect(tldts.parse('Pelé@example.com')).to.deep.include({
38
+ domain: 'example.com',
39
+ hostname: 'example.com',
40
+ publicSuffix: 'com',
41
+ });
42
+
43
+ expect(tldts.parse('δοκιμή@παράδειγμα.δοκιμή')).to.deep.include({
44
+ domain: 'παράδειγμα.δοκιμή',
45
+ hostname: 'παράδειγμα.δοκιμή',
46
+ publicSuffix: 'δοκιμή',
47
+ });
48
+
49
+ expect(tldts.parse('我買@屋企.香港')).to.deep.include({
50
+ domain: '屋企.香港',
51
+ hostname: '屋企.香港',
52
+ publicSuffix: '香港',
53
+ });
54
+
55
+ expect(tldts.parse('甲斐@黒川.日本')).to.deep.include({
56
+ domain: '黒川.日本',
57
+ hostname: '黒川.日本',
58
+ publicSuffix: '日本',
59
+ });
60
+
61
+ expect(tldts.parse('чебурашка@ящик-с-апельсинами.рф')).to.deep.include({
62
+ domain: 'ящик-с-апельсинами.рф',
63
+ hostname: 'ящик-с-апельсинами.рф',
64
+ publicSuffix: 'рф',
65
+ });
66
+
67
+ expect(tldts.parse('用户@例子.广告')).to.deep.include({
68
+ domain: '例子.广告',
69
+ hostname: '例子.广告',
70
+ publicSuffix: '广告',
71
+ });
72
+ });
73
+ });
74
+
75
+ describe('#getDomain', () => {
76
+ it('should allow disabling parsing/validation of hostnames', () => {
77
+ expect(
78
+ tldts.getDomain('foo.com', {
79
+ extractHostname: false,
80
+ }),
81
+ ).to.equal('foo.com');
82
+ });
83
+
84
+ describe('supports reserved keywords', () => {
85
+ [
86
+ 'abstract',
87
+ 'arguments',
88
+ 'await',
89
+ 'boolean',
90
+ 'break',
91
+ 'byte',
92
+ 'case',
93
+ 'catch',
94
+ 'char',
95
+ 'class',
96
+ 'const',
97
+ 'continue',
98
+ 'debugger',
99
+ 'default',
100
+ 'delete',
101
+ 'do',
102
+ 'double',
103
+ 'else',
104
+ 'enum',
105
+ 'eval',
106
+ 'export',
107
+ 'extends',
108
+ 'false',
109
+ 'final',
110
+ 'finally',
111
+ 'float',
112
+ 'for',
113
+ 'function',
114
+ 'goto',
115
+ 'if',
116
+ 'implements',
117
+ 'import',
118
+ 'in',
119
+ 'instanceof',
120
+ 'int',
121
+ 'interface',
122
+ 'let',
123
+ 'long',
124
+ 'native',
125
+ 'new',
126
+ 'null',
127
+ 'package',
128
+ 'private',
129
+ 'protected',
130
+ 'public',
131
+ 'return',
132
+ 'short',
133
+ 'static',
134
+ 'super',
135
+ 'switch',
136
+ 'synchronized',
137
+ 'this',
138
+ 'throw',
139
+ 'throws',
140
+ 'transient',
141
+ 'true',
142
+ 'try',
143
+ 'typeof',
144
+ 'var',
145
+ 'void',
146
+ 'volatile',
147
+ 'while',
148
+ 'with',
149
+ 'yield',
150
+ ].forEach((keyword) => {
151
+ it(keyword, () => {
152
+ expect(tldts.getDomain(`https://${keyword}.com`)).to.equal(
153
+ `${keyword}.com`,
154
+ );
155
+ expect(tldts.getDomain(`https://foo.${keyword}.com`)).to.equal(
156
+ `${keyword}.com`,
157
+ );
158
+ expect(tldts.getDomain(`https://foo.${keyword}`)).to.equal(
159
+ `foo.${keyword}`,
160
+ );
161
+ });
162
+ });
163
+ });
164
+
165
+ it('handle IPs', () => {
166
+ expect(tldts.getDomain('1.2.3.4')).to.equal(null);
167
+ expect(tldts.getHostname('1.2.3.4')).to.equal('1.2.3.4');
168
+ });
169
+
170
+ it('handle weird urls', () => {
171
+ expect(tldts.getDomain(' ftp:/mapasamazonsa.com.ve./ ')).to.equal(
172
+ 'mapasamazonsa.com.ve',
173
+ );
174
+ expect(tldts.getDomain(' ftp://///mapasamazonsa.com.ve./ ')).to.equal(
175
+ 'mapasamazonsa.com.ve',
176
+ );
177
+ expect(tldts.getDomain(' ftp://///mapasamazonsa.com.ve/ ')).to.equal(
178
+ 'mapasamazonsa.com.ve',
179
+ );
180
+ expect(tldts.getDomain('ftp://///mapasamazonsa.com.ve/')).to.equal(
181
+ 'mapasamazonsa.com.ve',
182
+ );
183
+
184
+ // From https://github.com/peerigon/parse-domain/issues/49
185
+ expect(tldts.getDomain('ftp://mapasamazonsa.com.ve/')).to.equal(
186
+ 'mapasamazonsa.com.ve',
187
+ );
188
+ expect(
189
+ tldts.getDomain('http://y399.3466633.be:4/235222/399.html'),
190
+ ).to.equal('3466633.be');
191
+ expect(tldts.getDomain('this%20file%20was%')).to.equal(null);
192
+ expect(
193
+ tldts.getDomain(
194
+ 'wss://ie14.zopim.com/s/W/ws/zPYsGUAnWMyJ1XOL/c/1537265376519',
195
+ ),
196
+ ).to.equal('zopim.com');
197
+ expect(tldts.getDomain('wss://mp.sparkchess.com/ ')).to.equal(
198
+ 'sparkchess.com',
199
+ );
200
+ expect(
201
+ tldts.getDomain(
202
+ 'wss://119.92.223.221.prod.hosts.ooklaserver.net:8080/ws',
203
+ ),
204
+ ).to.equal('ooklaserver.net');
205
+ expect(
206
+ tldts.getDomain(
207
+ 'wss://gscspeedtest1.dctechmicro.com.prod.hosts.ooklaserver.net:8080/ws',
208
+ ),
209
+ ).to.equal('ooklaserver.net');
210
+ expect(
211
+ tldts.getDomain('ws://lhg2-speedtest.globe.com.ph:8080/ws'),
212
+ ).to.equal('globe.com.ph');
213
+ expect(
214
+ tldts.getDomain('wss://s-usc1c-nss-218.firebaseio.com/.ws'),
215
+ ).to.equal('firebaseio.com');
216
+ expect(tldts.getDomain('http://server.dr.pt./')).to.equal('dr.pt');
217
+ });
218
+
219
+ it('should return the expected domain from a simple string', () => {
220
+ expect(tldts.getDomain('google.com')).to.equal('google.com');
221
+ expect(tldts.getDomain('t.co')).to.equal('t.co');
222
+ expect(tldts.getDomain(' GOOGLE.COM ')).to.equal('google.com');
223
+ expect(tldts.getDomain(' t.CO ')).to.equal('t.co');
224
+ });
225
+
226
+ it('should return the relevant domain of a two levels domain', () => {
227
+ expect(tldts.getDomain('google.co.uk')).to.equal('google.co.uk');
228
+ });
229
+
230
+ it('should return the relevant domain from a subdomain string', () => {
231
+ expect(tldts.getDomain('fr.google.com')).to.equal('google.com');
232
+ expect(tldts.getDomain('foo.google.co.uk')).to.equal('google.co.uk');
233
+ expect(tldts.getDomain('fr.t.co')).to.equal('t.co');
234
+ });
235
+
236
+ it('should handle domains with lots of subdomains', () => {
237
+ expect(tldts.getDomain('a.f.g.h.i.bar.baz.google.com')).to.equal(
238
+ 'google.com',
239
+ );
240
+ expect(tldts.getDomain('foo.bar.baz.fr.t.co')).to.equal('t.co');
241
+ expect(tldts.getDomain('sub.sub2.foo.bar.baz.fr.t.co')).to.equal('t.co');
242
+ });
243
+
244
+ it('should not break on specific RegExp characters', () => {
245
+ expect(() => {
246
+ // @see https://github.com/oncletom/tld.js/issues/33
247
+ tldts.getDomain('www.weir)domain.com');
248
+ }).not.to.throw();
249
+ expect(() => {
250
+ // @see https://github.com/oncletom/tld.js/issues/53
251
+ tldts.getDomain(
252
+ "http://('4drsteve.com', [], ['54.213.246.177'])/xmlrpc.php",
253
+ );
254
+ }).not.to.throw();
255
+ expect(() => {
256
+ // @see https://github.com/oncletom/tld.js/issues/53
257
+ tldts.getDomain("('4drsteve.com', [], ['54.213.246.177'])");
258
+ }).not.to.throw();
259
+ });
260
+
261
+ // See https://github.com/remusao/tldts/issues/1523
262
+ it('should accept leading dots in a domain', () => {
263
+ expect(
264
+ tldts.getDomain('http://.example.co.uk./some/path?and&query#hash'),
265
+ ).to.equal('example.co.uk');
266
+ });
267
+
268
+ // See https://github.com/remusao/tldts/issues/1534
269
+ it('should accept leading dash and underscores in a domain', () => {
270
+ expect(
271
+ tldts.parse(
272
+ '_0f6879f07aa61fc09d9645cce98b30e3.bsg-1418.bryanjswift.com',
273
+ ),
274
+ ).to.eql({
275
+ domain: 'bryanjswift.com',
276
+ domainWithoutSuffix: 'bryanjswift',
277
+ hostname: '_0f6879f07aa61fc09d9645cce98b30e3.bsg-1418.bryanjswift.com',
278
+ isIcann: true,
279
+ isIp: false,
280
+ isPrivate: false,
281
+ publicSuffix: 'com',
282
+ subdomain: '_0f6879f07aa61fc09d9645cce98b30e3.bsg-1418',
283
+ });
284
+
285
+ expect(tldts.parse('_bsg-1418.bryanjswift.com')).to.eql({
286
+ domain: 'bryanjswift.com',
287
+ domainWithoutSuffix: 'bryanjswift',
288
+ hostname: '_bsg-1418.bryanjswift.com',
289
+ isIcann: true,
290
+ isIp: false,
291
+ isPrivate: false,
292
+ publicSuffix: 'com',
293
+ subdomain: '_bsg-1418',
294
+ });
295
+
296
+ expect(tldts.parse('_bryanjswift.com')).to.eql({
297
+ domain: '_bryanjswift.com',
298
+ domainWithoutSuffix: '_bryanjswift',
299
+ hostname: '_bryanjswift.com',
300
+ isIcann: true,
301
+ isIp: false,
302
+ isPrivate: false,
303
+ publicSuffix: 'com',
304
+ subdomain: '',
305
+ });
306
+ });
307
+
308
+ // @see https://github.com/oncletom/tld.js/issues/53
309
+ it('should correctly extract domain from paths including "@" in the path', () => {
310
+ const domain = tldts.getDomain(
311
+ 'http://cdn.jsdelivr.net/g/jquery@1.8.2,jquery.waypoints@2.0.2,qtip2@2.2.1,typeahead.js@0.9.3,sisyphus@0.1,jquery.slick@1.3.15,fastclick@1.0.3',
312
+ );
313
+ expect(domain).to.equal('jsdelivr.net');
314
+ });
315
+
316
+ it('should provide consistent results', () => {
317
+ expect(tldts.getDomain('www.bl.uk')).to.equal('bl.uk');
318
+ expect(tldts.getDomain('www.majestic12.co.uk')).to.equal(
319
+ 'majestic12.co.uk',
320
+ );
321
+ });
322
+
323
+ // @see https://github.com/oncletom/tld.js/issues/25
324
+ // @see https://github.com/oncletom/tld.js/issues/30
325
+ if (includePrivate) {
326
+ it('existing rule constraint', () => {
327
+ expect(tldts.getDomain('s3.amazonaws.com')).to.equal('amazonaws.com');
328
+ expect(
329
+ tldts.getDomain('s3.amazonaws.com', { allowPrivateDomains: true }),
330
+ ).to.equal(null);
331
+ // Removed: https://github.com/publicsuffix/list/pull/2327
332
+ // expect(
333
+ // tldts.getDomain('blogspot.co.uk', { allowPrivateDomains: true }),
334
+ // ).to.equal(null);
335
+ // expect(tldts.getDomain('blogspot.co.uk')).to.equal('blogspot.co.uk');
336
+ });
337
+ }
338
+
339
+ it('should return nytimes.com even in a whole valid', () => {
340
+ expect(tldts.getDomain('http://www.nytimes.com/')).to.equal(
341
+ 'nytimes.com',
342
+ );
343
+ });
344
+
345
+ // @see https://github.com/oncletom/tld.js/issues/95
346
+ it('should ignore the trailing dot in a domain', () => {
347
+ expect(tldts.getDomain('https://www.google.co.uk./maps')).to.equal(
348
+ 'google.co.uk',
349
+ );
350
+ });
351
+ });
352
+
353
+ describe('#getPublicSuffix', () => {
354
+ if (includePrivate) {
355
+ describe('allowPrivateDomains', () => {
356
+ const getPublicSuffix = (url: string) => {
357
+ return tldts.getPublicSuffix(url, { allowPrivateDomains: true });
358
+ };
359
+
360
+ it('should return de if example.de', () => {
361
+ expect(getPublicSuffix('example.de')).to.equal('de');
362
+ });
363
+
364
+ it('should return co.uk if google.co.uk', () => {
365
+ expect(getPublicSuffix('google.co.uk')).to.equal('co.uk');
366
+ });
367
+
368
+ // @see https://github.com/oncletom/tld.js/pull/97
369
+ it('should return www.ck if www.www.ck', () => {
370
+ expect(getPublicSuffix('www.www.ck')).to.equal('ck');
371
+ });
372
+
373
+ // @see https://github.com/oncletom/tld.js/issues/30
374
+ it('should return s3.amazonaws.com if s3.amazonaws.com', () => {
375
+ expect(getPublicSuffix('s3.amazonaws.com')).to.equal(
376
+ 's3.amazonaws.com',
377
+ );
378
+ });
379
+
380
+ it('should return s3.amazonaws.com if www.s3.amazonaws.com', () => {
381
+ expect(getPublicSuffix('www.s3.amazonaws.com')).to.equal(
382
+ 's3.amazonaws.com',
383
+ );
384
+ });
385
+
386
+ it('should directly return the suffix if it matches a rule key', () => {
387
+ expect(getPublicSuffix('youtube')).to.equal('youtube');
388
+ });
389
+
390
+ it('should return the suffix if a rule exists that has no exceptions', () => {
391
+ expect(getPublicSuffix('microsoft.eu')).to.equal('eu');
392
+ });
393
+
394
+ // @see https://github.com/oncletom/tld.js/pull/97
395
+ it('should return the string tldts if the publicsuffix does not exist', () => {
396
+ expect(getPublicSuffix('www.freedom.nsa')).to.equal('nsa');
397
+ });
398
+
399
+ // @see https://github.com/oncletom/tld.js/issues/95
400
+ it('should ignore the trailing dot in a domain', () => {
401
+ expect(getPublicSuffix('https://www.google.co.uk./maps')).to.equal(
402
+ 'co.uk',
403
+ );
404
+ });
405
+ });
406
+ }
407
+
408
+ describe('ignoring Private domains', () => {
409
+ const getPublicSuffix = (url: string) => {
410
+ return tldts.getPublicSuffix(url, { allowPrivateDomains: false });
411
+ };
412
+
413
+ it('should return de if example.de', () => {
414
+ expect(getPublicSuffix('example.de')).to.equal('de');
415
+ expect(getPublicSuffix('example.foo.de')).to.equal('de');
416
+ });
417
+
418
+ it('should return de if example.gov', () => {
419
+ expect(getPublicSuffix('example.gov')).to.equal('gov');
420
+ expect(getPublicSuffix('example.foo.gov')).to.equal('gov');
421
+ });
422
+
423
+ it('should return de if example.edu', () => {
424
+ expect(getPublicSuffix('example.edu')).to.equal('edu');
425
+ expect(getPublicSuffix('example.foo.edu')).to.equal('edu');
426
+ });
427
+
428
+ it('should return de if example.org', () => {
429
+ expect(getPublicSuffix('example.org')).to.equal('org');
430
+ expect(getPublicSuffix('example.foo.org')).to.equal('org');
431
+ });
432
+
433
+ it('should return com if www.s3.amazonaws.com', () => {
434
+ expect(getPublicSuffix('www.s3.amazonaws.com')).to.equal('com');
435
+ });
436
+
437
+ it('should return net if global.prod.fastly.net', () => {
438
+ expect(getPublicSuffix('https://global.prod.fastly.net')).to.equal(
439
+ 'net',
440
+ );
441
+ });
442
+
443
+ it('should return co.uk if google.co.uk', () => {
444
+ expect(getPublicSuffix('google.co.uk')).to.equal('co.uk');
445
+ });
446
+ });
447
+
448
+ if (includePrivate) {
449
+ describe('ignoring ICANN domains', () => {
450
+ const getPublicSuffix = (url: string) => {
451
+ return tldts.getPublicSuffix(url, {
452
+ allowIcannDomains: false,
453
+ allowPrivateDomains: true,
454
+ });
455
+ };
456
+
457
+ it('should return s3.amazonaws.com if www.s3.amazonaws.com', () => {
458
+ expect(getPublicSuffix('www.s3.amazonaws.com')).to.equal(
459
+ 's3.amazonaws.com',
460
+ );
461
+ });
462
+
463
+ it('should return global.prod.fastly.net if global.prod.fastly.net', () => {
464
+ expect(getPublicSuffix('https://global.prod.fastly.net')).to.equal(
465
+ 'global.prod.fastly.net',
466
+ );
467
+ });
468
+
469
+ it('should return co.uk if google.co.uk', () => {
470
+ expect(getPublicSuffix('google.co.uk')).to.equal('uk');
471
+ });
472
+ });
473
+ }
474
+ });
475
+
476
+ describe('#getHostname', () => {
477
+ it('handles space only inputs', () => {
478
+ expect(tldts.getHostname(' ')).to.equal(null);
479
+ expect(tldts.getHostname(' ')).to.equal(null);
480
+ });
481
+
482
+ it('handles space corner-cases', () => {
483
+ expect(tldts.getHostname(' a')).to.equal('a');
484
+ expect(tldts.getHostname('a ')).to.equal('a');
485
+ expect(tldts.getHostname(' a ')).to.equal('a');
486
+ expect(tldts.getHostname(' a ')).to.equal('a');
487
+ });
488
+
489
+ it('should return a valid hostname as is', () => {
490
+ expect(tldts.getHostname(' example.CO.uk ')).to.equal('example.co.uk');
491
+ expect(tldts.getHostname(' example.CO.uk ')).to.equal('example.co.uk');
492
+ expect(tldts.getHostname(' example.CO.uk ')).to.equal('example.co.uk');
493
+ });
494
+
495
+ it('should strip trailing dots', () => {
496
+ expect(tldts.getHostname('example.co.uk.')).to.equal('example.co.uk');
497
+ expect(tldts.getHostname('example.co.uk..')).to.equal('example.co.uk');
498
+ expect(tldts.getHostname('example.co.uk...')).to.equal('example.co.uk');
499
+ });
500
+
501
+ it('should return the hostname of a scheme-less URL', () => {
502
+ expect(
503
+ tldts.getHostname('example.co.uk/some/path?and&query#hash'),
504
+ ).to.equal('example.co.uk');
505
+ });
506
+
507
+ it('should return the hostname of a scheme-less + port URL', () => {
508
+ expect(
509
+ tldts.getHostname('example.co.uk:8080/some/path?and&query#hash'),
510
+ ).to.equal('example.co.uk');
511
+ });
512
+
513
+ it('should return the hostname of a scheme-less + authentication URL', () => {
514
+ expect(
515
+ tldts.getHostname(
516
+ 'user:password@example.co.uk/some/path?and&query#hash',
517
+ ),
518
+ ).to.equal('example.co.uk');
519
+ });
520
+
521
+ it('should return the hostname of a scheme-less + passwordless URL', () => {
522
+ expect(
523
+ tldts.getHostname('user@example.co.uk/some/path?and&query#hash'),
524
+ ).to.equal('example.co.uk');
525
+ });
526
+
527
+ it('should return the hostname of a scheme-less + authentication + port URL', () => {
528
+ expect(
529
+ tldts.getHostname(
530
+ 'user:password@example.co.uk:8080/some/path?and&query#hash',
531
+ ),
532
+ ).to.equal('example.co.uk');
533
+ });
534
+
535
+ it('should return the hostname of a scheme-less + passwordless + port URL', () => {
536
+ expect(
537
+ tldts.getHostname('user@example.co.uk:8080/some/path?and&query#hash'),
538
+ ).to.equal('example.co.uk');
539
+ });
540
+
541
+ it('should return the hostname of a user-password same-scheme URL', () => {
542
+ expect(
543
+ tldts.getHostname(
544
+ '//user:password@example.co.uk:8080/some/path?and&query#hash',
545
+ ),
546
+ ).to.equal('example.co.uk');
547
+ expect(
548
+ tldts.getHostname(
549
+ ' //user:password@example.co.uk:8080/some/path?and&query#hash',
550
+ ),
551
+ ).to.equal('example.co.uk');
552
+ });
553
+
554
+ it('should return the hostname of a passwordless same-scheme URL', () => {
555
+ expect(
556
+ tldts.getHostname('//user@example.co.uk:8080/some/path?and&query#hash'),
557
+ ).to.equal('example.co.uk');
558
+ expect(
559
+ tldts.getHostname(
560
+ ' //user@example.co.uk:8080/some/path?and&query#hash',
561
+ ),
562
+ ).to.equal('example.co.uk');
563
+ });
564
+
565
+ it('should return the hostname of a complex user-password scheme URL', () => {
566
+ expect(
567
+ tldts.getHostname(
568
+ 'git+ssh://user:password@example.co.uk:8080/some/path?and&query#hash',
569
+ ),
570
+ ).to.equal('example.co.uk');
571
+ });
572
+
573
+ it('should return the hostname of a complex passwordless scheme URL', () => {
574
+ expect(
575
+ tldts.getHostname(
576
+ 'git+ssh://user@example.co.uk:8080/some/path?and&query#hash',
577
+ ),
578
+ ).to.equal('example.co.uk');
579
+ });
580
+
581
+ it('should return www.nytimes.com even with an URL as a parameter', () => {
582
+ expect(
583
+ tldts.getHostname(
584
+ 'http://www.nytimes.com/glogin?URI=http://www.notnytimes.com/2010/03/26/us/politics/26court.html&OQ=_rQ3D1Q26&OP=45263736Q2FKgi!KQ7Dr!K@@@Ko!fQ24KJg(Q3FQ5Cgg!Q60KQ60W.WKWQ22KQ60IKyQ3FKigQ24Q26!Q26(Q3FKQ60I(gyQ5C!Q2Ao!fQ24',
585
+ ),
586
+ ).to.equal('www.nytimes.com');
587
+ });
588
+
589
+ // @see https://github.com/oncletom/tld.js/issues/95
590
+ it('should ignore the trailing dot in a domain', () => {
591
+ expect(
592
+ tldts.getHostname('http://example.co.uk./some/path?and&query#hash'),
593
+ ).to.equal('example.co.uk');
594
+ });
595
+
596
+ // See https://github.com/remusao/tldts/issues/1523
597
+ it('should accept leading dots in a hostname', () => {
598
+ expect(
599
+ tldts.getHostname('http://.example.co.uk./some/path?and&query#hash'),
600
+ ).to.equal('.example.co.uk');
601
+ });
602
+
603
+ it('should handle fragment URL', () => {
604
+ expect(tldts.getHostname('http://example.co.uk.#hash')).to.equal(
605
+ 'example.co.uk',
606
+ );
607
+ });
608
+
609
+ it('should handle parameter URL', () => {
610
+ expect(
611
+ tldts.getHostname('http://example.co.uk.?and&query#hash'),
612
+ ).to.equal('example.co.uk');
613
+ });
614
+
615
+ it('should detect invalid protocol characters', () => {
616
+ expect(tldts.getHostname('ht~tp://example.co.uk.')).to.equal(null);
617
+ });
618
+
619
+ it('should reject incomplete ipv6', () => {
620
+ expect(tldts.getHostname('http://[::1')).to.equal(null);
621
+ });
622
+
623
+ it('should allow disabling parsing of hostnames', () => {
624
+ expect(
625
+ tldts.getHostname('http://foo.com', {
626
+ extractHostname: false,
627
+ }),
628
+ ).to.equal('http://foo.com');
629
+ });
630
+
631
+ it('should allow disabling validation of hostnames', () => {
632
+ expect(
633
+ tldts.parse('http://f__.._oo.com', {
634
+ validateHostname: true,
635
+ }).hostname,
636
+ ).to.equal(null);
637
+
638
+ expect(
639
+ tldts.parse('http://f__.._oo.com', {
640
+ validateHostname: false,
641
+ }).hostname,
642
+ ).to.equal('f__.._oo.com');
643
+ });
644
+
645
+ it('should allow specifying no mixed inputs', () => {
646
+ const url = 'http://foo.com/baz?param=31';
647
+ expect(tldts.parse(url)).to.deep.equal(
648
+ tldts.parse(url, { mixedInputs: false }),
649
+ );
650
+ });
651
+
652
+ // https://github.com/remusao/tldts/issues/2258
653
+ it('should be consistent with parse method', () => {
654
+ const url = '___id___.c.mystat-in.net';
655
+
656
+ // With validation ('_' is forbidden at the start of a label)
657
+ expect(tldts.parse(url).hostname).to.be.null;
658
+ expect(tldts.getHostname(url)).to.be.null;
659
+
660
+ // Without validation
661
+ expect(tldts.parse(url, { validateHostname: false }).hostname).to.equal(
662
+ url,
663
+ );
664
+ expect(tldts.getHostname(url, { validateHostname: false })).to.equal(url);
665
+ });
666
+ });
667
+
668
+ describe('getDomainWithoutSuffix method', () => {
669
+ it('should return null if the domain cannot be found', () => {
670
+ expect(tldts.getDomainWithoutSuffix('not-a-validHost')).to.equal(null);
671
+ });
672
+
673
+ it('should return null if domain and suffix are the same', () => {
674
+ expect(tldts.getDomainWithoutSuffix('co.uk')).to.equal(null);
675
+ });
676
+
677
+ it('should return domain without suffix if domain exists', () => {
678
+ expect(tldts.getDomainWithoutSuffix('https://sub.foo.co.uk')).to.equal(
679
+ 'foo',
680
+ );
681
+ });
682
+ });
683
+
684
+ describe('getSubdomain method', () => {
685
+ it('should return null if the domain cannot be found', () => {
686
+ expect(tldts.getSubdomain('not-a-validHost')).to.equal(null);
687
+ });
688
+
689
+ it('should return the relevant subdomain of a hostname', () => {
690
+ expect(tldts.getSubdomain('localhost')).to.equal(null);
691
+ expect(tldts.getSubdomain('google.com')).to.equal('');
692
+ expect(tldts.getSubdomain('fr.google.com')).to.equal('fr');
693
+ expect(tldts.getSubdomain('random.fr.google.com')).to.equal('random.fr');
694
+ expect(tldts.getSubdomain('my.custom.domain')).to.equal('my');
695
+ });
696
+
697
+ it('should return the relevant subdomain of a badly trimmed string', () => {
698
+ expect(tldts.getSubdomain(' google.COM')).to.equal('');
699
+ expect(tldts.getSubdomain(' fr.GOOGLE.COM ')).to.equal('fr');
700
+ expect(tldts.getSubdomain(' random.FR.google.com')).to.equal('random.fr');
701
+ });
702
+
703
+ it('should return the subdomain of a tldts + SLD hostname', () => {
704
+ expect(tldts.getSubdomain('love.fukushima.jp')).to.equal('');
705
+ expect(tldts.getSubdomain('i.love.fukushima.jp')).to.equal('i');
706
+ expect(tldts.getSubdomain('random.nuclear.strike.co.jp')).to.equal(
707
+ 'random.nuclear',
708
+ );
709
+ });
710
+
711
+ it('should return the subdomain of a wildcard hostname', () => {
712
+ expect(tldts.getSubdomain('google.co.uk')).to.equal('');
713
+ expect(tldts.getSubdomain('fr.google.co.uk')).to.equal('fr');
714
+ expect(tldts.getSubdomain('random.fr.google.co.uk')).to.equal(
715
+ 'random.fr',
716
+ );
717
+ });
718
+
719
+ // @see https://github.com/oncletom/tld.js/issues/25
720
+ // Removed: https://github.com/publicsuffix/list/pull/2327
721
+ // it('should return the subdomain of reserved subdomains', () => {
722
+ // expect(tldts.getSubdomain('blogspot.co.uk')).to.equal('');
723
+ // expect(tldts.getSubdomain('emergency.blogspot.co.uk')).to.equal(
724
+ // 'emergency',
725
+ // );
726
+ // });
727
+
728
+ it('should not break on specific RegExp characters', () => {
729
+ expect(() => {
730
+ // @see https://github.com/oncletom/tld.js/issues/33
731
+ tldts.getSubdomain('www.weir)domain.com');
732
+ }).not.to.throw();
733
+ expect(() => {
734
+ // @see https://github.com/oncletom/tld.js/issues/53
735
+ tldts.getSubdomain(
736
+ "http://('4drsteve.com', [], ['54.213.246.177'])/xmlrpc.php",
737
+ );
738
+ }).not.to.throw();
739
+ expect(() => {
740
+ // @see https://github.com/oncletom/tld.js/issues/53
741
+ tldts.getSubdomain("('4drsteve.com', [], ['54.213.246.177'])");
742
+ }).not.to.throw();
743
+ });
744
+
745
+ // @see https://github.com/oncletom/tld.js/issues/53
746
+ it('should correctly extract domain from paths including "@" in the path', () => {
747
+ const domain = tldts.getSubdomain(
748
+ 'http://cdn.jsdelivr.net/g/jquery@1.8.2,jquery.waypoints@2.0.2,qtip2@2.2.1,typeahead.js@0.9.3,sisyphus@0.1,jquery.slick@1.3.15,fastclick@1.0.3',
749
+ );
750
+ expect(domain).to.equal('cdn');
751
+ });
752
+
753
+ // @see https://github.com/oncletom/tld.js/issues/35
754
+ it('should provide consistent results', () => {
755
+ expect(tldts.getSubdomain('www.bl.uk')).to.equal('www');
756
+ expect(tldts.getSubdomain('www.majestic12.co.uk')).to.equal('www');
757
+ });
758
+
759
+ // @see https://github.com/oncletom/tld.js/issues/95
760
+ it('should ignore the trailing dot in a domain', () => {
761
+ expect(tldts.getSubdomain('random.fr.google.co.uk.')).to.equal(
762
+ 'random.fr',
763
+ );
764
+ });
765
+ });
766
+
767
+ describe('#parse', () => {
768
+ const mockResponse = (hostname: string | null) => {
769
+ return {
770
+ domain: null,
771
+ domainWithoutSuffix: null,
772
+ hostname,
773
+ isIcann: null,
774
+ isIp: true,
775
+ isPrivate: null,
776
+ publicSuffix: null,
777
+ subdomain: null,
778
+ };
779
+ };
780
+
781
+ it('fallback to wildcard', () => {
782
+ expect(tldts.parse('https://foo.bar.badasdasdada')).to.deep.equal(
783
+ includePrivate
784
+ ? {
785
+ domain: 'bar.badasdasdada',
786
+ domainWithoutSuffix: 'bar',
787
+ hostname: 'foo.bar.badasdasdada',
788
+ isIcann: false,
789
+ isIp: false,
790
+ isPrivate: false,
791
+ publicSuffix: 'badasdasdada',
792
+ subdomain: 'foo',
793
+ }
794
+ : {
795
+ domain: 'bar.badasdasdada',
796
+ domainWithoutSuffix: 'bar',
797
+ hostname: 'foo.bar.badasdasdada',
798
+ isIcann: null,
799
+ isIp: false,
800
+ isPrivate: null,
801
+ publicSuffix: 'badasdasdada',
802
+ subdomain: 'foo',
803
+ },
804
+ );
805
+ });
806
+
807
+ it('should handle data URLs', () => {
808
+ expect(tldts.parse('data:image/png,some-base-64-value')).to.deep.equal({
809
+ ...mockResponse(null),
810
+ isIp: null,
811
+ });
812
+ });
813
+
814
+ it('should handle ipv6 addresses properly', () => {
815
+ expect(
816
+ tldts.parse('http://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]'),
817
+ ).to.deep.equal(mockResponse('2001:0db8:85a3:0000:0000:8a2e:0370:7334'));
818
+ expect(
819
+ tldts.parse('http://user:pass@[::1]/segment/index.html?query#frag'),
820
+ ).to.deep.equal(mockResponse('::1'));
821
+ expect(tldts.parse('https://[::1]')).to.deep.equal(mockResponse('::1'));
822
+ expect(tldts.parse('http://[1080::8:800:200C:417A]/foo')).to.deep.equal(
823
+ mockResponse('1080::8:800:200c:417a'),
824
+ );
825
+ expect(
826
+ tldts.parse('http://[1080::8:800:200C:417A]:4242/foo'),
827
+ ).to.deep.equal(mockResponse('1080::8:800:200c:417a'));
828
+ });
829
+
830
+ it('handles ipv6 address when extractHostname is false', () => {
831
+ const hostname = '1080::8:800:200C:417A';
832
+ expect(tldts.parse(hostname, { extractHostname: false })).to.deep.equal({
833
+ domain: null,
834
+ domainWithoutSuffix: null,
835
+ hostname,
836
+ isIcann: null,
837
+ isIp: true,
838
+ isPrivate: null,
839
+ publicSuffix: null,
840
+ subdomain: null,
841
+ });
842
+ });
843
+
844
+ it('handles ipv6 address when extractHostname is false (with brackets)', () => {
845
+ const hostname = '[1080::8:800:200C:417A]';
846
+ expect(tldts.parse(hostname, { extractHostname: false })).to.deep.equal({
847
+ domain: null,
848
+ domainWithoutSuffix: null,
849
+ hostname,
850
+ isIcann: null,
851
+ isIp: true,
852
+ isPrivate: null,
853
+ publicSuffix: null,
854
+ subdomain: null,
855
+ });
856
+ });
857
+
858
+ it('should handle ipv4 addresses properly', () => {
859
+ expect(tldts.parse('http://192.168.0.1/')).to.deep.equal(
860
+ mockResponse('192.168.0.1'),
861
+ );
862
+ });
863
+
864
+ it('disable ip detection', () => {
865
+ expect(
866
+ tldts.parse('http://192.168.0.1/', { detectIp: false }),
867
+ ).to.deep.equal(
868
+ includePrivate
869
+ ? {
870
+ domain: '0.1',
871
+ domainWithoutSuffix: '0',
872
+ hostname: '192.168.0.1',
873
+ isIcann: false,
874
+ isIp: null,
875
+ isPrivate: false,
876
+ publicSuffix: '1',
877
+ subdomain: '192.168',
878
+ }
879
+ : {
880
+ domain: '0.1',
881
+ domainWithoutSuffix: '0',
882
+ hostname: '192.168.0.1',
883
+ isIcann: null,
884
+ isIp: null,
885
+ isPrivate: null,
886
+ publicSuffix: '1',
887
+ subdomain: '192.168',
888
+ },
889
+ );
890
+ });
891
+ });
892
+
893
+ describe('validHosts', () => {
894
+ describe('non-empty array', () => {
895
+ const options: Options = {
896
+ validHosts: ['localhost'],
897
+ };
898
+
899
+ it('should return the known valid host', () => {
900
+ expect(tldts.getDomain('localhost', options)).to.equal('localhost');
901
+ expect(tldts.getDomain('subdomain.localhost', options)).to.equal(
902
+ 'localhost',
903
+ );
904
+ expect(tldts.getDomain('subdomain.notlocalhost', options)).to.equal(
905
+ 'subdomain.notlocalhost',
906
+ );
907
+ expect(tldts.getDomain('subdomain.not-localhost', options)).to.equal(
908
+ 'subdomain.not-localhost',
909
+ );
910
+ });
911
+
912
+ // @see https://github.com/oncletom/tld.js/issues/66
913
+ it('should return the subdomain of a validHost', () => {
914
+ expect(tldts.getSubdomain('vhost.localhost', options)).to.equal(
915
+ 'vhost',
916
+ );
917
+ });
918
+
919
+ it('should fallback to normal extraction if no match in validHost', () => {
920
+ expect(tldts.getSubdomain('vhost.evil.com', options)).to.equal('vhost');
921
+ });
922
+ });
923
+ });
924
+
925
+ // Examples based on What-wg specification: https://url.spec.whatwg.org/#example-host-psl
926
+ describe('whatwg URL spec', () => {
927
+ for (const [input, publicSuffix, domain] of includePrivate
928
+ ? ([
929
+ ['com', 'com', null],
930
+ ['example.com', 'com', 'example.com'],
931
+ ['www.example.com', 'com', 'example.com'],
932
+ ['sub.www.example.com', 'com', 'example.com'],
933
+ ['EXAMPLE.COM', 'com', 'example.com'],
934
+ // ['example.com.', 'com.', 'example.com.'],
935
+ ['github.io', 'github.io', null],
936
+ ['whatwg.github.io', 'github.io', 'whatwg.github.io'],
937
+ ['إختبار', 'إختبار', null],
938
+ ['example.إختبار', 'إختبار', 'example.إختبار'],
939
+ ['sub.example.إختبار', 'إختبار', 'example.إختبار'],
940
+ ['[2001:0db8:85a3:0000:0000:8a2e:0370:7334]', null, null],
941
+ ] as const)
942
+ : ([
943
+ ['com', 'com', null],
944
+ ['example.com', 'com', 'example.com'],
945
+ ['www.example.com', 'com', 'example.com'],
946
+ ['sub.www.example.com', 'com', 'example.com'],
947
+ ['EXAMPLE.COM', 'com', 'example.com'],
948
+ // ['example.com.', 'com.', 'example.com.'],
949
+ ['github.io', 'io', 'github.io'],
950
+ ['whatwg.github.io', 'io', 'github.io'],
951
+ ['إختبار', 'إختبار', null],
952
+ ['example.إختبار', 'إختبار', 'example.إختبار'],
953
+ ['sub.example.إختبار', 'إختبار', 'example.إختبار'],
954
+ ['[2001:0db8:85a3:0000:0000:8a2e:0370:7334]', null, null],
955
+ ] as const)) {
956
+ it(input, () => {
957
+ const result = tldts.parse(input, {
958
+ allowPrivateDomains: includePrivate,
959
+ });
960
+ expect(result, input).not.to.equal(null);
961
+ expect(result.publicSuffix, input).to.equal(publicSuffix);
962
+ expect(result.domain, input).to.equal(domain);
963
+ });
964
+ }
965
+ });
966
+
967
+ describe('wildcard tests', () => {
968
+ parsePublicSuffixRules(loadPublicSuffixList(), (rule) => {
969
+ if (
970
+ !rule.isException &&
971
+ rule.isWildcard &&
972
+ (rule.isIcann || includePrivate) &&
973
+ rule.rule !== '*.wc.psl.hrsn.dev'
974
+ ) {
975
+ it(rule.rule, () => {
976
+ expect(rule.rule.startsWith('*.')).to.be.true;
977
+ const domain = rule.rule.slice(2);
978
+ const url = `https://www.sub.${domain}/`;
979
+ const result = tldts.parse(url, {
980
+ allowPrivateDomains: includePrivate,
981
+ });
982
+ expect(result, url).not.to.equal(null);
983
+ expect(result.publicSuffix, url).to.equal(`sub.${domain}`);
984
+ expect(result.domain, url).to.equal(`www.sub.${domain}`);
985
+ expect(result.hostname, url).to.equal(`www.sub.${domain}`);
986
+ });
987
+ }
988
+ });
989
+ });
990
+
991
+ describe('exception tests', () => {
992
+ parsePublicSuffixRules(loadPublicSuffixList(), (rule) => {
993
+ if (
994
+ rule.isException &&
995
+ !rule.isWildcard &&
996
+ (rule.isIcann || includePrivate)
997
+ ) {
998
+ const domain = rule.rule;
999
+ it(domain, () => {
1000
+ const url = `https://${domain}/`;
1001
+ const result = tldts.parse(url, {
1002
+ allowPrivateDomains: includePrivate,
1003
+ });
1004
+ expect(result, url).not.to.equal(null);
1005
+ expect(result.publicSuffix, url).to.equal(
1006
+ domain.split('.').slice(1).join('.'),
1007
+ );
1008
+ expect(result.domain, url).to.equal(domain);
1009
+ expect(result.hostname, url).to.equal(domain);
1010
+ });
1011
+ }
1012
+ });
1013
+ });
1014
+
1015
+ describe('extended tests', () => {
1016
+ parsePublicSuffixRules(loadPublicSuffixList(), (rule) => {
1017
+ if (
1018
+ !rule.isException &&
1019
+ !rule.isWildcard &&
1020
+ (rule.isIcann || includePrivate)
1021
+ ) {
1022
+ const suffix = rule.rule;
1023
+ it(suffix, () => {
1024
+ const url = `https://example.${suffix}/`;
1025
+ const result = tldts.parse(url, {
1026
+ allowPrivateDomains: includePrivate,
1027
+ });
1028
+ expect(result, url).not.to.equal(null);
1029
+ expect(result.publicSuffix, url).to.equal(suffix);
1030
+ expect(result.domain, url).to.equal(`example.${suffix}`);
1031
+ });
1032
+ }
1033
+ });
1034
+ });
1035
+ }