Changeset 6481
- Timestamp:
- 03/27/07 20:55:56 (2 years ago)
- Files:
-
- spinoffs/prototype/trunk/CHANGELOG (modified) (1 diff)
- spinoffs/prototype/trunk/src/hash.js (modified) (1 diff)
- spinoffs/prototype/trunk/src/string.js (modified) (1 diff)
- spinoffs/prototype/trunk/test/lib/unittest.js (modified) (4 diffs)
- spinoffs/prototype/trunk/test/unit/hash.html (modified) (5 diffs)
- spinoffs/prototype/trunk/test/unit/string.html (modified) (1 diff)
- spinoffs/prototype/trunk/test/unit/unit_tests.html (added)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
spinoffs/prototype/trunk/CHANGELOG
r6478 r6481 1 1 *SVN* 2 2 3 * Make Hash.toQueryString serialize undefined values. Ensure consistency with String.prototype.toQueryParams. Closes #7806. [Mislav Marohnić] 4 Examples: 5 $H({a:'b',c:undefined}).toQueryString() -> 'a=b&c' 6 $H({a:'b',c:null}).toQueryString() -> 'a=b&c=' 7 $H('a=b&c'.toQueryParams()).toQueryString() -> 'a=b&c' 8 $H('a=b&c='.toQueryParams()).toQueryString() -> 'a=b&c=' 9 3 10 * Fix issues with Selector an+b logic, :not support, attribute selector double quotes, plus performance improvements. Closes #7873, #7901. [Andrew Dupont] 4 11 spinoffs/prototype/trunk/src/hash.js
r6368 r6481 36 36 37 37 Hash.toQueryString.addPair = function(key, value, prefix) { 38 if (value == null) return;39 38 key = encodeURIComponent(key); 40 this.push(key + '=' + (value == null ? '' : encodeURIComponent(value))); 39 if (value === undefined) this.push(key); 40 else this.push(key + '=' + (value == null ? '' : encodeURIComponent(value))); 41 41 } 42 42 spinoffs/prototype/trunk/src/string.js
r6473 r6481 96 96 return match[1].split(separator || '&').inject({}, function(hash, pair) { 97 97 if ((pair = pair.split('='))[0]) { 98 var name = decodeURIComponent(pair[0]);99 var value = pair [1] ? decodeURIComponent(pair[1]) : undefined;100 101 if (hash[name] !== undefined) {102 if (hash[name].constructor != Array)103 hash[name] = [hash[name]];104 if (value) hash[name].push(value);98 var key = decodeURIComponent(pair.shift()); 99 var value = pair.length > 1 ? pair.join('=') : pair[0]; 100 if (value != undefined) value = decodeURIComponent(value); 101 102 if (key in hash) { 103 if (hash[key].constructor != Array) hash[key] = [hash[key]]; 104 hash[key].push(value); 105 105 } 106 else hash[ name] = value;106 else hash[key] = value; 107 107 } 108 108 return hash; spinoffs/prototype/trunk/test/lib/unittest.js
r6366 r6481 304 304 catch(e) { this.error(e); } 305 305 }, 306 assertNotEqual: function(expected, actual) { 307 var message = arguments[2] || "assertNotEqual"; 308 try { (expected != actual) ? this.pass() : 309 this.fail(message + ': got "' + Test.Unit.inspect(actual) + '"'); } 310 catch(e) { this.error(e); } 311 }, 306 312 assertEnumEqual: function(expected, actual) { 307 313 var message = arguments[2] || "assertEnumEqual"; … … 314 320 catch(e) { this.error(e); } 315 321 }, 316 assertNotEqual: function(expected, actual) { 317 var message = arguments[2] || "assertNotEqual"; 318 try { (expected != actual) ? this.pass() : 319 this.fail(message + ': got "' + Test.Unit.inspect(actual) + '"'); } 322 assertEnumNotEqual: function(expected, actual) { 323 var message = arguments[2] || "assertEnumEqual"; 324 expected = $A(expected); 325 actual = $A(actual); 326 try { expected.length != actual.length || 327 expected.zip(actual).any(function(pair) { return pair[0] != pair[1] }) ? 328 this.pass() : this.fail(message + ': ' + Test.Unit.inspect(expected) + 329 ' was the same as ' + Test.Unit.inspect(actual)); } 330 catch(e) { this.error(e); } 331 }, 332 assertHashEqual: function(expected, actual) { 333 var message = arguments[2] || "assertHashEqual"; 334 expected = $H(expected); 335 actual = $H(actual); 336 var expected_array = expected.toArray().sort(), actual_array = actual.toArray().sort(); 337 // from now we recursively zip & compare nested arrays 338 try { expected_array.length == actual_array.length && 339 expected_array.zip(actual_array).all(function(pair) { 340 return pair.all(function(i){ return i && i.constructor == Array }) ? 341 pair[0].zip(pair[1]).all(arguments.callee) : pair[0] == pair[1]; 342 }) ? 343 this.pass() : this.fail(message + ': expected ' + Test.Unit.inspect(expected) + 344 ', actual ' + Test.Unit.inspect(actual)); } 345 catch(e) { this.error(e); } 346 }, 347 assertHashNotEqual: function(expected, actual) { 348 var message = arguments[2] || "assertHashEqual"; 349 expected = $H(expected); 350 actual = $H(actual); 351 var expected_array = expected.toArray().sort(), actual_array = actual.toArray().sort(); 352 // from now we recursively zip & compare nested arrays 353 try { !(expected_array.length == actual_array.length && 354 expected_array.zip(actual_array).all(function(pair) { 355 return pair.all(function(i){ return i && i.constructor == Array }) ? 356 pair[0].zip(pair[1]).all(arguments.callee) : pair[0] == pair[1]; 357 })) ? 358 this.pass() : this.fail(message + ': ' + Test.Unit.inspect(expected) + 359 ' was the same as ' + Test.Unit.inspect(actual)); } 320 360 catch(e) { this.error(e); } 321 361 }, … … 373 413 var message = arguments[2] || 'assertMatch'; 374 414 var regex = new RegExp(expected); 375 try { (regex.exec(actual)) ? this.pass() :415 try { regex.exec(actual) ? this.pass() : 376 416 this.fail(message + ' : regex: "' + Test.Unit.inspect(expected) + ' did not match: ' + Test.Unit.inspect(actual) + '"'); } 417 catch(e) { this.error(e); } 418 }, 419 assertNoMatch: function(expected, actual) { 420 var message = arguments[2] || 'assertMatch'; 421 var regex = new RegExp(expected); 422 try { !regex.exec(actual) ? this.pass() : 423 this.fail(message + ' : regex: "' + Test.Unit.inspect(expected) + ' matched: ' + Test.Unit.inspect(actual) + '"'); } 377 424 catch(e) { this.error(e); } 378 425 }, … … 380 427 var message = arguments[1] || 'assertHidden'; 381 428 this.assertEqual("none", element.style.display, message); 382 },383 assertNotNull: function(object) {384 var message = arguments[1] || 'assertNotNull';385 this.assert(object != null, message);386 429 }, 387 430 assertInstanceOf: function(expected, actual) { spinoffs/prototype/trunk/test/unit/hash.html
r6363 r6481 39 39 40 40 functions: { 41 alpha: 'foo',42 beta: function(n) { return n+1;}41 quad: function(n) { return n*n }, 42 plus: function(n) { return n+n } 43 43 }, 44 44 … … 66 66 67 67 testConstruct: function(){ with(this) { 68 var h = $H(Fixtures.one) 69 assertNotIdentical(Fixtures.one, h) 70 assertIdentical(h, $H(h)) 68 var h = $H(Fixtures.one); 69 assertNotIdentical(Fixtures.one, h); 70 assertIdentical(h, $H(h)); 71 71 72 var h2 = new Hash(h) 73 assertNotIdentical(h, h2) 74 assert Equal(h.inspect(), h2.inspect())72 var h2 = new Hash(h); 73 assertNotIdentical(h, h2); 74 assertHashEqual(h, h2); 75 75 }}, 76 76 … … 78 78 assertEnumEqual([], $H({}).keys()); 79 79 assertEnumEqual(['a'], $H(Fixtures.one).keys()); 80 assertEnumEqual($w('a b c d'), $H(Fixtures.many).keys() );81 assertEnumEqual($w(' alpha beta'), $H(Fixtures.functions).keys());80 assertEnumEqual($w('a b c d'), $H(Fixtures.many).keys().sort()); 81 assertEnumEqual($w('plus quad'), $H(Fixtures.functions).keys().sort()); 82 82 }}, 83 83 … … 85 85 assertEnumEqual([], $H({}).values()); 86 86 assertEnumEqual(['A#'], $H(Fixtures.one).values()); 87 assertEnumEqual($w('A B C D#'), $H(Fixtures.many).values()); 88 assertEqual('function', typeof $H(Fixtures.functions).values()[1]); 89 assertEqual(2, $H(Fixtures.functions).beta(1)); 87 assertEnumEqual($w('A B C D#'), $H(Fixtures.many).values().sort()); 88 assertEnumEqual($w('function function'), 89 $H(Fixtures.functions).values().map(function(i){ return typeof i })); 90 assertEqual(9, $H(Fixtures.functions).quad(3)); 91 assertEqual(6, $H(Fixtures.functions).plus(3)); 90 92 }}, 91 93 92 94 testMerge: function(){ with(this) { 93 assertEqual($H(Fixtures.many).inspect(), $H(Fixtures.many).merge().inspect()); 94 assertEqual($H(Fixtures.many).inspect(), $H(Fixtures.many).merge({}).inspect()); 95 assertEqual("#<Hash:{'a': 'A', 'b': 'B', 'c': 'C', 'd': 'D#', 'aaa': 'AAA'}>", $H(Fixtures.many).merge({aaa: 'AAA'}).inspect()); 96 assertEqual("#<Hash:{'a': 'A#', 'b': 'B', 'c': 'C', 'd': 'D#'}>", $H(Fixtures.many).merge(Fixtures.one).inspect()); 95 assertHashEqual(Fixtures.many, $H(Fixtures.many).merge()); 96 assertHashEqual(Fixtures.many, $H(Fixtures.many).merge({})); 97 assertHashEqual(Fixtures.many, $H(Fixtures.many).merge($H())); 98 assertHashEqual({a:'A', b:'B', c:'C', d:'D#', aaa:'AAA' }, $H(Fixtures.many).merge({aaa: 'AAA'})); 99 assertHashEqual({a:'A#', b:'B', c:'C', d:'D#' }, $H(Fixtures.many).merge(Fixtures.one)); 97 100 }}, 98 101 … … 100 103 var hash = $H(Fixtures.many); 101 104 var values = hash.remove('b', 'c'); 102 assert EnumEqual($w('a d'), hash.keys());105 assertHashEqual({a:'A', d:'D#'}, hash); 103 106 assertEnumEqual($w('B C'), values); 104 107 }}, 105 108 106 109 testToQueryString: function(){ with(this) { 107 assertEqual('', $H({}).toQueryString()); 108 assertEqual('a=A%23', $H(Fixtures.one).toQueryString()); 109 assertEqual('a=A&b=B&c=C&d=D%23', $H(Fixtures.many).toQueryString()); 110 assertEqual("a=b", $H(Fixtures.value_undefined).toQueryString()); 111 assertEqual("a=b", $H(Fixtures.value_null).toQueryString()); 112 assertEqual("a=b&c=0", $H(Fixtures.value_zero).toQueryString()); 110 assertEqual('', $H({}).toQueryString()); 111 assertEqual('a=A%23', $H(Fixtures.one).toQueryString()); 112 assertEqual('a=A&b=B&c=C&d=D%23', $H(Fixtures.many).toQueryString()); 113 assertEqual("a=b&c", $H(Fixtures.value_undefined).toQueryString()); 114 assertEqual("a=b&c", $H("a=b&c".toQueryParams()).toQueryString()); 115 assertEqual("a=b&c=", $H(Fixtures.value_null).toQueryString()); 116 assertEqual("a=b&c=0", $H(Fixtures.value_zero).toQueryString()); 113 117 assertEqual("color=r&color=g&color=b", $H(Fixtures.multiple).toQueryString()); 114 assertEqual("color=r&color= g&color=0", $H(Fixtures.multiple_nil).toQueryString());115 assertEqual(" ",$H(Fixtures.multiple_all_nil).toQueryString());116 assertEqual("", $H(Fixtures.multiple_empty).toQueryString());118 assertEqual("color=r&color=&color=g&color&color=0", $H(Fixtures.multiple_nil).toQueryString()); 119 assertEqual("color=&color", $H(Fixtures.multiple_all_nil).toQueryString()); 120 assertEqual("", $H(Fixtures.multiple_empty).toQueryString()); 117 121 assertEqual("stuff%5B%5D=%24&stuff%5B%5D=a&stuff%5B%5D=%3B", $H(Fixtures.multiple_special).toQueryString()); 118 119 assertEnumEqual($w("_each=E map=M keys=K values=V collect=C inject=I").sort(),120 Hash.toQueryString(Fixtures.dangerous).split('&').sort());121 assertEnumEqual( $w('_each=E map=M keys=K values=V collect=C inject=I').sort(),122 $H(Fixtures.dangerous).toQueryString().split('&').sort());122 assertHashEqual(Fixtures.multiple_special, $H(Fixtures.multiple_special).toQueryString().toQueryParams()); 123 124 var danger = $w("_each=E collect=C inject=I keys=K map=M values=V"); 125 assertEnumEqual(danger, Hash.toQueryString(Fixtures.dangerous).split('&').sort()); 126 assertEnumEqual(danger, $H(Fixtures.dangerous).toQueryString().split('&').sort()); 123 127 }}, 124 128 spinoffs/prototype/trunk/test/unit/string.html
r6473 r6481 290 290 291 291 testToQueryParams: function() {with(this) { 292 assertEnumEqual([], Object.keys(''.toQueryParams())); 293 assertEnumEqual([], Object.keys('foo?'.toQueryParams())); 294 295 assertEnumEqual(['a', 'b'], Object.keys('foo?a&b'.toQueryParams())); 296 assertEnumEqual(['a', 'b'], Object.keys('foo?a&b#fragment'.toQueryParams())); 297 assertEnumEqual(['a', 'b'], Object.keys('a;b'.toQueryParams(';'))); 298 299 var result = 'a'.toQueryParams(); 300 assertEqual(undefined, result['a']); 301 assert(result.hasOwnProperty('a')); 302 303 result = 'a&b=c'.toQueryParams(); 304 assertEqual(undefined, result['a']); 305 assert(result.hasOwnProperty('a')); 306 assertEqual('c', result['b']); 307 308 result = 'a%20b=c&d=e%20f&g=h'.toQueryParams(); 309 assertEqual('c', result['a b']); 310 assertEqual('e f', result['d']); 311 assertEqual('h', result['g']); 312 313 result = 'color=r&color=g&color=b'.toQueryParams(); 314 assertEnumEqual(['r', 'g', 'b'], result['color']); 315 assertEnumEqual(['r', 'b'], 'c=r&c=&c=b'.toQueryParams()['c']); 316 assertEqual('blue', 'c=&c=blue'.toQueryParams()['c']); 317 assertEqual('blue', 'c=blue&c='.toQueryParams()['c']); 292 // only the query part 293 var result = {a:undefined, b:'c'}; 294 assertHashEqual({}, ''.toQueryParams(), 'empty query'); 295 assertHashEqual({}, 'foo?'.toQueryParams(), 'empty query with URL'); 296 assertHashEqual(result, 'foo?a&b=c'.toQueryParams(), 'query with URL'); 297 assertHashEqual(result, 'foo?a&b=c#fragment'.toQueryParams(), 'query with URL and fragment'); 298 assertHashEqual(result, 'a;b=c'.toQueryParams(';'), 'custom delimiter'); 299 300 assertHashEqual({a:undefined}, 'a'.toQueryParams(), 'key without value'); 301 assertHashEqual({a:'b'}, 'a=b&=c'.toQueryParams(), 'empty key'); 302 assertHashEqual({a:'b', c:''}, 'a=b&c='.toQueryParams(), 'empty value'); 303 304 assertHashEqual({'a b':'c', d:'e f', g:'h'}, 305 'a%20b=c&d=e%20f&g=h'.toQueryParams(), 'proper decoding'); 306 assertHashEqual({a:'b=c=d'}, 'a=b=c=d'.toQueryParams(), 'multiple equal signs'); 307 assertHashEqual({a:'b', c:'d'}, '&a=b&&&c=d'.toQueryParams(), 'proper splitting'); 308 309 assertEnumEqual($w('r g b'), 'col=r&col=g&col=b'.toQueryParams()['col'], 310 'collection without square brackets'); 311 var msg = 'empty values inside collection'; 312 assertEnumEqual(['r', '', 'b'], 'c=r&c=&c=b'.toQueryParams()['c'], msg); 313 assertEnumEqual(['', 'blue'], 'c=&c=blue'.toQueryParams()['c'], msg); 314 assertEnumEqual(['blue', ''], 'c=blue&c='.toQueryParams()['c'], msg); 318 315 }}, 319 316