parse-domain 2.3.0 → 2.3.4
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.
- package/CHANGELOG.md +27 -0
- package/README.md +2 -2
- package/build/tries/icann.complete.json +1 -1
- package/build/tries/icann.light.json +1 -1
- package/build/tries/meta.json +1 -0
- package/build/tries/private.complete.json +1 -1
- package/build/tries/private.json +1 -0
- package/lib/parseDomain.js +18 -36
- package/lib/trie/characters.js +16 -0
- package/lib/trie/lookUp.js +33 -0
- package/lib/trie/nodes.js +40 -0
- package/lib/trie/parse.js +64 -0
- package/lib/{tries → trie}/parsePubSuffixList.js +0 -0
- package/lib/{tries → trie}/serializeTrie.js +6 -6
- package/lists/icann.complete.js +2 -2
- package/lists/icann.light.js +2 -2
- package/lists/private.complete.js +2 -2
- package/package.json +6 -7
- package/scripts/build-tries.js +15 -7
- package/src/index.d.ts +18 -0
- package/test/parseDomain.test.js +214 -90
- package/test/snapshots.test.js +6 -29
- package/test/trie/lookUp.test.js +96 -0
- package/test/trie/nodes.test.js +24 -0
- package/test/trie/parse.test.js +140 -0
- package/test/trie/parsePubSuffixList.test.js +130 -0
- package/test/{tries → trie}/serializeTrie.test.js +20 -14
- package/lib/tries/lookUp.js +0 -40
- package/lib/tries/parseTrie.js +0 -62
- package/lib/tries/separators.js +0 -12
- package/test/mocha.opts +0 -1
- package/test/tries/lookUp.test.js +0 -116
- package/test/tries/parsePubSuffixList.test.js +0 -129
- package/test/tries/parseTrie.test.js +0 -162
package/test/parseDomain.test.js
CHANGED
|
@@ -1,217 +1,219 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
const chai = require("chai");
|
|
4
|
-
|
|
5
|
-
const expect = chai.expect;
|
|
6
3
|
const parseDomain = require("../lib/parseDomain.js");
|
|
7
4
|
|
|
8
|
-
chai.config.includeStack = true;
|
|
9
|
-
|
|
10
5
|
describe("parseDomain(url)", () => {
|
|
11
|
-
|
|
12
|
-
expect(parseDomain("http://example.com")).
|
|
6
|
+
test("should remove the protocol", () => {
|
|
7
|
+
expect(parseDomain("http://example.com")).toEqual({
|
|
13
8
|
subdomain: "",
|
|
14
9
|
domain: "example",
|
|
15
10
|
tld: "com",
|
|
16
11
|
});
|
|
17
|
-
expect(parseDomain("//example.com")).
|
|
12
|
+
expect(parseDomain("//example.com")).toEqual({
|
|
18
13
|
subdomain: "",
|
|
19
14
|
domain: "example",
|
|
20
15
|
tld: "com",
|
|
21
16
|
});
|
|
22
|
-
expect(parseDomain("https://example.com")).
|
|
17
|
+
expect(parseDomain("https://example.com")).toEqual({
|
|
23
18
|
subdomain: "",
|
|
24
19
|
domain: "example",
|
|
25
20
|
tld: "com",
|
|
26
21
|
});
|
|
27
22
|
});
|
|
28
23
|
|
|
29
|
-
|
|
30
|
-
expect(parseDomain("www.example.com")).
|
|
24
|
+
test("should remove sub-domains", () => {
|
|
25
|
+
expect(parseDomain("www.example.com")).toEqual({
|
|
31
26
|
subdomain: "www",
|
|
32
27
|
domain: "example",
|
|
33
28
|
tld: "com",
|
|
34
29
|
});
|
|
35
|
-
expect(parseDomain("www.some.other.subdomain.example.com")).
|
|
30
|
+
expect(parseDomain("www.some.other.subdomain.example.com")).toEqual({
|
|
36
31
|
subdomain: "www.some.other.subdomain",
|
|
37
32
|
domain: "example",
|
|
38
33
|
tld: "com",
|
|
39
34
|
});
|
|
40
35
|
});
|
|
41
36
|
|
|
42
|
-
|
|
43
|
-
expect(parseDomain("example.com/some/path?and&query")).
|
|
37
|
+
test("should remove the path", () => {
|
|
38
|
+
expect(parseDomain("example.com/some/path?and&query")).toEqual({
|
|
44
39
|
subdomain: "",
|
|
45
40
|
domain: "example",
|
|
46
41
|
tld: "com",
|
|
47
42
|
});
|
|
48
|
-
expect(parseDomain("example.com/")).
|
|
43
|
+
expect(parseDomain("example.com/")).toEqual({
|
|
49
44
|
subdomain: "",
|
|
50
45
|
domain: "example",
|
|
51
46
|
tld: "com",
|
|
52
47
|
});
|
|
53
48
|
});
|
|
54
49
|
|
|
55
|
-
|
|
56
|
-
expect(parseDomain("example.com?and&query")).
|
|
50
|
+
test("should remove the query string", () => {
|
|
51
|
+
expect(parseDomain("example.com?and&query")).toEqual({
|
|
57
52
|
subdomain: "",
|
|
58
53
|
domain: "example",
|
|
59
54
|
tld: "com",
|
|
60
55
|
});
|
|
61
56
|
});
|
|
62
57
|
|
|
63
|
-
|
|
64
|
-
expect(parseDomain("http://m.example.com\r")).
|
|
58
|
+
test("should remove special characters", () => {
|
|
59
|
+
expect(parseDomain("http://m.example.com\r")).toEqual({
|
|
65
60
|
subdomain: "m",
|
|
66
61
|
domain: "example",
|
|
67
62
|
tld: "com",
|
|
68
63
|
});
|
|
69
64
|
});
|
|
70
65
|
|
|
71
|
-
|
|
72
|
-
expect(parseDomain("example.com:8080")).
|
|
66
|
+
test("should remove the port", () => {
|
|
67
|
+
expect(parseDomain("example.com:8080")).toEqual({
|
|
73
68
|
subdomain: "",
|
|
74
69
|
domain: "example",
|
|
75
70
|
tld: "com",
|
|
76
71
|
});
|
|
77
72
|
});
|
|
78
73
|
|
|
79
|
-
|
|
80
|
-
expect(parseDomain("user:password@example.com")).
|
|
74
|
+
test("should remove the authentication", () => {
|
|
75
|
+
expect(parseDomain("user:password@example.com")).toEqual({
|
|
81
76
|
subdomain: "",
|
|
82
77
|
domain: "example",
|
|
83
78
|
tld: "com",
|
|
84
79
|
});
|
|
85
80
|
});
|
|
86
81
|
|
|
87
|
-
|
|
88
|
-
expect(parseDomain("https://medium.com/@username/")).
|
|
82
|
+
test("should allow @ characters in the path", () => {
|
|
83
|
+
expect(parseDomain("https://medium.com/@username/")).toEqual({
|
|
89
84
|
subdomain: "",
|
|
90
85
|
domain: "medium",
|
|
91
86
|
tld: "com",
|
|
92
87
|
});
|
|
93
88
|
});
|
|
94
89
|
|
|
95
|
-
|
|
96
|
-
expect(parseDomain("www.example.co.uk")).
|
|
90
|
+
test("should also work with three-level domains like .co.uk", () => {
|
|
91
|
+
expect(parseDomain("www.example.co.uk")).toEqual({
|
|
97
92
|
subdomain: "www",
|
|
98
93
|
domain: "example",
|
|
99
94
|
tld: "co.uk",
|
|
100
95
|
});
|
|
101
96
|
});
|
|
102
97
|
|
|
103
|
-
|
|
104
|
-
expect(parseDomain("foo.blogspot.com")).
|
|
98
|
+
test("should not include private domains like blogspot.com by default", () => {
|
|
99
|
+
expect(parseDomain("foo.blogspot.com")).toEqual({
|
|
105
100
|
subdomain: "foo",
|
|
106
101
|
domain: "blogspot",
|
|
107
102
|
tld: "com",
|
|
108
103
|
});
|
|
109
104
|
});
|
|
110
105
|
|
|
111
|
-
|
|
112
|
-
expect(parseDomain("foo.blogspot.com", {privateTlds: true})).
|
|
106
|
+
test("should include private tlds", () => {
|
|
107
|
+
expect(parseDomain("foo.blogspot.com", {privateTlds: true})).toEqual({
|
|
113
108
|
subdomain: "",
|
|
114
109
|
domain: "foo",
|
|
115
110
|
tld: "blogspot.com",
|
|
116
111
|
});
|
|
117
112
|
});
|
|
118
113
|
|
|
119
|
-
|
|
120
|
-
expect(parseDomain("https://user@www.some.other.subdomain.example.co.uk:8080/some/path?and&query#hash")).
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}
|
|
126
|
-
);
|
|
114
|
+
test("should work when all url parts are present", () => {
|
|
115
|
+
expect(parseDomain("https://user@www.some.other.subdomain.example.co.uk:8080/some/path?and&query#hash")).toEqual({
|
|
116
|
+
subdomain: "www.some.other.subdomain",
|
|
117
|
+
domain: "example",
|
|
118
|
+
tld: "co.uk",
|
|
119
|
+
});
|
|
127
120
|
});
|
|
128
121
|
|
|
129
|
-
|
|
130
|
-
expect(parseDomain("example.com")).
|
|
122
|
+
test("should also work with the minimum", () => {
|
|
123
|
+
expect(parseDomain("example.com")).toEqual({
|
|
131
124
|
subdomain: "",
|
|
132
125
|
domain: "example",
|
|
133
126
|
tld: "com",
|
|
134
127
|
});
|
|
135
128
|
});
|
|
136
129
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
130
|
+
test(
|
|
131
|
+
"should return null if the given url contains an unsupported top-level domain",
|
|
132
|
+
() => {
|
|
133
|
+
expect(parseDomain("example.kk")).toBeNull();
|
|
134
|
+
}
|
|
135
|
+
);
|
|
140
136
|
|
|
141
|
-
|
|
142
|
-
expect(parseDomain(undefined)).
|
|
143
|
-
expect(parseDomain({})).
|
|
137
|
+
test("should return null if the given value is not a string", () => {
|
|
138
|
+
expect(parseDomain(undefined)).toBeNull();
|
|
139
|
+
expect(parseDomain({})).toBeNull();
|
|
144
140
|
});
|
|
145
141
|
|
|
146
|
-
|
|
147
|
-
expect(parseDomain("\xa0")).
|
|
148
|
-
expect(parseDomain("")).
|
|
149
|
-
expect(parseDomain(" ")).
|
|
150
|
-
expect(parseDomain("http://hell.d\ne.ibm.com")).
|
|
142
|
+
test("should return null if the given string is not a valid URL", () => {
|
|
143
|
+
expect(parseDomain("\xa0")).toBeNull();
|
|
144
|
+
expect(parseDomain("")).toBeNull();
|
|
145
|
+
expect(parseDomain(" ")).toBeNull();
|
|
146
|
+
expect(parseDomain("http://hell.d\ne.ibm.com")).toBeNull();
|
|
151
147
|
});
|
|
152
148
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
149
|
+
test(
|
|
150
|
+
"should return null if the given is an empty string with a space character",
|
|
151
|
+
() => {
|
|
152
|
+
expect(parseDomain(" ")).toBeNull();
|
|
153
|
+
}
|
|
154
|
+
);
|
|
156
155
|
|
|
157
|
-
|
|
158
|
-
expect(parseDomain("http://hello.de.ibm.com")).
|
|
156
|
+
test("should work with domains that could match multiple tlds", () => {
|
|
157
|
+
expect(parseDomain("http://hello.de.ibm.com")).toEqual({
|
|
159
158
|
subdomain: "hello.de",
|
|
160
159
|
domain: "ibm",
|
|
161
160
|
tld: "com",
|
|
162
161
|
});
|
|
163
162
|
});
|
|
164
163
|
|
|
165
|
-
|
|
164
|
+
test("should work with custom top-level domains (eg .local)", () => {
|
|
166
165
|
const options = {customTlds: ["local"]};
|
|
167
166
|
|
|
168
|
-
expect(parseDomain("mymachine.local", options)).
|
|
167
|
+
expect(parseDomain("mymachine.local", options)).toEqual({
|
|
169
168
|
subdomain: "",
|
|
170
169
|
domain: "mymachine",
|
|
171
170
|
tld: "local",
|
|
172
171
|
});
|
|
173
172
|
|
|
174
173
|
// Sanity checks if the option does not misbehave
|
|
175
|
-
expect(parseDomain("mymachine.local")).
|
|
176
|
-
expect(parseDomain("http://example.com", options)).
|
|
174
|
+
expect(parseDomain("mymachine.local")).toBe(null);
|
|
175
|
+
expect(parseDomain("http://example.com", options)).toEqual({
|
|
177
176
|
subdomain: "",
|
|
178
177
|
domain: "example",
|
|
179
178
|
tld: "com",
|
|
180
179
|
});
|
|
181
180
|
});
|
|
182
181
|
|
|
183
|
-
|
|
184
|
-
|
|
182
|
+
test(
|
|
183
|
+
"should also work with custom top-level domains passed as regexps",
|
|
184
|
+
() => {
|
|
185
|
+
const options = {customTlds: /(\.local|localhost)$/};
|
|
185
186
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
187
|
+
expect(parseDomain("mymachine.local", options)).toEqual({
|
|
188
|
+
subdomain: "",
|
|
189
|
+
domain: "mymachine",
|
|
190
|
+
tld: "local",
|
|
191
|
+
});
|
|
192
|
+
expect(parseDomain("localhost", options)).toEqual({
|
|
193
|
+
subdomain: "",
|
|
194
|
+
domain: "",
|
|
195
|
+
tld: "localhost",
|
|
196
|
+
});
|
|
197
|
+
expect(parseDomain("localhost:8080", options)).toEqual({
|
|
198
|
+
subdomain: "",
|
|
199
|
+
domain: "",
|
|
200
|
+
tld: "localhost",
|
|
201
|
+
});
|
|
201
202
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
203
|
+
// Sanity checks if the option does not misbehave
|
|
204
|
+
expect(parseDomain("mymachine.local")).toBe(null);
|
|
205
|
+
expect(parseDomain("http://example.com", options)).toEqual({
|
|
206
|
+
subdomain: "",
|
|
207
|
+
domain: "example",
|
|
208
|
+
tld: "com",
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
);
|
|
210
212
|
|
|
211
213
|
describe("real-world use cases", () => {
|
|
212
214
|
// See https://github.com/peerigon/parse-domain/pull/65
|
|
213
|
-
|
|
214
|
-
expect(parseDomain("example.police.uk")).
|
|
215
|
+
test("should parse police.uk as tld", () => {
|
|
216
|
+
expect(parseDomain("example.police.uk")).toEqual({
|
|
215
217
|
subdomain: "",
|
|
216
218
|
domain: "example",
|
|
217
219
|
tld: "police.uk",
|
|
@@ -219,12 +221,134 @@ describe("parseDomain(url)", () => {
|
|
|
219
221
|
});
|
|
220
222
|
|
|
221
223
|
// See https://github.com/peerigon/parse-domain/issues/67
|
|
222
|
-
|
|
223
|
-
expect(parseDomain("dev.classea12.beta.gouv.fr", {privateTlds: true})).
|
|
224
|
+
test("should parse gouv.fr as tld", () => {
|
|
225
|
+
expect(parseDomain("dev.classea12.beta.gouv.fr", {privateTlds: true})).toEqual({
|
|
224
226
|
tld: "gouv.fr",
|
|
225
227
|
domain: "beta",
|
|
226
228
|
subdomain: "dev.classea12",
|
|
227
229
|
});
|
|
228
230
|
});
|
|
229
231
|
});
|
|
232
|
+
|
|
233
|
+
describe("official test suite", () => {
|
|
234
|
+
test("passes all inputs", () => {
|
|
235
|
+
function checkPublicSuffix(input, expectedTld) {
|
|
236
|
+
const result = parseDomain(input, {privateTlds: true});
|
|
237
|
+
|
|
238
|
+
if (expectedTld === null) {
|
|
239
|
+
// When the expectedTld is null it means that the domain
|
|
240
|
+
// should not be registerable.
|
|
241
|
+
// Our module will return an empty string for the domain
|
|
242
|
+
// in that case. The tld should match the input.
|
|
243
|
+
expect(result.tld).toBe(input.toLowerCase());
|
|
244
|
+
expect(result.domain).toBe("");
|
|
245
|
+
} else {
|
|
246
|
+
expect(result.domain + "." + result.tld).toBe(expectedTld);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Any copyright is dedicated to the Public Domain.
|
|
251
|
+
// https://creativecommons.org/publicdomain/zero/1.0/
|
|
252
|
+
|
|
253
|
+
// null input.
|
|
254
|
+
// checkPublicSuffix(null, null);
|
|
255
|
+
// Mixed case.
|
|
256
|
+
checkPublicSuffix("COM", null);
|
|
257
|
+
checkPublicSuffix("example.COM", "example.com");
|
|
258
|
+
checkPublicSuffix("WwW.example.COM", "example.com");
|
|
259
|
+
// Leading dot.
|
|
260
|
+
// TODO: Make this test work
|
|
261
|
+
// checkPublicSuffix(".com", null);
|
|
262
|
+
// checkPublicSuffix(".example", null);
|
|
263
|
+
// checkPublicSuffix(".example.com", null);
|
|
264
|
+
// checkPublicSuffix(".example.example", null);
|
|
265
|
+
// Unlisted TLD.
|
|
266
|
+
// This is a strange test case. Why should 'example.example' be registerable when 'example' is unknown?
|
|
267
|
+
// checkPublicSuffix("example", null);
|
|
268
|
+
// checkPublicSuffix("example.example", "example.example");
|
|
269
|
+
// checkPublicSuffix("b.example.example", "example.example");
|
|
270
|
+
// checkPublicSuffix("a.b.example.example", "example.example");
|
|
271
|
+
// Listed, but non-Internet, TLD.
|
|
272
|
+
// checkPublicSuffix('local', null);
|
|
273
|
+
// checkPublicSuffix('example.local', null);
|
|
274
|
+
// checkPublicSuffix('b.example.local', null);
|
|
275
|
+
// checkPublicSuffix('a.b.example.local', null);
|
|
276
|
+
// TLD with only 1 rule.
|
|
277
|
+
checkPublicSuffix("biz", null);
|
|
278
|
+
checkPublicSuffix("domain.biz", "domain.biz");
|
|
279
|
+
checkPublicSuffix("b.domain.biz", "domain.biz");
|
|
280
|
+
checkPublicSuffix("a.b.domain.biz", "domain.biz");
|
|
281
|
+
// TLD with some 2-level rules.
|
|
282
|
+
checkPublicSuffix("com", null);
|
|
283
|
+
checkPublicSuffix("example.com", "example.com");
|
|
284
|
+
checkPublicSuffix("b.example.com", "example.com");
|
|
285
|
+
checkPublicSuffix("a.b.example.com", "example.com");
|
|
286
|
+
checkPublicSuffix("uk.com", null);
|
|
287
|
+
checkPublicSuffix("example.uk.com", "example.uk.com");
|
|
288
|
+
checkPublicSuffix("b.example.uk.com", "example.uk.com");
|
|
289
|
+
checkPublicSuffix("a.b.example.uk.com", "example.uk.com");
|
|
290
|
+
checkPublicSuffix("test.ac", "test.ac");
|
|
291
|
+
// TLD with only 1 (wildcard) rule.
|
|
292
|
+
checkPublicSuffix("mm", null);
|
|
293
|
+
checkPublicSuffix("c.mm", null);
|
|
294
|
+
checkPublicSuffix("b.c.mm", "b.c.mm");
|
|
295
|
+
checkPublicSuffix("a.b.c.mm", "b.c.mm");
|
|
296
|
+
// More complex TLD.
|
|
297
|
+
checkPublicSuffix("jp", null);
|
|
298
|
+
checkPublicSuffix("test.jp", "test.jp");
|
|
299
|
+
checkPublicSuffix("www.test.jp", "test.jp");
|
|
300
|
+
checkPublicSuffix("ac.jp", null);
|
|
301
|
+
checkPublicSuffix("test.ac.jp", "test.ac.jp");
|
|
302
|
+
checkPublicSuffix("www.test.ac.jp", "test.ac.jp");
|
|
303
|
+
checkPublicSuffix("kyoto.jp", null);
|
|
304
|
+
checkPublicSuffix("test.kyoto.jp", "test.kyoto.jp");
|
|
305
|
+
checkPublicSuffix("ide.kyoto.jp", null);
|
|
306
|
+
checkPublicSuffix("b.ide.kyoto.jp", "b.ide.kyoto.jp");
|
|
307
|
+
checkPublicSuffix("a.b.ide.kyoto.jp", "b.ide.kyoto.jp");
|
|
308
|
+
checkPublicSuffix("c.kobe.jp", null);
|
|
309
|
+
checkPublicSuffix("b.c.kobe.jp", "b.c.kobe.jp");
|
|
310
|
+
checkPublicSuffix("a.b.c.kobe.jp", "b.c.kobe.jp");
|
|
311
|
+
checkPublicSuffix("city.kobe.jp", "city.kobe.jp");
|
|
312
|
+
checkPublicSuffix("www.city.kobe.jp", "city.kobe.jp");
|
|
313
|
+
// TLD with a wildcard rule and exceptions.
|
|
314
|
+
checkPublicSuffix("ck", null);
|
|
315
|
+
checkPublicSuffix("test.ck", null);
|
|
316
|
+
checkPublicSuffix("b.test.ck", "b.test.ck");
|
|
317
|
+
checkPublicSuffix("a.b.test.ck", "b.test.ck");
|
|
318
|
+
checkPublicSuffix("www.ck", "www.ck");
|
|
319
|
+
checkPublicSuffix("www.www.ck", "www.ck");
|
|
320
|
+
// US K12.
|
|
321
|
+
checkPublicSuffix("us", null);
|
|
322
|
+
checkPublicSuffix("test.us", "test.us");
|
|
323
|
+
checkPublicSuffix("www.test.us", "test.us");
|
|
324
|
+
checkPublicSuffix("ak.us", null);
|
|
325
|
+
checkPublicSuffix("test.ak.us", "test.ak.us");
|
|
326
|
+
checkPublicSuffix("www.test.ak.us", "test.ak.us");
|
|
327
|
+
checkPublicSuffix("k12.ak.us", null);
|
|
328
|
+
checkPublicSuffix("test.k12.ak.us", "test.k12.ak.us");
|
|
329
|
+
checkPublicSuffix("www.test.k12.ak.us", "test.k12.ak.us");
|
|
330
|
+
// IDN labels.
|
|
331
|
+
checkPublicSuffix("食狮.com.cn", "食狮.com.cn");
|
|
332
|
+
checkPublicSuffix("食狮.公司.cn", "食狮.公司.cn");
|
|
333
|
+
checkPublicSuffix("www.食狮.公司.cn", "食狮.公司.cn");
|
|
334
|
+
checkPublicSuffix("shishi.公司.cn", "shishi.公司.cn");
|
|
335
|
+
checkPublicSuffix("公司.cn", null);
|
|
336
|
+
checkPublicSuffix("食狮.中国", "食狮.中国");
|
|
337
|
+
checkPublicSuffix("www.食狮.中国", "食狮.中国");
|
|
338
|
+
checkPublicSuffix("shishi.中国", "shishi.中国");
|
|
339
|
+
checkPublicSuffix("中国", null);
|
|
340
|
+
// Same as above, but punycoded.
|
|
341
|
+
// Punycode is currently not supported
|
|
342
|
+
// TODO: Make these tests work
|
|
343
|
+
// checkPublicSuffix("xn--85x722f.com.cn", "xn--85x722f.com.cn");
|
|
344
|
+
// checkPublicSuffix("xn--85x722f.xn--55qx5d.cn", "xn--85x722f.xn--55qx5d.cn");
|
|
345
|
+
// checkPublicSuffix("www.xn--85x722f.xn--55qx5d.cn", "xn--85x722f.xn--55qx5d.cn");
|
|
346
|
+
// checkPublicSuffix("shishi.xn--55qx5d.cn", "shishi.xn--55qx5d.cn");
|
|
347
|
+
// checkPublicSuffix("xn--55qx5d.cn", null);
|
|
348
|
+
// checkPublicSuffix("xn--85x722f.xn--fiqs8s", "xn--85x722f.xn--fiqs8s");
|
|
349
|
+
// checkPublicSuffix("www.xn--85x722f.xn--fiqs8s", "xn--85x722f.xn--fiqs8s");
|
|
350
|
+
// checkPublicSuffix("shishi.xn--fiqs8s", "shishi.xn--fiqs8s");
|
|
351
|
+
// checkPublicSuffix("xn--fiqs8s", null);
|
|
352
|
+
});
|
|
353
|
+
});
|
|
230
354
|
});
|
package/test/snapshots.test.js
CHANGED
|
@@ -2,13 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
const fs = require("fs");
|
|
4
4
|
const path = require("path");
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const serializeTrie = require("../lib/tries/serializeTrie");
|
|
8
|
-
const parseTrie = require("../lib/tries/parseTrie");
|
|
9
|
-
const lookUp = require("../lib/tries/lookUp");
|
|
5
|
+
const parsePubSuffixList = require("../lib/trie/parsePubSuffixList");
|
|
6
|
+
const serializeTrie = require("../lib/trie/serializeTrie");
|
|
10
7
|
|
|
11
|
-
const expect = chai.expect;
|
|
12
8
|
const TEST_SNAPSHOT = true;
|
|
13
9
|
const pathToFixtures = path.resolve(__dirname, "fixtures");
|
|
14
10
|
const pathToSnapshots = path.resolve(__dirname, "snapshots");
|
|
@@ -17,42 +13,23 @@ const pathToSerializeTrieSnapshot = path.resolve(pathToSnapshots, "serializeTrie
|
|
|
17
13
|
|
|
18
14
|
describe("snapshots", () => {
|
|
19
15
|
describe("parsePubSuffixList()", () => {
|
|
20
|
-
|
|
16
|
+
test("matches the approved snapshot", () => {
|
|
21
17
|
const pubSuffixList = fs.readFileSync(path.resolve(pathToFixtures, "pubSuffixList.txt"), "utf8");
|
|
22
18
|
const parsedList = parsePubSuffixList(pubSuffixList);
|
|
23
19
|
const snapshot = JSON.parse(fs.readFileSync(pathToParsePubSuffixListSnapshot, "utf8"));
|
|
24
20
|
|
|
25
|
-
TEST_SNAPSHOT && expect(parsedList).
|
|
21
|
+
TEST_SNAPSHOT && expect(parsedList).toEqual(snapshot);
|
|
26
22
|
fs.writeFileSync(pathToParsePubSuffixListSnapshot, JSON.stringify(parsedList));
|
|
27
23
|
});
|
|
28
24
|
});
|
|
29
25
|
describe("serializeTrie()", () => {
|
|
30
|
-
|
|
26
|
+
test("matches the approved snapshot", () => {
|
|
31
27
|
const parsedList = JSON.parse(fs.readFileSync(pathToParsePubSuffixListSnapshot, "utf8"));
|
|
32
28
|
const snapshot = JSON.parse(fs.readFileSync(pathToSerializeTrieSnapshot, "utf8"));
|
|
33
29
|
const serializedTrie = serializeTrie(parsedList.icann);
|
|
34
30
|
|
|
35
|
-
TEST_SNAPSHOT && expect(serializedTrie).
|
|
31
|
+
TEST_SNAPSHOT && expect(serializedTrie).toEqual(snapshot);
|
|
36
32
|
fs.writeFileSync(pathToSerializeTrieSnapshot, JSON.stringify(serializedTrie));
|
|
37
33
|
});
|
|
38
34
|
});
|
|
39
|
-
describe("parseTrie() and lookUp() calling lookUp() with the result from parseTrie(snapshot) and hostname", () => {
|
|
40
|
-
const serializedTrie = JSON.parse(fs.readFileSync(pathToSerializeTrieSnapshot, "utf8"));
|
|
41
|
-
const parsedTrie = parseTrie(serializedTrie);
|
|
42
|
-
|
|
43
|
-
[
|
|
44
|
-
["example.com", "com"],
|
|
45
|
-
["example.a.com", "com"],
|
|
46
|
-
["example.uk", "uk"],
|
|
47
|
-
["example.co.uk", "co.uk"],
|
|
48
|
-
["example.ab.uk", "uk"],
|
|
49
|
-
].forEach(testArgs => {
|
|
50
|
-
const hostname = testArgs[0];
|
|
51
|
-
const expectedResult = testArgs[1];
|
|
52
|
-
|
|
53
|
-
it(`'${hostname}' returns ${expectedResult}`, () => {
|
|
54
|
-
expect(lookUp(parsedTrie, hostname)).to.equal(expectedResult);
|
|
55
|
-
});
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
35
|
});
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const lookUp = require("../../lib/trie/lookUp");
|
|
4
|
+
const characters = require("../../lib/trie/characters");
|
|
5
|
+
const {createNode, adoptChild} = require("../../lib/trie/nodes");
|
|
6
|
+
|
|
7
|
+
function createOneLevelDeepTrie() {
|
|
8
|
+
const root = createNode();
|
|
9
|
+
const com = createNode("com");
|
|
10
|
+
|
|
11
|
+
adoptChild(root, com);
|
|
12
|
+
|
|
13
|
+
return root;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function createTwoLevelDeepTrie() {
|
|
17
|
+
const root = createNode();
|
|
18
|
+
const uk = createNode("uk");
|
|
19
|
+
const co = createNode("co");
|
|
20
|
+
|
|
21
|
+
adoptChild(root, uk);
|
|
22
|
+
adoptChild(uk, co);
|
|
23
|
+
|
|
24
|
+
return root;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function createTrieWithWildcardAndException() {
|
|
28
|
+
const root = createNode();
|
|
29
|
+
const wildcard = createNode(characters.WILDCARD);
|
|
30
|
+
const exception = createNode(characters.EXCEPTION + "exception");
|
|
31
|
+
|
|
32
|
+
adoptChild(root, wildcard);
|
|
33
|
+
adoptChild(root, exception);
|
|
34
|
+
|
|
35
|
+
return root;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
describe("lookUp()", () => {
|
|
39
|
+
describe("with an empty trie", () => {
|
|
40
|
+
test("returns an empty array", () => {
|
|
41
|
+
const root = createNode();
|
|
42
|
+
|
|
43
|
+
expect(lookUp(root, ["com"])).toEqual([]);
|
|
44
|
+
expect(lookUp(root, ["example", "com"])).toEqual([]);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
describe("with a one level deep trie", () => {
|
|
48
|
+
test("returns the known TLD as array", () => {
|
|
49
|
+
const root = createOneLevelDeepTrie();
|
|
50
|
+
|
|
51
|
+
expect(lookUp(root, ["com"])).toEqual(["com"]);
|
|
52
|
+
expect(lookUp(root, ["example", "com"])).toEqual(["com"]);
|
|
53
|
+
expect(lookUp(root, ["www", "example", "com"])).toEqual(["com"]);
|
|
54
|
+
});
|
|
55
|
+
test("returns an empty array if there is no known TLD", () => {
|
|
56
|
+
const root = createOneLevelDeepTrie();
|
|
57
|
+
|
|
58
|
+
expect(lookUp(root, ["de"])).toEqual([]);
|
|
59
|
+
expect(lookUp(root, ["example", "de"])).toEqual([]);
|
|
60
|
+
expect(lookUp(root, ["www", "example", "de"])).toEqual([]);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
describe("with a two level deep trie", () => {
|
|
64
|
+
test("returns the known TLD", () => {
|
|
65
|
+
const root = createTwoLevelDeepTrie();
|
|
66
|
+
|
|
67
|
+
expect(lookUp(root, ["uk"])).toEqual(["uk"]);
|
|
68
|
+
expect(lookUp(root, ["example", "uk"])).toEqual(["uk"]);
|
|
69
|
+
expect(lookUp(root, ["co", "uk"])).toEqual(["co", "uk"]);
|
|
70
|
+
expect(lookUp(root, ["example", "co", "uk"])).toEqual(["co", "uk"]);
|
|
71
|
+
expect(lookUp(root, ["www", "example", "co", "uk"])).toEqual(["co", "uk"]);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test("returns an empty array if there is no known TLD", () => {
|
|
75
|
+
const root = createTwoLevelDeepTrie();
|
|
76
|
+
|
|
77
|
+
expect(lookUp(root, ["de"])).toEqual([]);
|
|
78
|
+
expect(lookUp(root, ["example", "de"])).toEqual([]);
|
|
79
|
+
expect(lookUp(root, ["www", "example", "de"])).toEqual([]);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
describe("with a wildcard and exceptions", () => {
|
|
83
|
+
test("does not accept the exception as TLD", () => {
|
|
84
|
+
const root = createTrieWithWildcardAndException();
|
|
85
|
+
|
|
86
|
+
expect(lookUp(root, ["exception"])).toEqual([]);
|
|
87
|
+
expect(lookUp(root, ["www", "exception"])).toEqual([]);
|
|
88
|
+
});
|
|
89
|
+
test("accepts all domain names as TLD in place of the wildcard", () => {
|
|
90
|
+
const root = createTrieWithWildcardAndException();
|
|
91
|
+
|
|
92
|
+
expect(lookUp(root, ["anything"])).toEqual(["anything"]);
|
|
93
|
+
expect(lookUp(root, ["www", "anything"])).toEqual(["anything"]);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const {createNode, adoptChild} = require("../../lib/trie/nodes");
|
|
4
|
+
|
|
5
|
+
describe("adoptChild()", () => {
|
|
6
|
+
test("throws an error if the child has no domain", () => {
|
|
7
|
+
expect(() => {
|
|
8
|
+
adoptChild(createNode(), createNode());
|
|
9
|
+
}).toThrowError("Cannot adopt child: child.domain must be a string");
|
|
10
|
+
});
|
|
11
|
+
test(
|
|
12
|
+
"throws an error if the parent has already a child with that domain",
|
|
13
|
+
() => {
|
|
14
|
+
expect(() => {
|
|
15
|
+
const parent = createNode();
|
|
16
|
+
|
|
17
|
+
adoptChild(parent, createNode("some-domain"));
|
|
18
|
+
adoptChild(parent, createNode("some-domain"));
|
|
19
|
+
}).toThrowError(
|
|
20
|
+
"Cannot adopt child: parent has already a child with the domain 'some-domain'"
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
);
|
|
24
|
+
});
|