@nocobase/plugin-multi-keyword-filter 2.0.3

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.
Files changed (54) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +99 -0
  3. package/client.d.ts +2 -0
  4. package/client.js +1 -0
  5. package/dist/client/0d9b6225e99c9b66.js +10 -0
  6. package/dist/client/MultipleKeywordsInput.d.ts +15 -0
  7. package/dist/client/index.d.ts +15 -0
  8. package/dist/client/index.js +10 -0
  9. package/dist/client/interceptor.d.ts +9 -0
  10. package/dist/client/locale.d.ts +10 -0
  11. package/dist/externalVersion.js +20 -0
  12. package/dist/index.d.ts +10 -0
  13. package/dist/index.js +48 -0
  14. package/dist/locale/de-DE.json +18 -0
  15. package/dist/locale/en-US.json +18 -0
  16. package/dist/locale/es-ES.json +18 -0
  17. package/dist/locale/fr-FR.json +18 -0
  18. package/dist/locale/hu-HU.json +18 -0
  19. package/dist/locale/id-ID.json +18 -0
  20. package/dist/locale/it-IT.json +18 -0
  21. package/dist/locale/ja-JP.json +18 -0
  22. package/dist/locale/ko-KR.json +18 -0
  23. package/dist/locale/nl-NL.json +18 -0
  24. package/dist/locale/pt-BR.json +18 -0
  25. package/dist/locale/ru-RU.json +18 -0
  26. package/dist/locale/tr-TR.json +18 -0
  27. package/dist/locale/uk-UA.json +18 -0
  28. package/dist/locale/vi-VN.json +18 -0
  29. package/dist/locale/zh-CN.json +18 -0
  30. package/dist/locale/zh-TW.json +18 -0
  31. package/dist/node_modules/qs/.editorconfig +43 -0
  32. package/dist/node_modules/qs/.eslintrc +38 -0
  33. package/dist/node_modules/qs/.github/FUNDING.yml +12 -0
  34. package/dist/node_modules/qs/.nycrc +13 -0
  35. package/dist/node_modules/qs/dist/qs.js +2087 -0
  36. package/dist/node_modules/qs/lib/formats.js +23 -0
  37. package/dist/node_modules/qs/lib/index.js +1 -0
  38. package/dist/node_modules/qs/lib/parse.js +264 -0
  39. package/dist/node_modules/qs/lib/stringify.js +320 -0
  40. package/dist/node_modules/qs/lib/utils.js +252 -0
  41. package/dist/node_modules/qs/package.json +1 -0
  42. package/dist/node_modules/qs/test/empty-keys-cases.js +37 -0
  43. package/dist/node_modules/qs/test/parse.js +898 -0
  44. package/dist/node_modules/qs/test/stringify.js +972 -0
  45. package/dist/node_modules/qs/test/utils.js +136 -0
  46. package/dist/server/index.d.ts +9 -0
  47. package/dist/server/index.js +42 -0
  48. package/dist/server/middlewares.d.ts +10 -0
  49. package/dist/server/middlewares.js +63 -0
  50. package/dist/server/plugin.d.ts +19 -0
  51. package/dist/server/plugin.js +58 -0
  52. package/package.json +31 -0
  53. package/server.d.ts +2 -0
  54. package/server.js +1 -0
