| 1 | if (typeof(dojo) != 'undefined') { dojo.require('MochiKit.Base'); } |
| 2 | if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.Base'); } |
| 3 | if (typeof(tests) == 'undefined') { tests = {}; } |
| 4 | |
| 5 | tests.test_Base = function (t) { |
| 6 | // test bind |
| 7 | var not_self = {"toString": function () { return "not self"; } }; |
| 8 | var self = {"toString": function () { return "self"; } }; |
| 9 | var func = function (arg) { return this.toString() + " " + arg; }; |
| 10 | var boundFunc = bind(func, self); |
| 11 | not_self.boundFunc = boundFunc; |
| 12 | |
| 13 | t.is( isEmpty([], [], ""), true, "isEmpty true" ) |
| 14 | t.is( isEmpty([], [1], ""), true, "isEmpty true" ) |
| 15 | t.is( isNotEmpty([], [], ""), false, "isNotEmpty false" ) |
| 16 | t.is( isNotEmpty([], [1], ""), false, "isNotEmpty false" ) |
| 17 | |
| 18 | t.is( isEmpty([1], [1], "1"), false, "isEmpty false" ) |
| 19 | t.is( isEmpty([1], [1], "1"), false, "isEmpty false" ) |
| 20 | t.is( isNotEmpty([1], [1], "1"), true, "isNotEmpty true" ) |
| 21 | t.is( isNotEmpty([1], [1], "1"), true, "isNotEmpty true" ) |
| 22 | |
| 23 | t.is( boundFunc("foo"), "self foo", "boundFunc bound to self properly" ); |
| 24 | t.is( not_self.boundFunc("foo"), "self foo", "boundFunc bound to self on another obj" ); |
| 25 | t.is( bind(boundFunc, not_self)("foo"), "not self foo", "boundFunc successfully rebound!" ); |
| 26 | t.is( bind(boundFunc, undefined, "foo")(), "self foo", "boundFunc partial no self change" ); |
| 27 | t.is( bind(boundFunc, not_self, "foo")(), "not self foo", "boundFunc partial self change" ); |
| 28 | |
| 29 | // test method |
| 30 | not_self = {"toString": function () { return "not self"; } }; |
| 31 | self = {"toString": function () { return "self"; } }; |
| 32 | func = function (arg) { return this.toString() + " " + arg; }; |
| 33 | var boundMethod = method(self, func); |
| 34 | not_self.boundMethod = boundMethod; |
| 35 | |
| 36 | t.is( boundMethod("foo"), "self foo", "boundMethod bound to self properly" ); |
| 37 | t.is( not_self.boundMethod("foo"), "self foo", "boundMethod bound to self on another obj" ); |
| 38 | t.is( method(not_self, boundMethod)("foo"), "not self foo", "boundMethod successfully rebound!" ); |
| 39 | t.is( method(undefined, boundMethod, "foo")(), "self foo", "boundMethod partial no self change" ); |
| 40 | t.is( method(not_self, boundMethod, "foo")(), "not self foo", "boundMethod partial self change" ); |
| 41 | |
| 42 | |
| 43 | |
| 44 | |
| 45 | // test bindMethods |
| 46 | |
| 47 | var O = function (value) { |
| 48 | bindMethods(this); |
| 49 | this.value = value; |
| 50 | }; |
| 51 | O.prototype.func = function () { |
| 52 | return this.value; |
| 53 | }; |
| 54 | |
| 55 | var o = new O("boring"); |
| 56 | var p = {}; |
| 57 | p.func = o.func; |
| 58 | var func = o.func; |
| 59 | t.is( o.func(), "boring", "bindMethods doesn't break shit" ); |
| 60 | t.is( p.func(), "boring", "bindMethods works on other objects" ); |
| 61 | t.is( func(), "boring", "bindMethods works on functions" ); |
| 62 | |
| 63 | var p = clone(o); |
| 64 | t.ok( p instanceof O, "cloned correct inheritance" ); |
| 65 | var q = clone(p); |
| 66 | t.ok( q instanceof O, "clone-cloned correct inheritance" ); |
| 67 | q.foo = "bar"; |
| 68 | t.is( p.foo, undefined, "clone-clone is copy-on-write" ); |
| 69 | p.bar = "foo"; |
| 70 | t.is( o.bar, undefined, "clone is copy-on-write" ); |
| 71 | t.is( q.bar, "foo", "clone-clone has proper delegation" ); |
| 72 | // unbind |
| 73 | p.func = bind(p.func, null); |
| 74 | t.is( p.func(), "boring", "clone function calls correct" ); |
| 75 | q.value = "awesome"; |
| 76 | t.is( q.func(), "awesome", "clone really does work" ); |
| 77 | |
| 78 | // test boring boolean funcs |
| 79 | |
| 80 | t.is( isCallable(isCallable), true, "isCallable returns true on itself" ); |
| 81 | t.is( isCallable(1), false, "isCallable returns false on numbers" ); |
| 82 | |
| 83 | t.is( isUndefined(null), false, "null is not undefined" ); |
| 84 | t.is( isUndefined(""), false, "empty string is not undefined" ); |
| 85 | t.is( isUndefined(undefined), true, "undefined is undefined" ); |
| 86 | t.is( isUndefined({}.foo), true, "missing property is undefined" ); |
| 87 | |
| 88 | t.is( isUndefinedOrNull(null), true, "null is undefined or null" ); |
| 89 | t.is( isUndefinedOrNull(""), false, "empty string is not undefined or null" ); |
| 90 | t.is( isUndefinedOrNull(undefined), true, "undefined is undefined or null" ); |
| 91 | t.is( isUndefinedOrNull({}.foo), true, "missing property is undefined or null" ); |
| 92 | |
| 93 | // test extension of arrays |
| 94 | var a = []; |
| 95 | var b = []; |
| 96 | var three = [1, 2, 3]; |
| 97 | |
| 98 | extend(a, three, 1); |
| 99 | t.ok( objEqual(a, [2, 3]), "extend to an empty array" ); |
| 100 | extend(a, three, 1) |
| 101 | t.ok( objEqual(a, [2, 3, 2, 3]), "extend to a non-empty array" ); |
| 102 | |
| 103 | extend(b, three); |
| 104 | t.ok( objEqual(b, three), "extend of an empty array" ); |
| 105 | |
| 106 | t.is( compare(1, 2), -1, "numbers compare lt" ); |
| 107 | t.is( compare(2, 1), 1, "numbers compare gt" ); |
| 108 | t.is( compare(1, 1), 0, "numbers compare eq" ); |
| 109 | t.is( compare([1], [1]), 0, "arrays compare eq" ); |
| 110 | t.is( compare([1], [1, 2]), -1, "arrays compare lt (length)" ); |
| 111 | t.is( compare([1, 2], [2, 1]), -1, "arrays compare lt (contents)" ); |
| 112 | t.is( compare([1, 2], [1]), 1, "arrays compare gt (length)" ); |
| 113 | t.is( compare([2, 1], [1, 1]), 1, "arrays compare gt (contents)" ); |
| 114 | |
| 115 | // test partial application |
| 116 | var a = []; |
| 117 | var func = function (a, b) { |
| 118 | if (arguments.length != 2) { |
| 119 | return "bad args"; |
| 120 | } else { |
| 121 | return this.value + a + b; |
| 122 | } |
| 123 | }; |
| 124 | var self = {"value": 1, "func": func}; |
| 125 | var self2 = {"value": 2}; |
| 126 | t.is( self.func(2, 3), 6, "setup for test is correct" ); |
| 127 | self.funcTwo = partial(self.func, 2); |
| 128 | t.is( self.funcTwo(3), 6, "partial application works" ); |
| 129 | t.is( self.funcTwo(3), 6, "partial application works still" ); |
| 130 | t.is( bind(self.funcTwo, self2)(3), 7, "rebinding partial works" ); |
| 131 | self.funcTwo = bind(bind(self.funcTwo, self2), null); |
| 132 | t.is( self.funcTwo(3), 6, "re-unbinding partial application works" ); |
| 133 | |
| 134 | |
| 135 | // nodeWalk test |
| 136 | // ... looks a lot like a DOM tree on purpose |
| 137 | var tree = { |
| 138 | "id": "nodeWalkTestTree", |
| 139 | "test:int": "1", |
| 140 | "childNodes": [ |
| 141 | { |
| 142 | "test:int": "2", |
| 143 | "childNodes": [ |
| 144 | {"test:int": "5"}, |
| 145 | "ignored string", |
| 146 | {"ignored": "object"}, |
| 147 | ["ignored", "list"], |
| 148 | { |
| 149 | "test:skipchildren": "1", |
| 150 | "childNodes": [{"test:int": 6}] |
| 151 | } |
| 152 | ] |
| 153 | }, |
| 154 | {"test:int": "3"}, |
| 155 | {"test:int": "4"} |
| 156 | ] |
| 157 | } |
| 158 | |
| 159 | var visitedNodes = []; |
| 160 | nodeWalk(tree, function (node) { |
| 161 | var attr = node["test:int"]; |
| 162 | if (attr) { |
| 163 | visitedNodes.push(attr); |
| 164 | } |
| 165 | if (node["test:skipchildren"]) { |
| 166 | return; |
| 167 | } |
| 168 | return node.childNodes; |
| 169 | }); |
| 170 | |
| 171 | t.ok( objEqual(visitedNodes, ["1", "2", "3", "4", "5"]), "nodeWalk looks like it works"); |
| 172 | |
| 173 | // test map |
| 174 | var minusOne = function (x) { return x - 1; }; |
| 175 | var res = map(minusOne, [1, 2, 3]); |
| 176 | t.ok( objEqual(res, [0, 1, 2]), "map works" ); |
| 177 | |
| 178 | var res2 = xmap(minusOne, 1, 2, 3); |
| 179 | t.ok( objEqual(res2, res), "xmap works" ); |
| 180 | |
| 181 | res = map(operator.add, [1, 2, 3], [2, 4, 6]); |
| 182 | t.ok( objEqual(res, [3, 6, 9]), "map(fn, p, q) works" ); |
| 183 | |
| 184 | res = map(operator.add, [1, 2, 3], [2, 4, 6, 8]); |
| 185 | t.ok( objEqual(res, [3, 6, 9]), "map(fn, p, q) works (q long)" ); |
| 186 | |
| 187 | res = map(operator.add, [1, 2, 3, 4], [2, 4, 6]); |
| 188 | t.ok( objEqual(res, [3, 6, 9]), "map(fn, p, q) works (p long)" ); |
| 189 | |
| 190 | res = map(null, [1, 2, 3], [2, 4, 6]); |
| 191 | t.ok( objEqual(res, [[1, 2], [2, 4], [3, 6]]), "map(null, p, q) works" ); |
| 192 | |
| 193 | res = zip([1, 2, 3], [2, 4, 6]); |
| 194 | t.ok( objEqual(res, [[1, 2], [2, 4], [3, 6]]), "zip(p, q) works" ); |
| 195 | |
| 196 | res = map(null, [1, 2, 3]); |
| 197 | t.ok( objEqual(res, [1, 2, 3]), "map(null, lst) works" ); |
| 198 | |
| 199 | |
| 200 | |
| 201 | |
| 202 | t.is( isNotEmpty("foo"), true, "3 char string is not empty" ); |
| 203 | t.is( isNotEmpty(""), false, "0 char string is empty" ); |
| 204 | t.is( isNotEmpty([1, 2, 3]), true, "3 element list is not empty" ); |
| 205 | t.is( isNotEmpty([]), false, "0 element list is empty" ); |
| 206 | |
| 207 | // test filter |
| 208 | var greaterThanThis = function (x) { return x > this; }; |
| 209 | var greaterThanOne = function (x) { return x > 1; }; |
| 210 | var res = filter(greaterThanOne, [-1, 0, 1, 2, 3]); |
| 211 | t.ok( objEqual(res, [2, 3]), "filter works" ); |
| 212 | var res = filter(greaterThanThis, [-1, 0, 1, 2, 3], 1); |
| 213 | t.ok( objEqual(res, [2, 3]), "filter self works" ); |
| 214 | var res2 = xfilter(greaterThanOne, -1, 0, 1, 2, 3); |
| 215 | t.ok( objEqual(res2, res), "xfilter works" ); |
| 216 | |
| 217 | t.is(objMax(1, 2, 9, 12, 42, -16, 16), 42, "objMax works (with numbers)"); |
| 218 | t.is(objMin(1, 2, 9, 12, 42, -16, 16), -16, "objMin works (with numbers)"); |
| 219 | |
| 220 | // test adapter registry |
| 221 | |
| 222 | var R = new AdapterRegistry(); |
| 223 | R.register("callable", isCallable, function () { return "callable"; }); |
| 224 | R.register("arrayLike", isArrayLike, function () { return "arrayLike"; }); |
| 225 | t.is( R.match(function () {}), "callable", "registry found callable" ); |
| 226 | t.is( R.match([]), "arrayLike", "registry found ArrayLike" ); |
| 227 | try { |
| 228 | R.match(null); |
| 229 | t.ok( false, "non-matching didn't raise!" ); |
| 230 | } catch (e) { |
| 231 | t.is( e, NotFound, "non-matching raised correctly" ); |
| 232 | } |
| 233 | R.register("undefinedOrNull", isUndefinedOrNull, function () { return "undefinedOrNull" }); |
| 234 | R.register("undefined", isUndefined, function () { return "undefined" }); |
| 235 | t.is( R.match(undefined), "undefinedOrNull", "priorities are as documented" ); |
| 236 | t.ok( R.unregister("undefinedOrNull"), "removed adapter" ); |
| 237 | t.is( R.match(undefined), "undefined", "adapter was removed" ); |
| 238 | R.register("undefinedOrNull", isUndefinedOrNull, function () { return "undefinedOrNull" }, true); |
| 239 | t.is( R.match(undefined), "undefinedOrNull", "override works" ); |
| 240 | |
| 241 | var a1 = {"a": 1, "b": 2, "c": 2}; |
| 242 | var a2 = {"a": 2, "b": 1, "c": 2}; |
| 243 | t.is( keyComparator("a")(a1, a2), -1, "keyComparator 1 lt" ); |
| 244 | t.is( keyComparator("c")(a1, a2), 0, "keyComparator 1 eq" ); |
| 245 | t.is( keyComparator("c", "b")(a1, a2), 1, "keyComparator 2 eq gt" ); |
| 246 | t.is( keyComparator("c", "a")(a1, a2), -1, "keyComparator 2 eq lt" ); |
| 247 | t.is( reverseKeyComparator("a")(a1, a2), 1, "reverseKeyComparator" ); |
| 248 | t.is( compare(concat([1], [2], [3]), [1, 2, 3]), 0, "concat" ); |
| 249 | t.is( repr("foo"), '"foo"', "string repr" ); |
| 250 | t.is( repr(1), '1', "number repr" ); |
| 251 | t.is( listMin([1, 3, 5, 3, -1]), -1, "listMin" ); |
| 252 | t.is( objMin(1, 3, 5, 3, -1), -1, "objMin" ); |
| 253 | t.is( listMax([1, 3, 5, 3, -1]), 5, "listMax" ); |
| 254 | t.is( objMax(1, 3, 5, 3, -1), 5, "objMax" ); |
| 255 | |
| 256 | var v = keys(a1); |
| 257 | v.sort(); |
| 258 | t.is( compare(v, ["a", "b", "c"]), 0, "keys" ); |
| 259 | v = items(a1); |
| 260 | v.sort(); |
| 261 | t.is( compare(v, [["a", 1], ["b", 2], ["c", 2]]), 0, "items" ); |
| 262 | |
| 263 | var StringMap = function() {}; |
| 264 | a = new StringMap(); |
| 265 | a.foo = "bar"; |
| 266 | b = new StringMap(); |
| 267 | b.foo = "bar"; |
| 268 | try { |
| 269 | compare(a, b); |
| 270 | t.ok( false, "bad comparison registered!?" ); |
| 271 | } catch (e) { |
| 272 | t.ok( e instanceof TypeError, "bad comparison raised TypeError" ); |
| 273 | } |
| 274 | |
| 275 | t.is( repr(a), "[object Object]", "default repr for StringMap" ); |
| 276 | var isStringMap = function () { |
| 277 | for (var i = 0; i < arguments.length; i++) { |
| 278 | if (!(arguments[i] instanceof StringMap)) { |
| 279 | return false; |
| 280 | } |
| 281 | } |
| 282 | return true; |
| 283 | }; |
| 284 | |
| 285 | registerRepr("stringMap", |
| 286 | isStringMap, |
| 287 | function (obj) { |
| 288 | return "StringMap(" + repr(items(obj)) + ")"; |
| 289 | } |
| 290 | ); |
| 291 | |
| 292 | t.is( repr(a), 'StringMap([["foo", "bar"]])', "repr worked" ); |
| 293 | |
| 294 | // not public API |
| 295 | MochiKit.Base.reprRegistry.unregister("stringMap"); |
| 296 | |
| 297 | t.is( repr(a), "[object Object]", "default repr for StringMap" ); |
| 298 | |
| 299 | registerComparator("stringMap", |
| 300 | isStringMap, |
| 301 | function (a, b) { |
| 302 | // no sorted(...) in base |
| 303 | a = items(a); |
| 304 | b = items(b); |
| 305 | a.sort(compare); |
| 306 | b.sort(compare); |
| 307 | return compare(a, b); |
| 308 | } |
| 309 | ); |
| 310 | |
| 311 | t.is( compare(a, b), 0, "registerComparator" ); |
| 312 | |
| 313 | update(a, {"foo": "bar"}, {"wibble": "baz"}, undefined, null, {"grr": 1}); |
| 314 | t.is( a.foo, "bar", "update worked (first obj)" ); |
| 315 | t.is( a.wibble, "baz", "update worked (second obj)" ); |
| 316 | t.is( a.grr, 1, "update worked (skipped undefined and null)" ); |
| 317 | t.is( compare(a, b), 1, "update worked (comparison)" ); |
| 318 | |
| 319 | |
| 320 | setdefault(a, {"foo": "unf"}, {"bar": "web taco"} ); |
| 321 | t.is( a.foo, "bar", "setdefault worked (skipped existing)" ); |
| 322 | t.is( a.bar, "web taco", "setdefault worked (set non-existing)" ); |
| 323 | |
| 324 | var c = items(merge({"foo": "bar"}, {"wibble": "baz"})); |
| 325 | c.sort(compare); |
| 326 | t.is( compare(c, [["foo", "bar"], ["wibble", "baz"]]), 0, "merge worked" ); |
| 327 | |
| 328 | // not public API |
| 329 | MochiKit.Base.comparatorRegistry.unregister("stringMap"); |
| 330 | |
| 331 | try { |
| 332 | compare(a, b); |
| 333 | t.ok( false, "bad comparison registered!?" ); |
| 334 | } catch (e) { |
| 335 | t.ok( e instanceof TypeError, "bad comparison raised TypeError" ); |
| 336 | } |
| 337 | |
| 338 | var o = {"__repr__": function () { return "__repr__"; }}; |
| 339 | t.is( repr(o), "__repr__", "__repr__ protocol" ); |
| 340 | t.is( repr(MochiKit.Base), MochiKit.Base.__repr__(), "__repr__ protocol when repr is defined" ); |
| 341 | var o = {"NAME": "NAME"}; |
| 342 | t.is( repr(o), "NAME", "NAME protocol (obj)" ); |
| 343 | o = function () { return "TACO" }; |
| 344 | o.NAME = "NAME"; |
| 345 | t.is( repr(o), "NAME", "NAME protocol (func)" ); |
| 346 | |
| 347 | t.is( repr(MochiKit.Base.nameFunctions), "MochiKit.Base.nameFunctions", "test nameFunctions" ); |
| 348 | // Done! |
| 349 | |
| 350 | t.is( urlEncode("1+2=2").toUpperCase(), "1%2B2%3D2", "urlEncode" ); |
| 351 | t.is( queryString(["a", "b"], [1, "two"]), "a=1&b=two", "queryString"); |
| 352 | t.is( queryString({"a": 1}), "a=1", "one item alternate form queryString" ); |
| 353 | var o = {"a": 1, "b": 2, "c": function() {}}; |
| 354 | var res = queryString(o).split("&"); |
| 355 | res.sort(); |
| 356 | t.is( res.join("&"), "a=1&b=2", "two item alternate form queryString, function skip" ); |
| 357 | var res = parseQueryString("1+1=2&b=3%3D2"); |
| 358 | t.is( res["1 1"], "2", "parseQueryString pathological name" ); |
| 359 | t.is( res.b, "3=2", "parseQueryString second name:value pair" ); |
| 360 | var res = parseQueryString("foo=one&foo=two", true); |
| 361 | t.is( res["foo"].join(" "), "one two", "parseQueryString useArrays" ); |
| 362 | var res = parseQueryString("?foo=2&bar=1"); |
| 363 | t.is( res["foo"], "2", "parseQueryString strip leading question mark"); |
| 364 | |
| 365 | t.is( serializeJSON("foo\n\r\b\f\t"), "\"foo\\n\\r\\b\\f\\t\"", "string JSON" ); |
| 366 | t.is( serializeJSON(null), "null", "null JSON"); |
| 367 | try { |
| 368 | serializeJSON(undefined); |
| 369 | t.ok(false, "undefined should not be serializable"); |
| 370 | } catch (e) { |
| 371 | t.ok(e instanceof TypeError, "undefined not serializable"); |
| 372 | } |
| 373 | t.is( serializeJSON(1), "1", "1 JSON"); |
| 374 | t.is( serializeJSON(1.23), "1.23", "1.23 JSON"); |
| 375 | t.is( serializeJSON(serializeJSON), null, "function JSON (null, not string)" ); |
| 376 | t.is( serializeJSON([1, "2", 3.3]), "[1, \"2\", 3.3]", "array JSON" ); |
| 377 | var res = evalJSON(serializeJSON({"a":1, "b":2})); |
| 378 | t.is( res.a, 1, "evalJSON on an object (1)" ); |
| 379 | t.is( res.b, 2, "evalJSON on an object (2)" ); |
| 380 | var res = {"a": 1, "b": 2, "json": function () { return this; }}; |
| 381 | var res = evalJSON(serializeJSON(res)); |
| 382 | t.is( res.a, 1, "evalJSON on an object that jsons self (1)" ); |
| 383 | t.is( res.b, 2, "evalJSON on an object that jsons self (2)" ); |
| 384 | var strJSON = {"a": 1, "b": 2, "json": function () { return "json"; }}; |
| 385 | t.is( serializeJSON(strJSON), "\"json\"", "json serialization calling" ); |
| 386 | t.is( serializeJSON([strJSON]), "[\"json\"]", "json serialization calling in a structure" ); |
| 387 | registerJSON("isDateLike", |
| 388 | isDateLike, |
| 389 | function (d) { |
| 390 | return "this was a date"; |
| 391 | } |
| 392 | ); |
| 393 | t.is( serializeJSON(new Date()), "\"this was a date\"", "json registry" ); |
| 394 | MochiKit.Base.jsonRegistry.unregister("isDateLike"); |
| 395 | |
| 396 | var a = {"foo": {"bar": 12, "wibble": 13}}; |
| 397 | var b = {"foo": {"baz": 4, "bar": 16}, "bar": 4}; |
| 398 | updatetree(a, b); |
| 399 | var expect = [["bar", 16], ["baz", 4], ["wibble", 13]]; |
| 400 | var got = items(a.foo); |
| 401 | got.sort(compare); |
| 402 | t.is( repr(got), repr(expect), "updatetree merge" ); |
| 403 | t.is( a.bar, 4, "updatetree insert" ); |
| 404 | |
| 405 | var c = counter(); |
| 406 | t.is( c(), 1, "counter starts at 1" ); |
| 407 | t.is( c(), 2, "counter increases" ); |
| 408 | c = counter(2); |
| 409 | t.is( c(), 2, "counter starts at 2" ); |
| 410 | t.is( c(), 3, "counter increases" ); |
| 411 | |
| 412 | t.is( findValue([1, 2, 3], 4), -1, "findValue returns -1 on not found"); |
| 413 | t.is( findValue([1, 2, 3], 1), 0, "findValue returns correct index"); |
| 414 | t.is( findValue([1, 2, 3], 1, 1), -1, "findValue honors start"); |
| 415 | t.is( findValue([1, 2, 3], 2, 0, 1), -1, "findValue honors end"); |
| 416 | t.is( findIdentical([1, 2, 3], 4), -1, "findIdentical returns -1"); |
| 417 | t.is( findIdentical([1, 2, 3], 1), 0, "findIdentical returns correct index"); |
| 418 | t.is( findIdentical([1, 2, 3], 1, 1), -1, "findIdentical honors start"); |
| 419 | t.is( findIdentical([1, 2, 3], 2, 0, 1), -1, "findIdentical honors end"); |
| 420 | t.is( isNull(undefined), false, "isNull doesn't match undefined" ); |
| 421 | |
| 422 | var flat = flattenArguments(1, "2", 3, [4, [5, [6, 7], 8, [], 9]]); |
| 423 | var expect = [1, "2", 3, 4, 5, 6, 7, 8, 9]; |
| 424 | t.is( repr(flat), repr(expect), "flattenArguments" ); |
| 425 | |
| 426 | var fn = function () { |
| 427 | return [this, concat(arguments)]; |
| 428 | } |
| 429 | t.is( methodcaller("toLowerCase")("FOO"), "foo", "methodcaller with a method name" ); |
| 430 | t.is( repr(methodcaller(fn, 2, 3)(1)), "[1, [2, 3]]", "methodcaller with a function" ); |
| 431 | |
| 432 | var f1 = function (x) { return [1, x]; }; |
| 433 | var f2 = function (x) { return [2, x]; }; |
| 434 | var f3 = function (x) { return [3, x]; }; |
| 435 | t.is( repr(f1(f2(f3(4)))), "[1, [2, [3, 4]]]", "test the compose test" ); |
| 436 | t.is( repr(compose(f1,f2,f3)(4)), "[1, [2, [3, 4]]]", "three fn composition works" ); |
| 437 | t.is( repr(compose(compose(f1,f2),f3)(4)), "[1, [2, [3, 4]]]", "associative left" ); |
| 438 | t.is( repr(compose(f1,compose(f2,f3))(4)), "[1, [2, [3, 4]]]", "associative right" ); |
| 439 | |
| 440 | try { |
| 441 | compose(f1, "foo"); |
| 442 | t.ok( false, "wrong compose argument not raised!" ); |
| 443 | } catch (e) { |
| 444 | t.is( e.name, 'TypeError', "wrong compose argument raised correctly" ); |
| 445 | } |
| 446 | |
| 447 | t.is(camelize('one'), 'one', 'one word'); |
| 448 | t.is(camelize('one-two'), 'oneTwo', 'two words'); |
| 449 | t.is(camelize('one-two-three'), 'oneTwoThree', 'three words'); |
| 450 | t.is(camelize('1-one'), '1One', 'letter and word'); |
| 451 | t.is(camelize('one-'), 'one', 'trailing hyphen'); |
| 452 | t.is(camelize('-one'), 'One', 'starting hyphen'); |
| 453 | t.is(camelize('o-two'), 'oTwo', 'one character and word'); |
| 454 | |
| 455 | var flat = flattenArray([1, "2", 3, [4, [5, [6, 7], 8, [], 9]]]); |
| 456 | var expect = [1, "2", 3, 4, 5, 6, 7, 8, 9]; |
| 457 | t.is( repr(flat), repr(expect), "flattenArray" ); |
| 458 | |
| 459 | /* mean */ |
| 460 | try { |
| 461 | mean(); |
| 462 | t.ok( false, "no arguments didn't raise!" ); |
| 463 | } catch (e) { |
| 464 | t.is( e.name, 'TypeError', "no arguments raised correctly" ); |
| 465 | } |
| 466 | t.is( mean(1), 1, 'single argument (arg list)'); |
| 467 | t.is( mean([1]), 1, 'single argument (array)'); |
| 468 | t.is( mean(1,2,3), 2, 'three arguments (arg list)'); |
| 469 | t.is( mean([1,2,3]), 2, 'three arguments (array)'); |
| 470 | t.is( average(1), 1, 'test the average alias'); |
| 471 | |
| 472 | /* median */ |
| 473 | try { |
| 474 | median(); |
| 475 | t.ok( false, "no arguments didn't raise!" ); |
| 476 | } catch (e) { |
| 477 | t.is( e.name, 'TypeError', "no arguments raised correctly" ); |
| 478 | } |
| 479 | t.is( median(1), 1, 'single argument (arg list)'); |
| 480 | t.is( median([1]), 1, 'single argument (array)'); |
| 481 | t.is( median(3,1,2), 2, 'three arguments (arg list)'); |
| 482 | t.is( median([3,1,2]), 2, 'three arguments (array)'); |
| 483 | t.is( median(3,1,2,4), 2.5, 'four arguments (arg list)'); |
| 484 | t.is( median([3,1,2,4]), 2.5, 'four arguments (array)'); |
| 485 | |
| 486 | /* #185 */ |
| 487 | t.is( serializeJSON(parseQueryString("")), "{}", "parseQueryString('')" ); |
| 488 | t.is( serializeJSON(parseQueryString("", true)), "{}", "parseQueryString('', true)" ); |
| 489 | |
| 490 | /* #109 */ |
| 491 | t.is( queryString({ids: [1,2,3]}), "ids=1&ids=2&ids=3", "queryString array value" ); |
| 492 | t.is( queryString({ids: "123"}), "ids=123", "queryString string value" ); |
| 493 | |
| 494 | /* test values */ |
| 495 | var o = {a: 1, b: 2, c: 4, d: -1}; |
| 496 | var got = values(o); |
| 497 | got.sort(); |
| 498 | t.is( repr(got), repr([-1, 1, 2, 4]), "values()" ); |
| 499 | |
| 500 | t.is( queryString([["foo", "bar"], ["baz", "wibble"]]), "foo=baz&bar=wibble" ); |
| 501 | o = parseQueryString("foo=1=1=1&bar=2&baz&wibble="); |
| 502 | t.is( o.foo, "1=1=1", "parseQueryString multiple = first" ); |
| 503 | t.is( o.bar, "2", "parseQueryString multiple = second" ); |
| 504 | t.is( o.baz, "", "parseQueryString multiple = third" ); |
| 505 | t.is( o.wibble, "", "parseQueryString multiple = fourth" ); |
| 506 | |
| 507 | }; |