url_search_params_test.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. "use strict";
  2. const assert = require("assert.js");
  3. let params;
  4. function testCtor(value, expected) {
  5. assert.sameValue(new URLSearchParams(value).toString(), expected);
  6. }
  7. testCtor("user=abc&query=xyz", "user=abc&query=xyz");
  8. testCtor("?user=abc&query=xyz", "user=abc&query=xyz");
  9. testCtor(
  10. {
  11. num: 1,
  12. user: "abc",
  13. query: ["first", "second"],
  14. obj: { prop: "value" },
  15. b: true,
  16. },
  17. "num=1&user=abc&query=first%2Csecond&obj=%5Bobject+Object%5D&b=true"
  18. );
  19. const map = new Map();
  20. map.set("user", "abc");
  21. map.set("query", "xyz");
  22. testCtor(map, "user=abc&query=xyz");
  23. testCtor(
  24. [
  25. ["user", "abc"],
  26. ["query", "first"],
  27. ["query", "second"],
  28. ],
  29. "user=abc&query=first&query=second"
  30. );
  31. // Each key-value pair must have exactly two elements
  32. assert.throwsNodeError(() => new URLSearchParams([["single_value"]]), TypeError, "ERR_INVALID_TUPLE");
  33. assert.throwsNodeError(() => new URLSearchParams([["too", "many", "values"]]), TypeError, "ERR_INVALID_TUPLE");
  34. params = new URLSearchParams("a=b&cc=d");
  35. params.forEach((value, name, searchParams) => {
  36. if (name === "a") {
  37. assert.sameValue(value, "b");
  38. }
  39. if (name === "cc") {
  40. assert.sameValue(value, "d");
  41. }
  42. assert.sameValue(searchParams, params);
  43. });
  44. params.forEach((value, name, searchParams) => {
  45. if (name === "a") {
  46. assert.sameValue(value, "b");
  47. searchParams.set("cc", "d1");
  48. }
  49. if (name === "cc") {
  50. assert.sameValue(value, "d1");
  51. }
  52. assert.sameValue(searchParams, params);
  53. });
  54. assert.throwsNodeError(() => params.forEach(123), TypeError, "ERR_INVALID_ARG_TYPE");
  55. assert.throwsNodeError(() => params.forEach.call(1, 2), TypeError, "ERR_INVALID_THIS");
  56. params = new URLSearchParams("a=1=2&b=3");
  57. assert.sameValue(params.size, 2);
  58. assert.sameValue(params.get("a"), "1=2");
  59. assert.sameValue(params.get("b"), "3");
  60. params = new URLSearchParams("&");
  61. assert.sameValue(params.size, 0);
  62. params = new URLSearchParams("& ");
  63. assert.sameValue(params.size, 1);
  64. assert.sameValue(params.get(" "), "");
  65. params = new URLSearchParams(" &");
  66. assert.sameValue(params.size, 1);
  67. assert.sameValue(params.get(" "), "");
  68. params = new URLSearchParams("=");
  69. assert.sameValue(params.size, 1);
  70. assert.sameValue(params.get(""), "");
  71. params = new URLSearchParams("&=2");
  72. assert.sameValue(params.size, 1);
  73. assert.sameValue(params.get(""), "2");
  74. params = new URLSearchParams("?user=abc");
  75. assert.throwsNodeError(() => params.append(), TypeError, "ERR_MISSING_ARGS");
  76. params.append("query", "first");
  77. assert.sameValue(params.toString(), "user=abc&query=first");
  78. params = new URLSearchParams("first=one&second=two&third=three");
  79. assert.throwsNodeError(() => params.delete(), TypeError, "ERR_MISSING_ARGS");
  80. params.delete("second", "fake-value");
  81. assert.sameValue(params.toString(), "first=one&second=two&third=three");
  82. params.delete("third", "three");
  83. assert.sameValue(params.toString(), "first=one&second=two");
  84. params.delete("second");
  85. assert.sameValue(params.toString(), "first=one");
  86. params = new URLSearchParams("user=abc&query=xyz");
  87. assert.throwsNodeError(() => params.get(), TypeError, "ERR_MISSING_ARGS");
  88. assert.sameValue(params.get("user"), "abc");
  89. assert.sameValue(params.get("non-existant"), null);
  90. params = new URLSearchParams("query=first&query=second");
  91. assert.throwsNodeError(() => params.getAll(), TypeError, "ERR_MISSING_ARGS");
  92. const all = params.getAll("query");
  93. assert.sameValue(all.includes("first"), true);
  94. assert.sameValue(all.includes("second"), true);
  95. assert.sameValue(all.length, 2);
  96. const getAllUndefined = params.getAll(undefined);
  97. assert.sameValue(getAllUndefined.length, 0);
  98. const getAllNonExistant = params.getAll("does_not_exists");
  99. assert.sameValue(getAllNonExistant.length, 0);
  100. params = new URLSearchParams("user=abc&query=xyz");
  101. assert.throwsNodeError(() => params.has(), TypeError, "ERR_MISSING_ARGS");
  102. assert.sameValue(params.has(undefined), false);
  103. assert.sameValue(params.has("user"), true);
  104. assert.sameValue(params.has("user", "abc"), true);
  105. assert.sameValue(params.has("user", "abc", "extra-param"), true);
  106. assert.sameValue(params.has("user", "efg"), false);
  107. assert.sameValue(params.has("user", undefined), true);
  108. params = new URLSearchParams();
  109. params.append("foo", "bar");
  110. params.append("foo", "baz");
  111. params.append("abc", "def");
  112. assert.sameValue(params.toString(), "foo=bar&foo=baz&abc=def");
  113. params.set("foo", "def");
  114. params.set("xyz", "opq");
  115. assert.sameValue(params.toString(), "foo=def&abc=def&xyz=opq");
  116. params = new URLSearchParams("query=first&query=second&user=abc&double=first,second");
  117. const URLSearchIteratorPrototype = params.entries().__proto__;
  118. assert.sameValue(typeof URLSearchIteratorPrototype, "object");
  119. assert.sameValue(params[Symbol.iterator], params.entries);
  120. {
  121. const entries = params.entries();
  122. assert.sameValue(entries.toString(), "[object URLSearchParams Iterator]");
  123. assert.sameValue(entries.__proto__, URLSearchIteratorPrototype);
  124. let item = entries.next();
  125. assert.sameValue(item.value.toString(), ["query", "first"].toString());
  126. assert.sameValue(item.done, false);
  127. item = entries.next();
  128. assert.sameValue(item.value.toString(), ["query", "second"].toString());
  129. assert.sameValue(item.done, false);
  130. item = entries.next();
  131. assert.sameValue(item.value.toString(), ["user", "abc"].toString());
  132. assert.sameValue(item.done, false);
  133. item = entries.next();
  134. assert.sameValue(item.value.toString(), ["double", "first,second"].toString());
  135. assert.sameValue(item.done, false);
  136. item = entries.next();
  137. assert.sameValue(item.value, undefined);
  138. assert.sameValue(item.done, true);
  139. }
  140. params = new URLSearchParams("query=first&query=second&user=abc");
  141. {
  142. const keys = params.keys();
  143. assert.sameValue(keys.__proto__, URLSearchIteratorPrototype);
  144. let item = keys.next();
  145. assert.sameValue(item.value, "query");
  146. assert.sameValue(item.done, false);
  147. item = keys.next();
  148. assert.sameValue(item.value, "query");
  149. assert.sameValue(item.done, false);
  150. item = keys.next();
  151. assert.sameValue(item.value, "user");
  152. assert.sameValue(item.done, false);
  153. item = keys.next();
  154. assert.sameValue(item.value, undefined);
  155. assert.sameValue(item.done, true);
  156. }
  157. params = new URLSearchParams("query=first&query=second&user=abc");
  158. {
  159. const values = params.values();
  160. assert.sameValue(values.__proto__, URLSearchIteratorPrototype);
  161. let item = values.next();
  162. assert.sameValue(item.value, "first");
  163. assert.sameValue(item.done, false);
  164. item = values.next();
  165. assert.sameValue(item.value, "second");
  166. assert.sameValue(item.done, false);
  167. item = values.next();
  168. assert.sameValue(item.value, "abc");
  169. assert.sameValue(item.done, false);
  170. item = values.next();
  171. assert.sameValue(item.value, undefined);
  172. assert.sameValue(item.done, true);
  173. }
  174. params = new URLSearchParams("query[]=abc&type=search&query[]=123");
  175. params.sort();
  176. assert.sameValue(params.toString(), "query%5B%5D=abc&query%5B%5D=123&type=search");
  177. params = new URLSearchParams("query=first&query=second&user=abc");
  178. assert.sameValue(params.size, 3);
  179. params = new URLSearchParams("%");
  180. assert.sameValue(params.has("%"), true);
  181. assert.sameValue(params.toString(), "%25=");
  182. {
  183. const params = new URLSearchParams("");
  184. assert.sameValue(params.size, 0);
  185. assert.sameValue(params.toString(), "");
  186. assert.sameValue(params.get(undefined), null);
  187. params.set(undefined, true);
  188. assert.sameValue(params.has(undefined), true);
  189. assert.sameValue(params.has("undefined"), true);
  190. assert.sameValue(params.get("undefined"), "true");
  191. assert.sameValue(params.get(undefined), "true");
  192. assert.sameValue(params.getAll(undefined).toString(), ["true"].toString());
  193. params.delete(undefined);
  194. assert.sameValue(params.has(undefined), false);
  195. assert.sameValue(params.has("undefined"), false);
  196. assert.sameValue(params.has(null), false);
  197. params.set(null, "nullval");
  198. assert.sameValue(params.has(null), true);
  199. assert.sameValue(params.has("null"), true);
  200. assert.sameValue(params.get(null), "nullval");
  201. assert.sameValue(params.get("null"), "nullval");
  202. params.delete(null);
  203. assert.sameValue(params.has(null), false);
  204. assert.sameValue(params.has("null"), false);
  205. }
  206. function* functionGeneratorExample() {
  207. yield ["user", "abc"];
  208. yield ["query", "first"];
  209. yield ["query", "second"];
  210. }
  211. params = new URLSearchParams(functionGeneratorExample());
  212. assert.sameValue(params.toString(), "user=abc&query=first&query=second");
  213. assert.sameValue(params.__proto__.constructor, URLSearchParams);
  214. assert.sameValue(params instanceof URLSearchParams, true);
  215. {
  216. const params = new URLSearchParams("1=2&1=3");
  217. assert.sameValue(params.get(1), "2");
  218. assert.sameValue(params.getAll(1).toString(), ["2", "3"].toString());
  219. assert.sameValue(params.getAll("x").toString(), [].toString());
  220. }
  221. // Sync
  222. {
  223. const url = new URL("https://test.com/");
  224. const params = url.searchParams;
  225. assert.sameValue(params.size, 0);
  226. url.search = "a=1";
  227. assert.sameValue(params.size, 1);
  228. assert.sameValue(params.get("a"), "1");
  229. }
  230. {
  231. const url = new URL("https://test.com/?a=1");
  232. const params = url.searchParams;
  233. assert.sameValue(params.size, 1);
  234. url.search = "";
  235. assert.sameValue(params.size, 0);
  236. url.search = "b=2";
  237. assert.sameValue(params.size, 1);
  238. }
  239. {
  240. const url = new URL("https://test.com/");
  241. const params = url.searchParams;
  242. params.append("a", "1");
  243. assert.sameValue(url.toString(), "https://test.com/?a=1");
  244. }
  245. {
  246. const url = new URL("https://test.com/");
  247. url.searchParams.append("a", "1");
  248. url.searchParams.append("b", "1");
  249. assert.sameValue(url.toString(), "https://test.com/?a=1&b=1");
  250. }
  251. {
  252. const url = new URL("https://test.com/");
  253. const params = url.searchParams;
  254. url.searchParams.append("a", "1");
  255. assert.sameValue(url.search, "?a=1");
  256. }
  257. {
  258. const url = new URL("https://test.com/?a=1");
  259. const params = url.searchParams;
  260. params.append("a", "2");
  261. assert.sameValue(url.search, "?a=1&a=2");
  262. }
  263. {
  264. const url = new URL("https://test.com/");
  265. const params = url.searchParams;
  266. params.set("a", "1");
  267. assert.sameValue(url.search, "?a=1");
  268. }
  269. {
  270. const url = new URL("https://test.com/");
  271. url.searchParams.set("a", "1");
  272. url.searchParams.set("b", "1");
  273. assert.sameValue(url.toString(), "https://test.com/?a=1&b=1");
  274. }
  275. {
  276. const url = new URL("https://test.com/?a=1&b=2");
  277. const params = url.searchParams;
  278. params.delete("a");
  279. assert.sameValue(url.search, "?b=2");
  280. }
  281. {
  282. const url = new URL("https://test.com/?b=2&a=1");
  283. const params = url.searchParams;
  284. params.sort();
  285. assert.sameValue(url.search, "?a=1&b=2");
  286. }
  287. {
  288. const url = new URL("https://test.com/?a=1");
  289. const params = url.searchParams;
  290. params.delete("a");
  291. assert.sameValue(url.search, "");
  292. params.set("a", 2);
  293. assert.sameValue(url.search, "?a=2");
  294. }
  295. // FAILING: no custom properties on wrapped Go structs
  296. /*
  297. {
  298. const params = new URLSearchParams("");
  299. assert.sameValue(Object.isExtensible(params), true);
  300. assert.sameValue(Reflect.defineProperty(params, "customField", {value: 42, configurable: true}), true);
  301. assert.sameValue(params.customField, 42);
  302. const desc = Reflect.getOwnPropertyDescriptor(params, "customField");
  303. assert.sameValue(desc.value, 42);
  304. assert.sameValue(desc.writable, false);
  305. assert.sameValue(desc.enumerable, false);
  306. assert.sameValue(desc.configurable, true);
  307. }
  308. */
  309. // Escape
  310. {
  311. const myURL = new URL('https://example.org/abc?fo~o=~ba r%z');
  312. assert.sameValue(myURL.search, "?fo~o=~ba%20r%z");
  313. // Modify the URL via searchParams...
  314. myURL.searchParams.sort();
  315. assert.sameValue(myURL.search, "?fo%7Eo=%7Eba+r%25z");
  316. }