@@ -0,0 +1,972 @@
1
+ 'use strict';
2
+
3
+ var test = require('tape');
4
+ var qs = require('../');
5
+ var utils = require('../lib/utils');
6
+ var iconv = require('iconv-lite');
7
+ var SaferBuffer = require('safer-buffer').Buffer;
8
+ var hasSymbols = require('has-symbols');
9
+ var emptyTestCases = require('./empty-keys-cases').emptyTestCases;
10
+ var hasBigInt = typeof BigInt === 'function';
11
+
12
+ test('stringify()', function (t) {
13
+ t.test('stringifies a querystring object', function (st) {
14
+ st.equal(qs.stringify({ a: 'b' }), 'a=b');
15
+ st.equal(qs.stringify({ a: 1 }), 'a=1');
16
+ st.equal(qs.stringify({ a: 1, b: 2 }), 'a=1&b=2');
17
+ st.equal(qs.stringify({ a: 'A_Z' }), 'a=A_Z');
18
+ st.equal(qs.stringify({ a: '€' }), 'a=%E2%82%AC');
19
+ st.equal(qs.stringify({ a: '' }), 'a=%EE%80%80');
20
+ st.equal(qs.stringify({ a: 'א' }), 'a=%D7%90');
21
+ st.equal(qs.stringify({ a: '𐐷' }), 'a=%F0%90%90%B7');
22
+ st.end();
23
+ });
24
+
25
+ t.test('stringifies falsy values', function (st) {
26
+ st.equal(qs.stringify(undefined), '');
27
+ st.equal(qs.stringify(null), '');
28
+ st.equal(qs.stringify(null, { strictNullHandling: true }), '');
29
+ st.equal(qs.stringify(false), '');
30
+ st.equal(qs.stringify(0), '');
31
+ st.end();
32
+ });
33
+
34
+ t.test('stringifies symbols', { skip: !hasSymbols() }, function (st) {
35
+ st.equal(qs.stringify(Symbol.iterator), '');
36
+ st.equal(qs.stringify([Symbol.iterator]), '0=Symbol%28Symbol.iterator%29');
37
+ st.equal(qs.stringify({ a: Symbol.iterator }), 'a=Symbol%28Symbol.iterator%29');
38
+ st.equal(
39
+ qs.stringify({ a: [Symbol.iterator] }, { encodeValuesOnly: true, arrayFormat: 'brackets' }),
40
+ 'a[]=Symbol%28Symbol.iterator%29'
41
+ );
42
+ st.end();
43
+ });
44
+
45
+ t.test('stringifies bigints', { skip: !hasBigInt }, function (st) {
46
+ var three = BigInt(3);
47
+ var encodeWithN = function (value, defaultEncoder, charset) {
48
+ var result = defaultEncoder(value, defaultEncoder, charset);
49
+ return typeof value === 'bigint' ? result + 'n' : result;
50
+ };
51
+ st.equal(qs.stringify(three), '');
52
+ st.equal(qs.stringify([three]), '0=3');
53
+ st.equal(qs.stringify([three], { encoder: encodeWithN }), '0=3n');
54
+ st.equal(qs.stringify({ a: three }), 'a=3');
55
+ st.equal(qs.stringify({ a: three }, { encoder: encodeWithN }), 'a=3n');
56
+ st.equal(
57
+ qs.stringify({ a: [three] }, { encodeValuesOnly: true, arrayFormat: 'brackets' }),
58
+ 'a[]=3'
59
+ );
60
+ st.equal(
61
+ qs.stringify({ a: [three] }, { encodeValuesOnly: true, encoder: encodeWithN, arrayFormat: 'brackets' }),
62
+ 'a[]=3n'
63
+ );
64
+ st.end();
65
+ });
66
+
67
+ t.test('adds query prefix', function (st) {
68
+ st.equal(qs.stringify({ a: 'b' }, { addQueryPrefix: true }), '?a=b');
69
+ st.end();
70
+ });
71
+
72
+ t.test('with query prefix, outputs blank string given an empty object', function (st) {
73
+ st.equal(qs.stringify({}, { addQueryPrefix: true }), '');
74
+ st.end();
75
+ });
76
+
77
+ t.test('stringifies nested falsy values', function (st) {
78
+ st.equal(qs.stringify({ a: { b: { c: null } } }), 'a%5Bb%5D%5Bc%5D=');
79
+ st.equal(qs.stringify({ a: { b: { c: null } } }, { strictNullHandling: true }), 'a%5Bb%5D%5Bc%5D');
80
+ st.equal(qs.stringify({ a: { b: { c: false } } }), 'a%5Bb%5D%5Bc%5D=false');
81
+ st.end();
82
+ });
83
+
84
+ t.test('stringifies a nested object', function (st) {
85
+ st.equal(qs.stringify({ a: { b: 'c' } }), 'a%5Bb%5D=c');
86
+ st.equal(qs.stringify({ a: { b: { c: { d: 'e' } } } }), 'a%5Bb%5D%5Bc%5D%5Bd%5D=e');
87
+ st.end();
88
+ });
89
+
90
+ t.test('stringifies a nested object with dots notation', function (st) {
91
+ st.equal(qs.stringify({ a: { b: 'c' } }, { allowDots: true }), 'a.b=c');
92
+ st.equal(qs.stringify({ a: { b: { c: { d: 'e' } } } }, { allowDots: true }), 'a.b.c.d=e');
93
+ st.end();
94
+ });
95
+
96
+ t.test('stringifies an array value', function (st) {
97
+ st.equal(
98
+ qs.stringify({ a: ['b', 'c', 'd'] }, { arrayFormat: 'indices' }),
99
+ 'a%5B0%5D=b&a%5B1%5D=c&a%5B2%5D=d',
100
+ 'indices => indices'
101
+ );
102
+ st.equal(
103
+ qs.stringify({ a: ['b', 'c', 'd'] }, { arrayFormat: 'brackets' }),
104
+ 'a%5B%5D=b&a%5B%5D=c&a%5B%5D=d',
105
+ 'brackets => brackets'
106
+ );
107
+ st.equal(
108
+ qs.stringify({ a: ['b', 'c', 'd'] }, { arrayFormat: 'comma' }),
109
+ 'a=b%2Cc%2Cd',
110
+ 'comma => comma'
111
+ );
112
+ st.equal(
113
+ qs.stringify({ a: ['b', 'c', 'd'] }),
114
+ 'a%5B0%5D=b&a%5B1%5D=c&a%5B2%5D=d',
115
+ 'default => indices'
116
+ );
117
+ st.end();
118
+ });
119
+
120
+ t.test('omits nulls when asked', function (st) {
121
+ st.equal(qs.stringify({ a: 'b', c: null }, { skipNulls: true }), 'a=b');
122
+ st.end();
123
+ });
124
+
125
+ t.test('omits nested nulls when asked', function (st) {
126
+ st.equal(qs.stringify({ a: { b: 'c', d: null } }, { skipNulls: true }), 'a%5Bb%5D=c');
127
+ st.end();
128
+ });
129
+
130
+ t.test('omits array indices when asked', function (st) {
131
+ st.equal(qs.stringify({ a: ['b', 'c', 'd'] }, { indices: false }), 'a=b&a=c&a=d');
132
+ st.end();
133
+ });
134
+
135
+ t.test('stringifies an array value with one item vs multiple items', function (st) {
136
+ st.test('non-array item', function (s2t) {
137
+ s2t.equal(qs.stringify({ a: 'c' }, { encodeValuesOnly: true, arrayFormat: 'indices' }), 'a=c');
138
+ s2t.equal(qs.stringify({ a: 'c' }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), 'a=c');
139
+ s2t.equal(qs.stringify({ a: 'c' }, { encodeValuesOnly: true, arrayFormat: 'comma' }), 'a=c');
140
+ s2t.equal(qs.stringify({ a: 'c' }, { encodeValuesOnly: true }), 'a=c');
141
+
142
+ s2t.end();
143
+ });
144
+
145
+ st.test('array with a single item', function (s2t) {
146
+ s2t.equal(qs.stringify({ a: ['c'] }, { encodeValuesOnly: true, arrayFormat: 'indices' }), 'a[0]=c');
147
+ s2t.equal(qs.stringify({ a: ['c'] }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), 'a[]=c');
148
+ s2t.equal(qs.stringify({ a: ['c'] }, { encodeValuesOnly: true, arrayFormat: 'comma' }), 'a=c');
149
+ s2t.equal(qs.stringify({ a: ['c'] }, { encodeValuesOnly: true, arrayFormat: 'comma', commaRoundTrip: true }), 'a[]=c'); // so it parses back as an array
150
+ s2t.equal(qs.stringify({ a: ['c'] }, { encodeValuesOnly: true }), 'a[0]=c');
151
+
152
+ s2t.end();
153
+ });
154
+
155
+ st.test('array with multiple items', function (s2t) {
156
+ s2t.equal(qs.stringify({ a: ['c', 'd'] }, { encodeValuesOnly: true, arrayFormat: 'indices' }), 'a[0]=c&a[1]=d');
157
+ s2t.equal(qs.stringify({ a: ['c', 'd'] }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), 'a[]=c&a[]=d');
158
+ s2t.equal(qs.stringify({ a: ['c', 'd'] }, { encodeValuesOnly: true, arrayFormat: 'comma' }), 'a=c,d');
159
+ s2t.equal(qs.stringify({ a: ['c', 'd'] }, { encodeValuesOnly: true }), 'a[0]=c&a[1]=d');
160
+
161
+ s2t.end();
162
+ });
163
+
164
+ st.test('array with multiple items with a comma inside', function (s2t) {
165
+ s2t.equal(qs.stringify({ a: ['c,d', 'e'] }, { encodeValuesOnly: true, arrayFormat: 'comma' }), 'a=c%2Cd,e');
166
+ s2t.equal(qs.stringify({ a: ['c,d', 'e'] }, { arrayFormat: 'comma' }), 'a=c%2Cd%2Ce');
167
+
168
+ s2t.end();
169
+ });
170
+
171
+ st.end();
172
+ });
173
+
174
+ t.test('stringifies a nested array value', function (st) {
175
+ st.equal(qs.stringify({ a: { b: ['c', 'd'] } }, { encodeValuesOnly: true, arrayFormat: 'indices' }), 'a[b][0]=c&a[b][1]=d');
176
+ st.equal(qs.stringify({ a: { b: ['c', 'd'] } }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), 'a[b][]=c&a[b][]=d');
177
+ st.equal(qs.stringify({ a: { b: ['c', 'd'] } }, { encodeValuesOnly: true, arrayFormat: 'comma' }), 'a[b]=c,d');
178
+ st.equal(qs.stringify({ a: { b: ['c', 'd'] } }, { encodeValuesOnly: true }), 'a[b][0]=c&a[b][1]=d');
179
+ st.end();
180
+ });
181
+
182
+ t.test('stringifies comma and empty array values', function (st) {
183
+ st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: false, arrayFormat: 'indices' }), 'a[0]=,&a[1]=&a[2]=c,d%');
184
+ st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: false, arrayFormat: 'brackets' }), 'a[]=,&a[]=&a[]=c,d%');
185
+ st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: false, arrayFormat: 'comma' }), 'a=,,,c,d%');
186
+ st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: false, arrayFormat: 'repeat' }), 'a=,&a=&a=c,d%');
187
+
188
+ st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: true, arrayFormat: 'indices' }), 'a[0]=%2C&a[1]=&a[2]=c%2Cd%25');
189
+ st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: true, arrayFormat: 'brackets' }), 'a[]=%2C&a[]=&a[]=c%2Cd%25');
190
+ st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: true, arrayFormat: 'comma' }), 'a=%2C,,c%2Cd%25');
191
+ st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: true, arrayFormat: 'repeat' }), 'a=%2C&a=&a=c%2Cd%25');
192
+
193
+ st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: false, arrayFormat: 'indices' }), 'a%5B0%5D=%2C&a%5B1%5D=&a%5B2%5D=c%2Cd%25');
194
+ st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: false, arrayFormat: 'brackets' }), 'a%5B%5D=%2C&a%5B%5D=&a%5B%5D=c%2Cd%25');
195
+ st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: false, arrayFormat: 'comma' }), 'a=%2C%2C%2Cc%2Cd%25');
196
+ st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: false, arrayFormat: 'repeat' }), 'a=%2C&a=&a=c%2Cd%25');
197
+
198
+ st.end();
199
+ });
200
+
201
+ t.test('stringifies comma and empty non-array values', function (st) {
202
+ st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: false, arrayFormat: 'indices' }), 'a=,&b=&c=c,d%');
203
+ st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: false, arrayFormat: 'brackets' }), 'a=,&b=&c=c,d%');
204
+ st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: false, arrayFormat: 'comma' }), 'a=,&b=&c=c,d%');
205
+ st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: false, arrayFormat: 'repeat' }), 'a=,&b=&c=c,d%');
206
+
207
+ st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: true, encodeValuesOnly: true, arrayFormat: 'indices' }), 'a=%2C&b=&c=c%2Cd%25');
208
+ st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: true, encodeValuesOnly: true, arrayFormat: 'brackets' }), 'a=%2C&b=&c=c%2Cd%25');
209
+ st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: true, encodeValuesOnly: true, arrayFormat: 'comma' }), 'a=%2C&b=&c=c%2Cd%25');
210
+ st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: true, encodeValuesOnly: true, arrayFormat: 'repeat' }), 'a=%2C&b=&c=c%2Cd%25');
211
+
212
+ st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: true, encodeValuesOnly: false, arrayFormat: 'indices' }), 'a=%2C&b=&c=c%2Cd%25');
213
+ st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: true, encodeValuesOnly: false, arrayFormat: 'brackets' }), 'a=%2C&b=&c=c%2Cd%25');
214
+ st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: true, encodeValuesOnly: false, arrayFormat: 'comma' }), 'a=%2C&b=&c=c%2Cd%25');
215
+ st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: true, encodeValuesOnly: false, arrayFormat: 'repeat' }), 'a=%2C&b=&c=c%2Cd%25');
216
+
217
+ st.end();
218
+ });
219
+
220
+ t.test('stringifies a nested array value with dots notation', function (st) {
221
+ st.equal(
222
+ qs.stringify(
223
+ { a: { b: ['c', 'd'] } },
224
+ { allowDots: true, encodeValuesOnly: true, arrayFormat: 'indices' }
225
+ ),
226
+ 'a.b[0]=c&a.b[1]=d',
227
+ 'indices: stringifies with dots + indices'
228
+ );
229
+ st.equal(
230
+ qs.stringify(
231
+ { a: { b: ['c', 'd'] } },
232
+ { allowDots: true, encodeValuesOnly: true, arrayFormat: 'brackets' }
233
+ ),
234
+ 'a.b[]=c&a.b[]=d',
235
+ 'brackets: stringifies with dots + brackets'
236
+ );
237
+ st.equal(
238
+ qs.stringify(
239
+ { a: { b: ['c', 'd'] } },
240
+ { allowDots: true, encodeValuesOnly: true, arrayFormat: 'comma' }
241
+ ),
242
+ 'a.b=c,d',
243
+ 'comma: stringifies with dots + comma'
244
+ );
245
+ st.equal(
246
+ qs.stringify(
247
+ { a: { b: ['c', 'd'] } },
248
+ { allowDots: true, encodeValuesOnly: true }
249
+ ),
250
+ 'a.b[0]=c&a.b[1]=d',
251
+ 'default: stringifies with dots + indices'
252
+ );
253
+ st.end();
254
+ });
255
+
256
+ t.test('stringifies an object inside an array', function (st) {
257
+ st.equal(
258
+ qs.stringify({ a: [{ b: 'c' }] }, { arrayFormat: 'indices' }),
259
+ 'a%5B0%5D%5Bb%5D=c', // a[0][b]=c
260
+ 'indices => brackets'
261
+ );
262
+ st.equal(
263
+ qs.stringify({ a: [{ b: 'c' }] }, { arrayFormat: 'brackets' }),
264
+ 'a%5B%5D%5Bb%5D=c', // a[][b]=c
265
+ 'brackets => brackets'
266
+ );
267
+ st.equal(
268
+ qs.stringify({ a: [{ b: 'c' }] }),
269
+ 'a%5B0%5D%5Bb%5D=c',
270
+ 'default => indices'
271
+ );
272
+
273
+ st.equal(
274
+ qs.stringify({ a: [{ b: { c: [1] } }] }, { arrayFormat: 'indices' }),
275
+ 'a%5B0%5D%5Bb%5D%5Bc%5D%5B0%5D=1',
276
+ 'indices => indices'
277
+ );
278
+
279
+ st.equal(
280
+ qs.stringify({ a: [{ b: { c: [1] } }] }, { arrayFormat: 'brackets' }),
281
+ 'a%5B%5D%5Bb%5D%5Bc%5D%5B%5D=1',
282
+ 'brackets => brackets'
283
+ );
284
+
285
+ st.equal(
286
+ qs.stringify({ a: [{ b: { c: [1] } }] }),
287
+ 'a%5B0%5D%5Bb%5D%5Bc%5D%5B0%5D=1',
288
+ 'default => indices'
289
+ );
290
+
291
+ st.end();
292
+ });
293
+
294
+ t.test('stringifies an array with mixed objects and primitives', function (st) {
295
+ st.equal(
296
+ qs.stringify({ a: [{ b: 1 }, 2, 3] }, { encodeValuesOnly: true, arrayFormat: 'indices' }),
297
+ 'a[0][b]=1&a[1]=2&a[2]=3',
298
+ 'indices => indices'
299
+ );
300
+ st.equal(
301
+ qs.stringify({ a: [{ b: 1 }, 2, 3] }, { encodeValuesOnly: true, arrayFormat: 'brackets' }),
302
+ 'a[][b]=1&a[]=2&a[]=3',
303
+ 'brackets => brackets'
304
+ );
305
+ st.equal(
306
+ qs.stringify({ a: [{ b: 1 }, 2, 3] }, { encodeValuesOnly: true, arrayFormat: 'comma' }),
307
+ '???',
308
+ 'brackets => brackets',
309
+ { skip: 'TODO: figure out what this should do' }
310
+ );
311
+ st.equal(
312
+ qs.stringify({ a: [{ b: 1 }, 2, 3] }, { encodeValuesOnly: true }),
313
+ 'a[0][b]=1&a[1]=2&a[2]=3',
314
+ 'default => indices'
315
+ );
316
+
317
+ st.end();
318
+ });
319
+
320
+ t.test('stringifies an object inside an array with dots notation', function (st) {
321
+ st.equal(
322
+ qs.stringify(
323
+ { a: [{ b: 'c' }] },
324
+ { allowDots: true, encode: false, arrayFormat: 'indices' }
325
+ ),
326
+ 'a[0].b=c',
327
+ 'indices => indices'
328
+ );
329
+ st.equal(
330
+ qs.stringify(
331
+ { a: [{ b: 'c' }] },
332
+ { allowDots: true, encode: false, arrayFormat: 'brackets' }
333
+ ),
334
+ 'a[].b=c',
335
+ 'brackets => brackets'
336
+ );
337
+ st.equal(
338
+ qs.stringify(
339
+ { a: [{ b: 'c' }] },
340
+ { allowDots: true, encode: false }
341
+ ),
342
+ 'a[0].b=c',
343
+ 'default => indices'
344
+ );
345
+
346
+ st.equal(
347
+ qs.stringify(
348
+ { a: [{ b: { c: [1] } }] },
349
+ { allowDots: true, encode: false, arrayFormat: 'indices' }
350
+ ),
351
+ 'a[0].b.c[0]=1',
352
+ 'indices => indices'
353
+ );
354
+ st.equal(
355
+ qs.stringify(
356
+ { a: [{ b: { c: [1] } }] },
357
+ { allowDots: true, encode: false, arrayFormat: 'brackets' }
358
+ ),
359
+ 'a[].b.c[]=1',
360
+ 'brackets => brackets'
361
+ );
362
+ st.equal(
363
+ qs.stringify(
364
+ { a: [{ b: { c: [1] } }] },
365
+ { allowDots: true, encode: false }
366
+ ),
367
+ 'a[0].b.c[0]=1',
368
+ 'default => indices'
369
+ );
370
+
371
+ st.end();
372
+ });
373
+
374
+ t.test('does not omit object keys when indices = false', function (st) {
375
+ st.equal(qs.stringify({ a: [{ b: 'c' }] }, { indices: false }), 'a%5Bb%5D=c');
376
+ st.end();
377
+ });
378
+
379
+ t.test('uses indices notation for arrays when indices=true', function (st) {
380
+ st.equal(qs.stringify({ a: ['b', 'c'] }, { indices: true }), 'a%5B0%5D=b&a%5B1%5D=c');
381
+ st.end();
382
+ });
383
+
384
+ t.test('uses indices notation for arrays when no arrayFormat is specified', function (st) {
385
+ st.equal(qs.stringify({ a: ['b', 'c'] }), 'a%5B0%5D=b&a%5B1%5D=c');
386
+ st.end();
387
+ });
388
+
389
+ t.test('uses indices notation for arrays when no arrayFormat=indices', function (st) {
390
+ st.equal(qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'indices' }), 'a%5B0%5D=b&a%5B1%5D=c');
391
+ st.end();
392
+ });
393
+
394
+ t.test('uses repeat notation for arrays when no arrayFormat=repeat', function (st) {
395
+ st.equal(qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'repeat' }), 'a=b&a=c');
396
+ st.end();
397
+ });
398
+
399
+ t.test('uses brackets notation for arrays when no arrayFormat=brackets', function (st) {
400
+ st.equal(qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'brackets' }), 'a%5B%5D=b&a%5B%5D=c');
401
+ st.end();
402
+ });
403
+
404
+ t.test('stringifies a complicated object', function (st) {
405
+ st.equal(qs.stringify({ a: { b: 'c', d: 'e' } }), 'a%5Bb%5D=c&a%5Bd%5D=e');
406
+ st.end();
407
+ });
408
+
409
+ t.test('stringifies an empty value', function (st) {
410
+ st.equal(qs.stringify({ a: '' }), 'a=');
411
+ st.equal(qs.stringify({ a: null }, { strictNullHandling: true }), 'a');
412
+
413
+ st.equal(qs.stringify({ a: '', b: '' }), 'a=&b=');
414
+ st.equal(qs.stringify({ a: null, b: '' }, { strictNullHandling: true }), 'a&b=');
415
+
416
+ st.equal(qs.stringify({ a: { b: '' } }), 'a%5Bb%5D=');
417
+ st.equal(qs.stringify({ a: { b: null } }, { strictNullHandling: true }), 'a%5Bb%5D');
418
+ st.equal(qs.stringify({ a: { b: null } }, { strictNullHandling: false }), 'a%5Bb%5D=');
419
+
420
+ st.end();
421
+ });
422
+
423
+ t.test('stringifies an empty array in different arrayFormat', function (st) {
424
+ st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false }), 'b[0]=&c=c');
425
+ // arrayFormat default
426
+ st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'indices' }), 'b[0]=&c=c');
427
+ st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'brackets' }), 'b[]=&c=c');
428
+ st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'repeat' }), 'b=&c=c');
429
+ st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'comma' }), 'b=&c=c');
430
+ st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'comma', commaRoundTrip: true }), 'b[]=&c=c');
431
+ // with strictNullHandling
432
+ st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'indices', strictNullHandling: true }), 'b[0]&c=c');
433
+ st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'brackets', strictNullHandling: true }), 'b[]&c=c');
434
+ st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'repeat', strictNullHandling: true }), 'b&c=c');
435
+ st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'comma', strictNullHandling: true }), 'b&c=c');
436
+ st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'comma', strictNullHandling: true, commaRoundTrip: true }), 'b[]&c=c');
437
+ // with skipNulls
438
+ st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'indices', skipNulls: true }), 'c=c');
439
+ st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'brackets', skipNulls: true }), 'c=c');
440
+ st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'repeat', skipNulls: true }), 'c=c');
441
+ st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'comma', skipNulls: true }), 'c=c');
442
+
443
+ st.end();
444
+ });
445
+
446
+ t.test('stringifies a null object', { skip: !Object.create }, function (st) {
447
+ var obj = Object.create(null);
448
+ obj.a = 'b';
449
+ st.equal(qs.stringify(obj), 'a=b');
450
+ st.end();
451
+ });
452
+
453
+ t.test('returns an empty string for invalid input', function (st) {
454
+ st.equal(qs.stringify(undefined), '');
455
+ st.equal(qs.stringify(false), '');
456
+ st.equal(qs.stringify(null), '');
457
+ st.equal(qs.stringify(''), '');
458
+ st.end();
459
+ });
460
+
461
+ t.test('stringifies an object with a null object as a child', { skip: !Object.create }, function (st) {
462
+ var obj = { a: Object.create(null) };
463
+
464
+ obj.a.b = 'c';
465
+ st.equal(qs.stringify(obj), 'a%5Bb%5D=c');
466
+ st.end();
467
+ });
468
+
469
+ t.test('drops keys with a value of undefined', function (st) {
470
+ st.equal(qs.stringify({ a: undefined }), '');
471
+
472
+ st.equal(qs.stringify({ a: { b: undefined, c: null } }, { strictNullHandling: true }), 'a%5Bc%5D');
473
+ st.equal(qs.stringify({ a: { b: undefined, c: null } }, { strictNullHandling: false }), 'a%5Bc%5D=');
474
+ st.equal(qs.stringify({ a: { b: undefined, c: '' } }), 'a%5Bc%5D=');
475
+ st.end();
476
+ });
477
+
478
+ t.test('url encodes values', function (st) {
479
+ st.equal(qs.stringify({ a: 'b c' }), 'a=b%20c');
480
+ st.end();
481
+ });
482
+
483
+ t.test('stringifies a date', function (st) {
484
+ var now = new Date();
485
+ var str = 'a=' + encodeURIComponent(now.toISOString());
486
+ st.equal(qs.stringify({ a: now }), str);
487
+ st.end();
488
+ });
489
+
490
+ t.test('stringifies the weird object from qs', function (st) {
491
+ st.equal(qs.stringify({ 'my weird field': '~q1!2"\'w$5&7/z8)?' }), 'my%20weird%20field=~q1%212%22%27w%245%267%2Fz8%29%3F');
492
+ st.end();
493
+ });
494
+
495
+ t.test('skips properties that are part of the object prototype', function (st) {
496
+ Object.prototype.crash = 'test';
497
+ st.equal(qs.stringify({ a: 'b' }), 'a=b');
498
+ st.equal(qs.stringify({ a: { b: 'c' } }), 'a%5Bb%5D=c');
499
+ delete Object.prototype.crash;
500
+ st.end();
501
+ });
502
+
503
+ t.test('stringifies boolean values', function (st) {
504
+ st.equal(qs.stringify({ a: true }), 'a=true');
505
+ st.equal(qs.stringify({ a: { b: true } }), 'a%5Bb%5D=true');
506
+ st.equal(qs.stringify({ b: false }), 'b=false');
507
+ st.equal(qs.stringify({ b: { c: false } }), 'b%5Bc%5D=false');
508
+ st.end();
509
+ });
510
+
511
+ t.test('stringifies buffer values', function (st) {
512
+ st.equal(qs.stringify({ a: SaferBuffer.from('test') }), 'a=test');
513
+ st.equal(qs.stringify({ a: { b: SaferBuffer.from('test') } }), 'a%5Bb%5D=test');
514
+ st.end();
515
+ });
516
+
517
+ t.test('stringifies an object using an alternative delimiter', function (st) {
518
+ st.equal(qs.stringify({ a: 'b', c: 'd' }, { delimiter: ';' }), 'a=b;c=d');
519
+ st.end();
520
+ });
521
+
522
+ t.test('does not blow up when Buffer global is missing', function (st) {
523
+ var tempBuffer = global.Buffer;
524
+ delete global.Buffer;
525
+ var result = qs.stringify({ a: 'b', c: 'd' });
526
+ global.Buffer = tempBuffer;
527
+ st.equal(result, 'a=b&c=d');
528
+ st.end();
529
+ });
530
+
531
+ t.test('does not crash when parsing circular references', function (st) {
532
+ var a = {};
533
+ a.b = a;
534
+
535
+ st['throws'](
536
+ function () { qs.stringify({ 'foo[bar]': 'baz', 'foo[baz]': a }); },
537
+ /RangeError: Cyclic object value/,
538
+ 'cyclic values throw'
539
+ );
540
+
541
+ var circular = {
542
+ a: 'value'
543
+ };
544
+ circular.a = circular;
545
+ st['throws'](
546
+ function () { qs.stringify(circular); },
547
+ /RangeError: Cyclic object value/,
548
+ 'cyclic values throw'
549
+ );
550
+
551
+ var arr = ['a'];
552
+ st.doesNotThrow(
553
+ function () { qs.stringify({ x: arr, y: arr }); },
554
+ 'non-cyclic values do not throw'
555
+ );
556
+
557
+ st.end();
558
+ });
559
+
560
+ t.test('non-circular duplicated references can still work', function (st) {
561
+ var hourOfDay = {
562
+ 'function': 'hour_of_day'
563
+ };
564
+
565
+ var p1 = {
566
+ 'function': 'gte',
567
+ arguments: [hourOfDay, 0]
568
+ };
569
+ var p2 = {
570
+ 'function': 'lte',
571
+ arguments: [hourOfDay, 23]
572
+ };
573
+
574
+ st.equal(
575
+ qs.stringify({ filters: { $and: [p1, p2] } }, { encodeValuesOnly: true }),
576
+ 'filters[$and][0][function]=gte&filters[$and][0][arguments][0][function]=hour_of_day&filters[$and][0][arguments][1]=0&filters[$and][1][function]=lte&filters[$and][1][arguments][0][function]=hour_of_day&filters[$and][1][arguments][1]=23'
577
+ );
578
+
579
+ st.end();
580
+ });
581
+
582
+ t.test('selects properties when filter=array', function (st) {
583
+ st.equal(qs.stringify({ a: 'b' }, { filter: ['a'] }), 'a=b');
584
+ st.equal(qs.stringify({ a: 1 }, { filter: [] }), '');
585
+
586
+ st.equal(
587
+ qs.stringify(
588
+ { a: { b: [1, 2, 3, 4], c: 'd' }, c: 'f' },
589
+ { filter: ['a', 'b', 0, 2], arrayFormat: 'indices' }
590
+ ),
591
+ 'a%5Bb%5D%5B0%5D=1&a%5Bb%5D%5B2%5D=3',
592
+ 'indices => indices'
593
+ );
594
+ st.equal(
595
+ qs.stringify(
596
+ { a: { b: [1, 2, 3, 4], c: 'd' }, c: 'f' },
597
+ { filter: ['a', 'b', 0, 2], arrayFormat: 'brackets' }
598
+ ),
599
+ 'a%5Bb%5D%5B%5D=1&a%5Bb%5D%5B%5D=3',
600
+ 'brackets => brackets'
601
+ );
602
+ st.equal(
603
+ qs.stringify(
604
+ { a: { b: [1, 2, 3, 4], c: 'd' }, c: 'f' },
605
+ { filter: ['a', 'b', 0, 2] }
606
+ ),
607
+ 'a%5Bb%5D%5B0%5D=1&a%5Bb%5D%5B2%5D=3',
608
+ 'default => indices'
609
+ );
610
+
611
+ st.end();
612
+ });
613
+
614
+ t.test('supports custom representations when filter=function', function (st) {
615
+ var calls = 0;
616
+ var obj = { a: 'b', c: 'd', e: { f: new Date(1257894000000) } };
617
+ var filterFunc = function (prefix, value) {
618
+ calls += 1;
619
+ if (calls === 1) {
620
+ st.equal(prefix, '', 'prefix is empty');
621
+ st.equal(value, obj);
622
+ } else if (prefix === 'c') {
623
+ return void 0;
624
+ } else if (value instanceof Date) {
625
+ st.equal(prefix, 'e[f]');
626
+ return value.getTime();
627
+ }
628
+ return value;
629
+ };
630
+
631
+ st.equal(qs.stringify(obj, { filter: filterFunc }), 'a=b&e%5Bf%5D=1257894000000');
632
+ st.equal(calls, 5);
633
+ st.end();
634
+ });
635
+
636
+ t.test('can disable uri encoding', function (st) {
637
+ st.equal(qs.stringify({ a: 'b' }, { encode: false }), 'a=b');
638
+ st.equal(qs.stringify({ a: { b: 'c' } }, { encode: false }), 'a[b]=c');
639
+ st.equal(qs.stringify({ a: 'b', c: null }, { strictNullHandling: true, encode: false }), 'a=b&c');
640
+ st.end();
641
+ });
642
+
643
+ t.test('can sort the keys', function (st) {
644
+ var sort = function (a, b) {
645
+ return a.localeCompare(b);
646
+ };
647
+ st.equal(qs.stringify({ a: 'c', z: 'y', b: 'f' }, { sort: sort }), 'a=c&b=f&z=y');
648
+ st.equal(qs.stringify({ a: 'c', z: { j: 'a', i: 'b' }, b: 'f' }, { sort: sort }), 'a=c&b=f&z%5Bi%5D=b&z%5Bj%5D=a');
649
+ st.end();
650
+ });
651
+
652
+ t.test('can sort the keys at depth 3 or more too', function (st) {
653
+ var sort = function (a, b) {
654
+ return a.localeCompare(b);
655
+ };
656
+ st.equal(
657
+ qs.stringify(
658
+ { a: 'a', z: { zj: { zjb: 'zjb', zja: 'zja' }, zi: { zib: 'zib', zia: 'zia' } }, b: 'b' },
659
+ { sort: sort, encode: false }
660
+ ),
661
+ 'a=a&b=b&z[zi][zia]=zia&z[zi][zib]=zib&z[zj][zja]=zja&z[zj][zjb]=zjb'
662
+ );
663
+ st.equal(
664
+ qs.stringify(
665
+ { a: 'a', z: { zj: { zjb: 'zjb', zja: 'zja' }, zi: { zib: 'zib', zia: 'zia' } }, b: 'b' },
666
+ { sort: null, encode: false }
667
+ ),
668
+ 'a=a&z[zj][zjb]=zjb&z[zj][zja]=zja&z[zi][zib]=zib&z[zi][zia]=zia&b=b'
669
+ );
670
+ st.end();
671
+ });
672
+
673
+ t.test('can stringify with custom encoding', function (st) {
674
+ st.equal(qs.stringify({ 県: '大阪府', '': '' }, {
675
+ encoder: function (str) {
676
+ if (str.length === 0) {
677
+ return '';
678
+ }
679
+ var buf = iconv.encode(str, 'shiftjis');
680
+ var result = [];
681
+ for (var i = 0; i < buf.length; ++i) {
682
+ result.push(buf.readUInt8(i).toString(16));
683
+ }
684
+ return '%' + result.join('%');
685
+ }
686
+ }), '%8c%a7=%91%e5%8d%e3%95%7b&=');
687
+ st.end();
688
+ });
689
+
690
+ t.test('receives the default encoder as a second argument', function (st) {
691
+ st.plan(2);
692
+ qs.stringify({ a: 1 }, {
693
+ encoder: function (str, defaultEncoder) {
694
+ st.equal(defaultEncoder, utils.encode);
695
+ }
696
+ });
697
+ st.end();
698
+ });
699
+
700
+ t.test('throws error with wrong encoder', function (st) {
701
+ st['throws'](function () {
702
+ qs.stringify({}, { encoder: 'string' });
703
+ }, new TypeError('Encoder has to be a function.'));
704
+ st.end();
705
+ });
706
+
707
+ t.test('can use custom encoder for a buffer object', { skip: typeof Buffer === 'undefined' }, function (st) {
708
+ st.equal(qs.stringify({ a: SaferBuffer.from([1]) }, {
709
+ encoder: function (buffer) {
710
+ if (typeof buffer === 'string') {
711
+ return buffer;
712
+ }
713
+ return String.fromCharCode(buffer.readUInt8(0) + 97);
714
+ }
715
+ }), 'a=b');
716
+
717
+ st.equal(qs.stringify({ a: SaferBuffer.from('a b') }, {
718
+ encoder: function (buffer) {
719
+ return buffer;
720
+ }
721
+ }), 'a=a b');
722
+ st.end();
723
+ });
724
+
725
+ t.test('serializeDate option', function (st) {
726
+ var date = new Date();
727
+ st.equal(
728
+ qs.stringify({ a: date }),
729
+ 'a=' + date.toISOString().replace(/:/g, '%3A'),
730
+ 'default is toISOString'
731
+ );
732
+
733
+ var mutatedDate = new Date();
734
+ mutatedDate.toISOString = function () {
735
+ throw new SyntaxError();
736
+ };
737
+ st['throws'](function () {
738
+ mutatedDate.toISOString();
739
+ }, SyntaxError);
740
+ st.equal(
741
+ qs.stringify({ a: mutatedDate }),
742
+ 'a=' + Date.prototype.toISOString.call(mutatedDate).replace(/:/g, '%3A'),
743
+ 'toISOString works even when method is not locally present'
744
+ );
745
+
746
+ var specificDate = new Date(6);
747
+ st.equal(
748
+ qs.stringify(
749
+ { a: specificDate },
750
+ { serializeDate: function (d) { return d.getTime() * 7; } }
751
+ ),
752
+ 'a=42',
753
+ 'custom serializeDate function called'
754
+ );
755
+
756
+ st.equal(
757
+ qs.stringify(
758
+ { a: [date] },
759
+ {
760
+ serializeDate: function (d) { return d.getTime(); },
761
+ arrayFormat: 'comma'
762
+ }
763
+ ),
764
+ 'a=' + date.getTime(),
765
+ 'works with arrayFormat comma'
766
+ );
767
+ st.equal(
768
+ qs.stringify(
769
+ { a: [date] },
770
+ {
771
+ serializeDate: function (d) { return d.getTime(); },
772
+ arrayFormat: 'comma',
773
+ commaRoundTrip: true
774
+ }
775
+ ),
776
+ 'a%5B%5D=' + date.getTime(),
777
+ 'works with arrayFormat comma'
778
+ );
779
+
780
+ st.end();
781
+ });
782
+
783
+ t.test('RFC 1738 serialization', function (st) {
784
+ st.equal(qs.stringify({ a: 'b c' }, { format: qs.formats.RFC1738 }), 'a=b+c');
785
+ st.equal(qs.stringify({ 'a b': 'c d' }, { format: qs.formats.RFC1738 }), 'a+b=c+d');
786
+ st.equal(qs.stringify({ 'a b': SaferBuffer.from('a b') }, { format: qs.formats.RFC1738 }), 'a+b=a+b');
787
+
788
+ st.equal(qs.stringify({ 'foo(ref)': 'bar' }, { format: qs.formats.RFC1738 }), 'foo(ref)=bar');
789
+
790
+ st.end();
791
+ });
792
+
793
+ t.test('RFC 3986 spaces serialization', function (st) {
794
+ st.equal(qs.stringify({ a: 'b c' }, { format: qs.formats.RFC3986 }), 'a=b%20c');
795
+ st.equal(qs.stringify({ 'a b': 'c d' }, { format: qs.formats.RFC3986 }), 'a%20b=c%20d');
796
+ st.equal(qs.stringify({ 'a b': SaferBuffer.from('a b') }, { format: qs.formats.RFC3986 }), 'a%20b=a%20b');
797
+
798
+ st.end();
799
+ });
800
+
801
+ t.test('Backward compatibility to RFC 3986', function (st) {
802
+ st.equal(qs.stringify({ a: 'b c' }), 'a=b%20c');
803
+ st.equal(qs.stringify({ 'a b': SaferBuffer.from('a b') }), 'a%20b=a%20b');
804
+
805
+ st.end();
806
+ });
807
+
808
+ t.test('Edge cases and unknown formats', function (st) {
809
+ ['UFO1234', false, 1234, null, {}, []].forEach(function (format) {
810
+ st['throws'](
811
+ function () {
812
+ qs.stringify({ a: 'b c' }, { format: format });
813
+ },
814
+ new TypeError('Unknown format option provided.')
815
+ );
816
+ });
817
+ st.end();
818
+ });
819
+
820
+ t.test('encodeValuesOnly', function (st) {
821
+ st.equal(
822
+ qs.stringify(
823
+ { a: 'b', c: ['d', 'e=f'], f: [['g'], ['h']] },
824
+ { encodeValuesOnly: true }
825
+ ),
826
+ 'a=b&c[0]=d&c[1]=e%3Df&f[0][0]=g&f[1][0]=h'
827
+ );
828
+ st.equal(
829
+ qs.stringify(
830
+ { a: 'b', c: ['d', 'e'], f: [['g'], ['h']] }
831
+ ),
832
+ 'a=b&c%5B0%5D=d&c%5B1%5D=e&f%5B0%5D%5B0%5D=g&f%5B1%5D%5B0%5D=h'
833
+ );
834
+ st.end();
835
+ });
836
+
837
+ t.test('encodeValuesOnly - strictNullHandling', function (st) {
838
+ st.equal(
839
+ qs.stringify(
840
+ { a: { b: null } },
841
+ { encodeValuesOnly: true, strictNullHandling: true }
842
+ ),
843
+ 'a[b]'
844
+ );
845
+ st.end();
846
+ });
847
+
848
+ t.test('throws if an invalid charset is specified', function (st) {
849
+ st['throws'](function () {
850
+ qs.stringify({ a: 'b' }, { charset: 'foobar' });
851
+ }, new TypeError('The charset option must be either utf-8, iso-8859-1, or undefined'));
852
+ st.end();
853
+ });
854
+
855
+ t.test('respects a charset of iso-8859-1', function (st) {
856
+ st.equal(qs.stringify({ æ: 'æ' }, { charset: 'iso-8859-1' }), '%E6=%E6');
857
+ st.end();
858
+ });
859
+
860
+ t.test('encodes unrepresentable chars as numeric entities in iso-8859-1 mode', function (st) {
861
+ st.equal(qs.stringify({ a: '☺' }, { charset: 'iso-8859-1' }), 'a=%26%239786%3B');
862
+ st.end();
863
+ });
864
+
865
+ t.test('respects an explicit charset of utf-8 (the default)', function (st) {
866
+ st.equal(qs.stringify({ a: 'æ' }, { charset: 'utf-8' }), 'a=%C3%A6');
867
+ st.end();
868
+ });
869
+
870
+ t.test('adds the right sentinel when instructed to and the charset is utf-8', function (st) {
871
+ st.equal(qs.stringify({ a: 'æ' }, { charsetSentinel: true, charset: 'utf-8' }), 'utf8=%E2%9C%93&a=%C3%A6');
872
+ st.end();
873
+ });
874
+
875
+ t.test('adds the right sentinel when instructed to and the charset is iso-8859-1', function (st) {
876
+ st.equal(qs.stringify({ a: 'æ' }, { charsetSentinel: true, charset: 'iso-8859-1' }), 'utf8=%26%2310003%3B&a=%E6');
877
+ st.end();
878
+ });
879
+
880
+ t.test('does not mutate the options argument', function (st) {
881
+ var options = {};
882
+ qs.stringify({}, options);
883
+ st.deepEqual(options, {});
884
+ st.end();
885
+ });
886
+
887
+ t.test('strictNullHandling works with custom filter', function (st) {
888
+ var filter = function (prefix, value) {
889
+ return value;
890
+ };
891
+
892
+ var options = { strictNullHandling: true, filter: filter };
893
+ st.equal(qs.stringify({ key: null }, options), 'key');
894
+ st.end();
895
+ });
896
+
897
+ t.test('strictNullHandling works with null serializeDate', function (st) {
898
+ var serializeDate = function () {
899
+ return null;
900
+ };
901
+ var options = { strictNullHandling: true, serializeDate: serializeDate };
902
+ var date = new Date();
903
+ st.equal(qs.stringify({ key: date }, options), 'key');
904
+ st.end();
905
+ });
906
+
907
+ t.test('allows for encoding keys and values differently', function (st) {
908
+ var encoder = function (str, defaultEncoder, charset, type) {
909
+ if (type === 'key') {
910
+ return defaultEncoder(str, defaultEncoder, charset, type).toLowerCase();
911
+ }
912
+ if (type === 'value') {
913
+ return defaultEncoder(str, defaultEncoder, charset, type).toUpperCase();
914
+ }
915
+ throw 'this should never happen! type: ' + type;
916
+ };
917
+
918
+ st.deepEqual(qs.stringify({ KeY: 'vAlUe' }, { encoder: encoder }), 'key=VALUE');
919
+ st.end();
920
+ });
921
+
922
+ t.test('objects inside arrays', function (st) {
923
+ var obj = { a: { b: { c: 'd', e: 'f' } } };
924
+ var withArray = { a: { b: [{ c: 'd', e: 'f' }] } };
925
+
926
+ st.equal(qs.stringify(obj, { encode: false }), 'a[b][c]=d&a[b][e]=f', 'no array, no arrayFormat');
927
+ st.equal(qs.stringify(obj, { encode: false, arrayFormat: 'bracket' }), 'a[b][c]=d&a[b][e]=f', 'no array, bracket');
928
+ st.equal(qs.stringify(obj, { encode: false, arrayFormat: 'indices' }), 'a[b][c]=d&a[b][e]=f', 'no array, indices');
929
+ st.equal(qs.stringify(obj, { encode: false, arrayFormat: 'comma' }), 'a[b][c]=d&a[b][e]=f', 'no array, comma');
930
+
931
+ st.equal(qs.stringify(withArray, { encode: false }), 'a[b][0][c]=d&a[b][0][e]=f', 'array, no arrayFormat');
932
+ st.equal(qs.stringify(withArray, { encode: false, arrayFormat: 'bracket' }), 'a[b][0][c]=d&a[b][0][e]=f', 'array, bracket');
933
+ st.equal(qs.stringify(withArray, { encode: false, arrayFormat: 'indices' }), 'a[b][0][c]=d&a[b][0][e]=f', 'array, indices');
934
+ st.equal(
935
+ qs.stringify(withArray, { encode: false, arrayFormat: 'comma' }),
936
+ '???',
937
+ 'array, comma',
938
+ { skip: 'TODO: figure out what this should do' }
939
+ );
940
+
941
+ st.end();
942
+ });
943
+
944
+ t.test('stringifies sparse arrays', function (st) {
945
+ /* eslint no-sparse-arrays: 0 */
946
+ st.equal(qs.stringify({ a: [, '2', , , '1'] }, { encodeValuesOnly: true }), 'a[1]=2&a[4]=1');
947
+ st.equal(qs.stringify({ a: [, { b: [, , { c: '1' }] }] }, { encodeValuesOnly: true }), 'a[1][b][2][c]=1');
948
+ st.equal(qs.stringify({ a: [, [, , [, , , { c: '1' }]]] }, { encodeValuesOnly: true }), 'a[1][2][3][c]=1');
949
+ st.equal(qs.stringify({ a: [, [, , [, , , { c: [, '1'] }]]] }, { encodeValuesOnly: true }), 'a[1][2][3][c][1]=1');
950
+
951
+ st.end();
952
+ });
953
+
954
+ t.end();
955
+ });
956
+
957
+ test('stringifies empty keys', function (t) {
958
+ emptyTestCases.forEach(function (testCase) {
959
+ t.test('stringifies an object with empty string key with ' + testCase.input, function (st) {
960
+ st.deepEqual(qs.stringify(testCase.withEmptyKeys, { encode: false }), testCase.stringifyOutput);
961
+
962
+ st.end();
963
+ });
964
+ });
965
+
966
+ t.test('edge case with object/arrays', function (st) {
967
+ st.deepEqual(qs.stringify({ '': { '': [2, 3] } }, { encode: false }), '[][0]=2&[][1]=3');
968
+ st.deepEqual(qs.stringify({ '': { '': [2, 3], a: 2 } }, { encode: false }), '[][0]=2&[][1]=3&[a]=2');
969
+
970
+ st.end();
971
+ });
972
+ });