๐Ÿ“ฆ robhogan / jsc-safe-url

๐Ÿ“„ test.js ยท 121 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121const { describe, test } = require("node:test");
const assert = require("node:assert");

const { isJscSafeUrl, toNormalUrl, toJscSafeUrl } = require("./index");

describe("toNormalUrl", () => {
  for (const [input, output] of [
    [
      "/path1/path2//&foo=bar?bar=baz#frag?",
      "/path1/path2?foo=bar&bar=baz#frag?",
    ],
    [
      "relative/path/with%3B%26/encoded//&foo=bar?bar=baz#frag?",
      "relative/path/with%3B%26/encoded?foo=bar&bar=baz#frag?",
    ],
    [
      "https://user:password@mydomain.com:8080/path1/path2//&foo=bar?bar=baz#frag?",
      "https://user:password@mydomain.com:8080/path1/path2?foo=bar&bar=baz#frag?",
    ],
    [
      "http://127.0.0.1/path1/path2//&foo=bar&bar=baz",
      "http://127.0.0.1/path1/path2?foo=bar&bar=baz",
    ],
  ]) {
    test(`rewrites urls treating // in paths as ? (${input} => ${output})`, () => {
      assert.strictEqual(toNormalUrl(input), output);
      assert.strictEqual(output, toNormalUrl(output));
    });
  }

  for (const url of [
    "http://user:password/@mydomain.com/foo?bar=zoo?baz=quux//&",
    "/foo?bar=zoo?baz=quux",
    "proto:arbitrary_bad_url",
    "*",
    "relative/path",
  ])
    `returns other strings exactly as given (${url})`,
      () => {
        assert.strictEqual(toNormalUrl(url), url);
      };
});

describe("toJscSafeUrl", () => {
  for (const [input, output] of [
    [
      "https://user:password@mydomain.com:8080/path1/path2?foo=bar&bar=question?#frag?",
      "https://user:password@mydomain.com:8080/path1/path2//&foo=bar&bar=question%3F#frag?",
    ],
    [
      "http://127.0.0.1/path1/path2?foo=bar",
      "http://127.0.0.1/path1/path2//&foo=bar",
    ],
    ["*", "*"],
    ["/absolute/path", "/absolute/path"],
    ["relative/path", "relative/path"],
    ["/?", "/"],
    ["http://127.0.0.1/path1/path", "http://127.0.0.1/path1/path"],
    [
      "/path1/path2?foo=bar&bar=question?#frag?",
      "/path1/path2//&foo=bar&bar=question%3F#frag?",
    ],
    [
      "relative/path?foo=bar&bar=question?#frag?",
      "relative/path//&foo=bar&bar=question%3F#frag?",
    ],
    [
      "/path1/path2//&foo=bar&bar=question%3F?extra=query#frag?",
      "/path1/path2//&foo=bar&bar=question%3F&extra=query#frag?",
    ],
  ]) {
    test(`replaces the first ? with a JSC-friendly delimeter, url-encodes subsequent ?, and is idempotent (${input} => ${output})`, () => {
      assert.strictEqual(toJscSafeUrl(input), output);
      assert.strictEqual(output, toJscSafeUrl(output));
    });
  }

  for (const input of [
    "http://127.0.0.1?foo=bar",
    "http://127.0.0.1?q#hash",
    "?foo=bar",
    "?foo=/bar#hash",
    "/?bar=baz/",
  ]) {
    test(`throws on a URL with an empty path and a query string (${input})`, () => {
      assert.throws(
        () => toJscSafeUrl(input),
        new Error(
          `The given URL "${input}" has an empty path and cannot be converted to a JSC-safe format.`
        )
      );
    });
  }
});

describe("isJscSafeUrl", () => {
  for (const input of [
    "http://example.com//&foo=bar//#frag=//",
    "http://example.com/with/path//&foo=bar//#frag=//",
    "//&foo=bar//#frag=//",
    "relative/path///&foo=bar//&#frag=//&",
    "/absolute/path//&foo=bar//&#frag=//&",
  ]) {
    test(`is a JSC URL (${input})`, () => {
      assert.strictEqual(isJscSafeUrl(input), true);
    });
  }

  for (const input of [
    "http://example.com?foo=bar//&#frag=//",
    "http://example.com/with/path/?foo=bar//&#frag=//",
    "?foo=bar//&#frag=//&",
    "relative/path/?foo=bar//#frag=//",
    "/absolute/path/?foo=bar//&#frag=//",
  ]) {
    test(`is not a JSC URL (${input})`, () => {
      assert.strictEqual(isJscSafeUrl(input), false);
    });
  }
});