qs 0.3.1 → 0.4.2
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/.travis.yml +4 -0
- package/History.md +21 -0
- package/Makefile +1 -3
- package/Readme.md +11 -6
- package/examples.js +3 -0
- package/lib/querystring.js +104 -76
- package/package.json +2 -2
- package/test/mocha.opts +2 -0
- package/test/{parse.test.js → parse.js} +14 -3
- package/test/stringify.js +103 -0
- package/test/stringify.test.js +0 -95
package/.travis.yml
ADDED
package/History.md
CHANGED
|
@@ -1,4 +1,25 @@
|
|
|
1
1
|
|
|
2
|
+
0.4.2 / 2012-02-08
|
|
3
|
+
==================
|
|
4
|
+
|
|
5
|
+
* Fixed: ensure objects are created when appropriate not arrays [aheckmann]
|
|
6
|
+
|
|
7
|
+
0.4.1 / 2012-01-26
|
|
8
|
+
==================
|
|
9
|
+
|
|
10
|
+
* Fixed stringify()ing numbers. Closes #23
|
|
11
|
+
|
|
12
|
+
0.4.0 / 2011-11-21
|
|
13
|
+
==================
|
|
14
|
+
|
|
15
|
+
* Allow parsing of an existing object (for `bodyParser()`) [jackyz]
|
|
16
|
+
* Replaced expresso with mocha
|
|
17
|
+
|
|
18
|
+
0.3.2 / 2011-11-08
|
|
19
|
+
==================
|
|
20
|
+
|
|
21
|
+
* Fixed global variable leak
|
|
22
|
+
|
|
2
23
|
0.3.1 / 2011-08-17
|
|
3
24
|
==================
|
|
4
25
|
|
package/Makefile
CHANGED
package/Readme.md
CHANGED
|
@@ -6,18 +6,23 @@
|
|
|
6
6
|
|
|
7
7
|
$ npm install qs
|
|
8
8
|
|
|
9
|
-
|
|
10
9
|
## Examples
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
```js
|
|
12
|
+
var qs = require('qs');
|
|
13
|
+
|
|
14
|
+
qs.parse('user[name][first]=Tobi&user[email]=tobi@learnboost.com');
|
|
15
|
+
// => { user: { name: { first: 'Tobi' }, email: 'tobi@learnboost.com' } }
|
|
16
|
+
|
|
17
|
+
qs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }})
|
|
18
|
+
// => user[name]=Tobi&user[email]=tobi%40learnboost.com
|
|
19
|
+
```
|
|
14
20
|
|
|
15
21
|
## Testing
|
|
16
22
|
|
|
17
|
-
|
|
23
|
+
Install dev dependencies:
|
|
18
24
|
|
|
19
|
-
$
|
|
20
|
-
$ git submodule update
|
|
25
|
+
$ npm install -d
|
|
21
26
|
|
|
22
27
|
and execute:
|
|
23
28
|
|
package/examples.js
CHANGED
package/lib/querystring.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
|
|
1
2
|
/*!
|
|
2
3
|
* querystring
|
|
3
4
|
* Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
|
|
@@ -8,7 +9,7 @@
|
|
|
8
9
|
* Library version.
|
|
9
10
|
*/
|
|
10
11
|
|
|
11
|
-
exports.version = '0.
|
|
12
|
+
exports.version = '0.4.2';
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Object#toString() ref for stringify().
|
|
@@ -20,31 +21,97 @@ var toString = Object.prototype.toString;
|
|
|
20
21
|
* Cache non-integer test regexp.
|
|
21
22
|
*/
|
|
22
23
|
|
|
23
|
-
var
|
|
24
|
+
var isint = /^[0-9]+$/;
|
|
25
|
+
|
|
26
|
+
function promote(parent, key) {
|
|
27
|
+
if (parent[key].length == 0) return parent[key] = {};
|
|
28
|
+
var t = {};
|
|
29
|
+
for (var i in parent[key]) t[i] = parent[key][i];
|
|
30
|
+
parent[key] = t;
|
|
31
|
+
return t;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function parse(parts, parent, key, val) {
|
|
35
|
+
var part = parts.shift();
|
|
36
|
+
// end
|
|
37
|
+
if (!part) {
|
|
38
|
+
if (Array.isArray(parent[key])) {
|
|
39
|
+
parent[key].push(val);
|
|
40
|
+
} else if ('object' == typeof parent[key]) {
|
|
41
|
+
parent[key] = val;
|
|
42
|
+
} else if ('undefined' == typeof parent[key]) {
|
|
43
|
+
parent[key] = val;
|
|
44
|
+
} else {
|
|
45
|
+
parent[key] = [parent[key], val];
|
|
46
|
+
}
|
|
47
|
+
// array
|
|
48
|
+
} else {
|
|
49
|
+
var obj = parent[key] = parent[key] || [];
|
|
50
|
+
if (']' == part) {
|
|
51
|
+
if (Array.isArray(obj)) {
|
|
52
|
+
if ('' != val) obj.push(val);
|
|
53
|
+
} else if ('object' == typeof obj) {
|
|
54
|
+
obj[Object.keys(obj).length] = val;
|
|
55
|
+
} else {
|
|
56
|
+
obj = parent[key] = [parent[key], val];
|
|
57
|
+
}
|
|
58
|
+
// prop
|
|
59
|
+
} else if (~part.indexOf(']')) {
|
|
60
|
+
part = part.substr(0, part.length - 1);
|
|
61
|
+
if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key);
|
|
62
|
+
parse(parts, obj, part, val);
|
|
63
|
+
// key
|
|
64
|
+
} else {
|
|
65
|
+
if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key);
|
|
66
|
+
parse(parts, obj, part, val);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
24
70
|
|
|
25
71
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* @param {String} str
|
|
29
|
-
* @return {Object}
|
|
30
|
-
* @api public
|
|
72
|
+
* Merge parent key/val pair.
|
|
31
73
|
*/
|
|
32
74
|
|
|
33
|
-
|
|
34
|
-
if (
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
75
|
+
function merge(parent, key, val){
|
|
76
|
+
if (~key.indexOf(']')) {
|
|
77
|
+
var parts = key.split('[')
|
|
78
|
+
, len = parts.length
|
|
79
|
+
, last = len - 1;
|
|
80
|
+
parse(parts, parent, 'base', val);
|
|
81
|
+
// optimize
|
|
82
|
+
} else {
|
|
83
|
+
if (!isint.test(key) && Array.isArray(parent.base)) {
|
|
84
|
+
var t = {};
|
|
85
|
+
for (var k in parent.base) t[k] = parent.base[k];
|
|
86
|
+
parent.base = t;
|
|
87
|
+
}
|
|
88
|
+
set(parent.base, key, val);
|
|
42
89
|
}
|
|
43
90
|
|
|
91
|
+
return parent;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Parse the given obj.
|
|
96
|
+
*/
|
|
97
|
+
|
|
98
|
+
function parseObject(obj){
|
|
99
|
+
var ret = { base: {} };
|
|
100
|
+
Object.keys(obj).forEach(function(name){
|
|
101
|
+
merge(ret, name, obj[name]);
|
|
102
|
+
});
|
|
103
|
+
return ret.base;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Parse the given str.
|
|
108
|
+
*/
|
|
109
|
+
|
|
110
|
+
function parseString(str){
|
|
44
111
|
return String(str)
|
|
45
112
|
.split('&')
|
|
46
113
|
.reduce(function(ret, pair){
|
|
47
|
-
try{
|
|
114
|
+
try{
|
|
48
115
|
pair = decodeURIComponent(pair.replace(/\+/g, ' '));
|
|
49
116
|
} catch(e) {
|
|
50
117
|
// ignore
|
|
@@ -54,69 +121,28 @@ exports.parse = function(str){
|
|
|
54
121
|
, brace = lastBraceInKey(pair)
|
|
55
122
|
, key = pair.substr(0, brace || eql)
|
|
56
123
|
, val = pair.substr(brace || eql, pair.length)
|
|
57
|
-
, val = val.substr(val.indexOf('=') + 1, val.length)
|
|
58
|
-
, parent = ret;
|
|
124
|
+
, val = val.substr(val.indexOf('=') + 1, val.length);
|
|
59
125
|
|
|
60
126
|
// ?foo
|
|
61
127
|
if ('' == key) key = pair, val = '';
|
|
62
128
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
, len = parts.length
|
|
67
|
-
, last = len - 1;
|
|
68
|
-
|
|
69
|
-
function parse(parts, parent, key) {
|
|
70
|
-
var part = parts.shift();
|
|
71
|
-
|
|
72
|
-
// end
|
|
73
|
-
if (!part) {
|
|
74
|
-
if (Array.isArray(parent[key])) {
|
|
75
|
-
parent[key].push(val);
|
|
76
|
-
} else if ('object' == typeof parent[key]) {
|
|
77
|
-
parent[key] = val;
|
|
78
|
-
} else if ('undefined' == typeof parent[key]) {
|
|
79
|
-
parent[key] = val;
|
|
80
|
-
} else {
|
|
81
|
-
parent[key] = [parent[key], val];
|
|
82
|
-
}
|
|
83
|
-
// array
|
|
84
|
-
} else {
|
|
85
|
-
obj = parent[key] = parent[key] || [];
|
|
86
|
-
if (']' == part) {
|
|
87
|
-
if (Array.isArray(obj)) {
|
|
88
|
-
if ('' != val) obj.push(val);
|
|
89
|
-
} else if ('object' == typeof obj) {
|
|
90
|
-
obj[Object.keys(obj).length] = val;
|
|
91
|
-
} else {
|
|
92
|
-
obj = parent[key] = [parent[key], val];
|
|
93
|
-
}
|
|
94
|
-
// prop
|
|
95
|
-
} else if (~part.indexOf(']')) {
|
|
96
|
-
part = part.substr(0, part.length - 1);
|
|
97
|
-
if(notint.test(part) && Array.isArray(obj)) obj = promote(parent, key);
|
|
98
|
-
parse(parts, obj, part);
|
|
99
|
-
// key
|
|
100
|
-
} else {
|
|
101
|
-
if(notint.test(part) && Array.isArray(obj)) obj = promote(parent, key);
|
|
102
|
-
parse(parts, obj, part);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
parse(parts, parent, 'base');
|
|
108
|
-
// optimize
|
|
109
|
-
} else {
|
|
110
|
-
if (notint.test(key) && Array.isArray(parent.base)) {
|
|
111
|
-
var t = {};
|
|
112
|
-
for(var k in parent.base) t[k] = parent.base[k];
|
|
113
|
-
parent.base = t;
|
|
114
|
-
}
|
|
115
|
-
set(parent.base, key, val);
|
|
116
|
-
}
|
|
129
|
+
return merge(ret, key, val);
|
|
130
|
+
}, { base: {} }).base;
|
|
131
|
+
}
|
|
117
132
|
|
|
118
|
-
|
|
119
|
-
|
|
133
|
+
/**
|
|
134
|
+
* Parse the given query `str` or `obj`, returning an object.
|
|
135
|
+
*
|
|
136
|
+
* @param {String} str | {Object} obj
|
|
137
|
+
* @return {Object}
|
|
138
|
+
* @api public
|
|
139
|
+
*/
|
|
140
|
+
|
|
141
|
+
exports.parse = function(str){
|
|
142
|
+
if (null == str || '' == str) return {};
|
|
143
|
+
return 'object' == typeof str
|
|
144
|
+
? parseObject(str)
|
|
145
|
+
: parseString(str);
|
|
120
146
|
};
|
|
121
147
|
|
|
122
148
|
/**
|
|
@@ -135,7 +161,7 @@ var stringify = exports.stringify = function(obj, prefix) {
|
|
|
135
161
|
} else if ('string' == typeof obj) {
|
|
136
162
|
return stringifyString(obj, prefix);
|
|
137
163
|
} else {
|
|
138
|
-
return prefix;
|
|
164
|
+
return prefix + '=' + obj;
|
|
139
165
|
}
|
|
140
166
|
};
|
|
141
167
|
|
|
@@ -184,12 +210,14 @@ function stringifyObject(obj, prefix) {
|
|
|
184
210
|
var ret = []
|
|
185
211
|
, keys = Object.keys(obj)
|
|
186
212
|
, key;
|
|
213
|
+
|
|
187
214
|
for (var i = 0, len = keys.length; i < len; ++i) {
|
|
188
215
|
key = keys[i];
|
|
189
216
|
ret.push(stringify(obj[key], prefix
|
|
190
217
|
? prefix + '[' + encodeURIComponent(key) + ']'
|
|
191
218
|
: encodeURIComponent(key)));
|
|
192
219
|
}
|
|
220
|
+
|
|
193
221
|
return ret.join('&');
|
|
194
222
|
}
|
|
195
223
|
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "qs",
|
|
3
3
|
"description": "querystring parser",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.4.2",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type" : "git",
|
|
7
7
|
"url" : "git://github.com/visionmedia/node-querystring.git"
|
|
8
8
|
},
|
|
9
9
|
"devDependencies": {
|
|
10
|
-
"
|
|
10
|
+
"mocha": "*"
|
|
11
11
|
, "should": "*"
|
|
12
12
|
},
|
|
13
13
|
"author": "TJ Holowaychuk <tj@vision-media.ca> (http://tjholowaychuk.com)",
|
package/test/mocha.opts
ADDED
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
* Module dependencies.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
var qs = require('../')
|
|
7
|
-
, should = require('should');
|
|
6
|
+
var qs = require('../');
|
|
8
7
|
|
|
9
8
|
module.exports = {
|
|
10
9
|
'test basics': function(){
|
|
@@ -92,8 +91,12 @@ module.exports = {
|
|
|
92
91
|
|
|
93
92
|
qs.parse('user[name][first]=tj&user[name][first]=TJ')
|
|
94
93
|
.should.eql({ user: { name: { first: ['tj', 'TJ'] }}});
|
|
94
|
+
|
|
95
|
+
var o = qs.parse('existing[fcbaebfecc][name][last]=tj')
|
|
96
|
+
o.should.eql({ existing: { 'fcbaebfecc': { name: { last: 'tj' }}}})
|
|
97
|
+
Array.isArray(o.existing).should.be.false;
|
|
95
98
|
},
|
|
96
|
-
|
|
99
|
+
|
|
97
100
|
'test right-hand brackets': function(){
|
|
98
101
|
qs.parse('pets=["tobi"]')
|
|
99
102
|
.should.eql({ pets: '["tobi"]' });
|
|
@@ -140,6 +143,14 @@ module.exports = {
|
|
|
140
143
|
'test malformed uri': function(){
|
|
141
144
|
qs.parse('{%:%}').should.eql({ '{%:%}': '' });
|
|
142
145
|
qs.parse('foo=%:%}').should.eql({ 'foo': '%:%}' });
|
|
146
|
+
},
|
|
147
|
+
|
|
148
|
+
'test semi-parsed': function(){
|
|
149
|
+
qs.parse({ 'user[name]': 'tobi' })
|
|
150
|
+
.should.eql({ user: { name: 'tobi' }});
|
|
151
|
+
|
|
152
|
+
qs.parse({ 'user[name]': 'tobi', 'user[email][main]': 'tobi@lb.com' })
|
|
153
|
+
.should.eql({ user: { name: 'tobi', email: { main: 'tobi@lb.com' } }});
|
|
143
154
|
}
|
|
144
155
|
|
|
145
156
|
// 'test complex': function(){
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* Module dependencies.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
var qs = require('../')
|
|
7
|
+
, should = require('should')
|
|
8
|
+
, str_identities = {
|
|
9
|
+
'basics': [
|
|
10
|
+
{ str: 'foo=bar', obj: {'foo' : 'bar'}},
|
|
11
|
+
{ str: 'foo=%22bar%22', obj: {'foo' : '\"bar\"'}},
|
|
12
|
+
{ str: 'foo=', obj: {'foo': ''}},
|
|
13
|
+
{ str: 'foo=1&bar=2', obj: {'foo' : '1', 'bar' : '2'}},
|
|
14
|
+
{ str: 'my%20weird%20field=q1!2%22\'w%245%267%2Fz8)%3F', obj: {'my weird field': "q1!2\"'w$5&7/z8)?"}},
|
|
15
|
+
{ str: 'foo%3Dbaz=bar', obj: {'foo=baz': 'bar'}},
|
|
16
|
+
{ str: 'foo=bar&bar=baz', obj: {foo: 'bar', bar: 'baz'}}
|
|
17
|
+
],
|
|
18
|
+
'escaping': [
|
|
19
|
+
{ str: 'foo=foo%20bar', obj: {foo: 'foo bar'}},
|
|
20
|
+
{ str: 'cht=p3&chd=t%3A60%2C40&chs=250x100&chl=Hello%7CWorld', obj: {
|
|
21
|
+
cht: 'p3'
|
|
22
|
+
, chd: 't:60,40'
|
|
23
|
+
, chs: '250x100'
|
|
24
|
+
, chl: 'Hello|World'
|
|
25
|
+
}}
|
|
26
|
+
],
|
|
27
|
+
'nested': [
|
|
28
|
+
{ str: 'foo[]=bar&foo[]=quux', obj: {'foo' : ['bar', 'quux']}},
|
|
29
|
+
{ str: 'foo[]=bar', obj: {foo: ['bar']}},
|
|
30
|
+
{ str: 'foo[]=1&foo[]=2', obj: {'foo' : ['1', '2']}},
|
|
31
|
+
{ str: 'foo=bar&baz[]=1&baz[]=2&baz[]=3', obj: {'foo' : 'bar', 'baz' : ['1', '2', '3']}},
|
|
32
|
+
{ str: 'foo[]=bar&baz[]=1&baz[]=2&baz[]=3', obj: {'foo' : ['bar'], 'baz' : ['1', '2', '3']}},
|
|
33
|
+
{ str: 'x[y][z]=1', obj: {'x' : {'y' : {'z' : '1'}}}},
|
|
34
|
+
{ str: 'x[y][z][]=1', obj: {'x' : {'y' : {'z' : ['1']}}}},
|
|
35
|
+
{ str: 'x[y][z]=2', obj: {'x' : {'y' : {'z' : '2'}}}},
|
|
36
|
+
{ str: 'x[y][z][]=1&x[y][z][]=2', obj: {'x' : {'y' : {'z' : ['1', '2']}}}},
|
|
37
|
+
{ str: 'x[y][][z]=1', obj: {'x' : {'y' : [{'z' : '1'}]}}},
|
|
38
|
+
{ str: 'x[y][][z][]=1', obj: {'x' : {'y' : [{'z' : ['1']}]}}},
|
|
39
|
+
{ str: 'x[y][][z]=1&x[y][][w]=2', obj: {'x' : {'y' : [{'z' : '1', 'w' : '2'}]}}},
|
|
40
|
+
{ str: 'x[y][][v][w]=1', obj: {'x' : {'y' : [{'v' : {'w' : '1'}}]}}},
|
|
41
|
+
{ str: 'x[y][][z]=1&x[y][][v][w]=2', obj: {'x' : {'y' : [{'z' : '1', 'v' : {'w' : '2'}}]}}},
|
|
42
|
+
{ str: 'x[y][][z]=1&x[y][][z]=2', obj: {'x' : {'y' : [{'z' : '1'}, {'z' : '2'}]}}},
|
|
43
|
+
{ str: 'x[y][][z]=1&x[y][][w]=a&x[y][][z]=2&x[y][][w]=3', obj: {'x' : {'y' : [{'z' : '1', 'w' : 'a'}, {'z' : '2', 'w' : '3'}]}}},
|
|
44
|
+
{ str: 'user[name][first]=tj&user[name][last]=holowaychuk', obj: { user: { name: { first: 'tj', last: 'holowaychuk' }}}}
|
|
45
|
+
],
|
|
46
|
+
'errors': [
|
|
47
|
+
{ obj: 'foo=bar', message: 'stringify expects an object' },
|
|
48
|
+
{ obj: ['foo', 'bar'], message: 'stringify expects an object' }
|
|
49
|
+
],
|
|
50
|
+
'numbers': [
|
|
51
|
+
{ str: 'limit[]=1&limit[]=2&limit[]=3', obj: { limit: [1, 2, '3'] }},
|
|
52
|
+
{ str: 'limit=1', obj: { limit: 1 }}
|
|
53
|
+
]
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
// Assert error
|
|
58
|
+
function err(fn, msg){
|
|
59
|
+
var err;
|
|
60
|
+
try {
|
|
61
|
+
fn();
|
|
62
|
+
} catch (e) {
|
|
63
|
+
should.equal(e.message, msg);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
throw new Error('no exception thrown, expected "' + msg + '"');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function test(type) {
|
|
70
|
+
var str, obj;
|
|
71
|
+
for (var i = 0; i < str_identities[type].length; i++) {
|
|
72
|
+
str = str_identities[type][i].str;
|
|
73
|
+
obj = str_identities[type][i].obj;
|
|
74
|
+
qs.stringify(obj).should.eql(str);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
module.exports = {
|
|
79
|
+
'test basics': function() {
|
|
80
|
+
test('basics');
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
'test escaping': function() {
|
|
84
|
+
test('escaping');
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
'test nested': function() {
|
|
88
|
+
test('nested');
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
'test numbers': function(){
|
|
92
|
+
test('numbers');
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
'test errors': function() {
|
|
96
|
+
var obj, message;
|
|
97
|
+
for (var i = 0; i < str_identities['errors'].length; i++) {
|
|
98
|
+
message = str_identities['errors'][i].message;
|
|
99
|
+
obj = str_identities['errors'][i].obj;
|
|
100
|
+
err(function(){ qs.stringify(obj) }, message);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
};
|
package/test/stringify.test.js
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* Module dependencies.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
var qs = require('../')
|
|
7
|
-
, should = require('should')
|
|
8
|
-
, query_string_identities = {
|
|
9
|
-
'basics': [
|
|
10
|
-
{query_string: 'foo=bar', parsed: {'foo' : 'bar'}},
|
|
11
|
-
{query_string: 'foo=%22bar%22', parsed: {'foo' : '\"bar\"'}},
|
|
12
|
-
{query_string: 'foo=', parsed: {'foo': ''}},
|
|
13
|
-
{query_string: 'foo=1&bar=2', parsed: {'foo' : '1', 'bar' : '2'}},
|
|
14
|
-
{query_string: 'my%20weird%20field=q1!2%22\'w%245%267%2Fz8)%3F', parsed: {'my weird field': "q1!2\"'w$5&7/z8)?"}},
|
|
15
|
-
{query_string: 'foo%3Dbaz=bar', parsed: {'foo=baz': 'bar'}},
|
|
16
|
-
{query_string: 'foo=bar&bar=baz', parsed: {foo: 'bar', bar: 'baz'}}
|
|
17
|
-
],
|
|
18
|
-
'escaping': [
|
|
19
|
-
{query_string: 'foo=foo%20bar', parsed: {foo: 'foo bar'}},
|
|
20
|
-
{query_string: 'cht=p3&chd=t%3A60%2C40&chs=250x100&chl=Hello%7CWorld', parsed: {
|
|
21
|
-
cht: 'p3'
|
|
22
|
-
, chd: 't:60,40'
|
|
23
|
-
, chs: '250x100'
|
|
24
|
-
, chl: 'Hello|World'
|
|
25
|
-
}}
|
|
26
|
-
],
|
|
27
|
-
'nested': [
|
|
28
|
-
{query_string: 'foo[]=bar&foo[]=quux', parsed: {'foo' : ['bar', 'quux']}},
|
|
29
|
-
{query_string: 'foo[]=bar', parsed: {foo: ['bar']}},
|
|
30
|
-
{query_string: 'foo[]=1&foo[]=2', parsed: {'foo' : ['1', '2']}},
|
|
31
|
-
{query_string: 'foo=bar&baz[]=1&baz[]=2&baz[]=3', parsed: {'foo' : 'bar', 'baz' : ['1', '2', '3']}},
|
|
32
|
-
{query_string: 'foo[]=bar&baz[]=1&baz[]=2&baz[]=3', parsed: {'foo' : ['bar'], 'baz' : ['1', '2', '3']}},
|
|
33
|
-
{query_string: 'x[y][z]=1', parsed: {'x' : {'y' : {'z' : '1'}}}},
|
|
34
|
-
{query_string: 'x[y][z][]=1', parsed: {'x' : {'y' : {'z' : ['1']}}}},
|
|
35
|
-
{query_string: 'x[y][z]=2', parsed: {'x' : {'y' : {'z' : '2'}}}},
|
|
36
|
-
{query_string: 'x[y][z][]=1&x[y][z][]=2', parsed: {'x' : {'y' : {'z' : ['1', '2']}}}},
|
|
37
|
-
{query_string: 'x[y][][z]=1', parsed: {'x' : {'y' : [{'z' : '1'}]}}},
|
|
38
|
-
{query_string: 'x[y][][z][]=1', parsed: {'x' : {'y' : [{'z' : ['1']}]}}},
|
|
39
|
-
{query_string: 'x[y][][z]=1&x[y][][w]=2', parsed: {'x' : {'y' : [{'z' : '1', 'w' : '2'}]}}},
|
|
40
|
-
{query_string: 'x[y][][v][w]=1', parsed: {'x' : {'y' : [{'v' : {'w' : '1'}}]}}},
|
|
41
|
-
{query_string: 'x[y][][z]=1&x[y][][v][w]=2', parsed: {'x' : {'y' : [{'z' : '1', 'v' : {'w' : '2'}}]}}},
|
|
42
|
-
{query_string: 'x[y][][z]=1&x[y][][z]=2', parsed: {'x' : {'y' : [{'z' : '1'}, {'z' : '2'}]}}},
|
|
43
|
-
{query_string: 'x[y][][z]=1&x[y][][w]=a&x[y][][z]=2&x[y][][w]=3', parsed: {'x' : {'y' : [{'z' : '1', 'w' : 'a'}, {'z' : '2', 'w' : '3'}]}}},
|
|
44
|
-
{query_string: 'user[name][first]=tj&user[name][last]=holowaychuk', parsed: { user: { name: { first: 'tj', last: 'holowaychuk' }}}}
|
|
45
|
-
],
|
|
46
|
-
'errors': [
|
|
47
|
-
{ parsed: 'foo=bar', message: 'stringify expects an object' },
|
|
48
|
-
{ parsed: ['foo', 'bar'], message: 'stringify expects an object' }
|
|
49
|
-
]
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
// Assert error
|
|
54
|
-
function err(fn, msg){
|
|
55
|
-
var err;
|
|
56
|
-
try {
|
|
57
|
-
fn();
|
|
58
|
-
} catch (e) {
|
|
59
|
-
should.equal(e.message, msg);
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
throw new Error('no exception thrown, expected "' + msg + '"');
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function test(type) {
|
|
66
|
-
var str, obj;
|
|
67
|
-
for (var i = 0; i < query_string_identities[type].length; i++) {
|
|
68
|
-
str = query_string_identities[type][i].query_string;
|
|
69
|
-
obj = query_string_identities[type][i].parsed;
|
|
70
|
-
qs.stringify(obj).should.eql(str);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
module.exports = {
|
|
75
|
-
'test basics': function() {
|
|
76
|
-
test('basics');
|
|
77
|
-
},
|
|
78
|
-
|
|
79
|
-
'test escaping': function() {
|
|
80
|
-
test('escaping');
|
|
81
|
-
},
|
|
82
|
-
|
|
83
|
-
'test nested': function() {
|
|
84
|
-
test('nested');
|
|
85
|
-
},
|
|
86
|
-
|
|
87
|
-
'test errors': function() {
|
|
88
|
-
var parsed, message;
|
|
89
|
-
for (var i = 0; i < query_string_identities['errors'].length; i++) {
|
|
90
|
-
message = query_string_identities['errors'][i].message;
|
|
91
|
-
parsed = query_string_identities['errors'][i].parsed;
|
|
92
|
-
err(function(){ qs.stringify(parsed) }, message);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
};
|