4 test("Primitive types and constants", function () {
5 equal(QUnit.equiv(null, null), true, "null");
6 equal(QUnit.equiv(null, {}), false, "null");
7 equal(QUnit.equiv(null, undefined), false, "null");
8 equal(QUnit.equiv(null, 0), false, "null");
9 equal(QUnit.equiv(null, false), false, "null");
10 equal(QUnit.equiv(null, ''), false, "null");
11 equal(QUnit.equiv(null, []), false, "null");
13 equal(QUnit.equiv(undefined, undefined), true, "undefined");
14 equal(QUnit.equiv(undefined, null), false, "undefined");
15 equal(QUnit.equiv(undefined, 0), false, "undefined");
16 equal(QUnit.equiv(undefined, false), false, "undefined");
17 equal(QUnit.equiv(undefined, {}), false, "undefined");
18 equal(QUnit.equiv(undefined, []), false, "undefined");
19 equal(QUnit.equiv(undefined, ""), false, "undefined");
21 // Nan usually doest not equal to Nan using the '==' operator.
22 // Only isNaN() is able to do it.
23 equal(QUnit.equiv(0/0, 0/0), true, "NaN"); // NaN VS NaN
24 equal(QUnit.equiv(1/0, 2/0), true, "Infinity"); // Infinity VS Infinity
25 equal(QUnit.equiv(-1/0, 2/0), false, "-Infinity, Infinity"); // -Infinity VS Infinity
26 equal(QUnit.equiv(-1/0, -2/0), true, "-Infinity, -Infinity"); // -Infinity VS -Infinity
27 equal(QUnit.equiv(0/0, 1/0), false, "NaN, Infinity"); // Nan VS Infinity
28 equal(QUnit.equiv(1/0, 0/0), false, "NaN, Infinity"); // Nan VS Infinity
29 equal(QUnit.equiv(0/0, null), false, "NaN");
30 equal(QUnit.equiv(0/0, undefined), false, "NaN");
31 equal(QUnit.equiv(0/0, 0), false, "NaN");
32 equal(QUnit.equiv(0/0, false), false, "NaN");
33 equal(QUnit.equiv(0/0, function () {}), false, "NaN");
34 equal(QUnit.equiv(1/0, null), false, "NaN, Infinity");
35 equal(QUnit.equiv(1/0, undefined), false, "NaN, Infinity");
36 equal(QUnit.equiv(1/0, 0), false, "NaN, Infinity");
37 equal(QUnit.equiv(1/0, 1), false, "NaN, Infinity");
38 equal(QUnit.equiv(1/0, false), false, "NaN, Infinity");
39 equal(QUnit.equiv(1/0, true), false, "NaN, Infinity");
40 equal(QUnit.equiv(1/0, function () {}), false, "NaN, Infinity");
42 equal(QUnit.equiv(0, 0), true, "number");
43 equal(QUnit.equiv(0, 1), false, "number");
44 equal(QUnit.equiv(1, 0), false, "number");
45 equal(QUnit.equiv(1, 1), true, "number");
46 equal(QUnit.equiv(1.1, 1.1), true, "number");
47 equal(QUnit.equiv(0.0000005, 0.0000005), true, "number");
48 equal(QUnit.equiv(0, ''), false, "number");
49 equal(QUnit.equiv(0, '0'), false, "number");
50 equal(QUnit.equiv(1, '1'), false, "number");
51 equal(QUnit.equiv(0, false), false, "number");
52 equal(QUnit.equiv(1, true), false, "number");
54 equal(QUnit.equiv(true, true), true, "boolean");
55 equal(QUnit.equiv(true, false), false, "boolean");
56 equal(QUnit.equiv(false, true), false, "boolean");
57 equal(QUnit.equiv(false, 0), false, "boolean");
58 equal(QUnit.equiv(false, null), false, "boolean");
59 equal(QUnit.equiv(false, undefined), false, "boolean");
60 equal(QUnit.equiv(true, 1), false, "boolean");
61 equal(QUnit.equiv(true, null), false, "boolean");
62 equal(QUnit.equiv(true, undefined), false, "boolean");
64 equal(QUnit.equiv('', ''), true, "string");
65 equal(QUnit.equiv('a', 'a'), true, "string");
66 equal(QUnit.equiv("foobar", "foobar"), true, "string");
67 equal(QUnit.equiv("foobar", "foo"), false, "string");
68 equal(QUnit.equiv('', 0), false, "string");
69 equal(QUnit.equiv('', false), false, "string");
70 equal(QUnit.equiv('', null), false, "string");
71 equal(QUnit.equiv('', undefined), false, "string");
73 // Rename for lint validation.
74 // We know this is bad, we are asserting whether we can coop with bad code like this.
75 var SafeNumber = Number, SafeString = String, SafeBoolean = Boolean, SafeObject = Object;
77 // primitives vs. objects
79 equal(QUnit.equiv(0, new SafeNumber()), true, "primitives vs. objects");
80 equal(QUnit.equiv(new SafeNumber(), 0), true, "primitives vs. objects");
81 equal(QUnit.equiv(1, new SafeNumber(1)), true, "primitives vs. objects");
82 equal(QUnit.equiv(new SafeNumber(1), 1), true, "primitives vs. objects");
83 equal(QUnit.equiv(new SafeNumber(0), 1), false, "primitives vs. objects");
84 equal(QUnit.equiv(0, new SafeNumber(1)), false, "primitives vs. objects");
86 equal(QUnit.equiv(new SafeString(), ""), true, "primitives vs. objects");
87 equal(QUnit.equiv("", new SafeString()), true, "primitives vs. objects");
88 equal(QUnit.equiv(new SafeString("My String"), "My String"), true, "primitives vs. objects");
89 equal(QUnit.equiv("My String", new SafeString("My String")), true, "primitives vs. objects");
90 equal(QUnit.equiv("Bad String", new SafeString("My String")), false, "primitives vs. objects");
91 equal(QUnit.equiv(new SafeString("Bad String"), "My String"), false, "primitives vs. objects");
93 equal(QUnit.equiv(false, new SafeBoolean()), true, "primitives vs. objects");
94 equal(QUnit.equiv(new SafeBoolean(), false), true, "primitives vs. objects");
95 equal(QUnit.equiv(true, new SafeBoolean(true)), true, "primitives vs. objects");
96 equal(QUnit.equiv(new SafeBoolean(true), true), true, "primitives vs. objects");
97 equal(QUnit.equiv(true, new SafeBoolean(1)), true, "primitives vs. objects");
98 equal(QUnit.equiv(false, new SafeBoolean(false)), true, "primitives vs. objects");
99 equal(QUnit.equiv(new SafeBoolean(false), false), true, "primitives vs. objects");
100 equal(QUnit.equiv(false, new SafeBoolean(0)), true, "primitives vs. objects");
101 equal(QUnit.equiv(true, new SafeBoolean(false)), false, "primitives vs. objects");
102 equal(QUnit.equiv(new SafeBoolean(false), true), false, "primitives vs. objects");
104 equal(QUnit.equiv(new SafeObject(), {}), true, "object literal vs. instantiation");
105 equal(QUnit.equiv({}, new SafeObject()), true, "object literal vs. instantiation");
106 equal(QUnit.equiv(new SafeObject(), {a:1}), false, "object literal vs. instantiation");
107 equal(QUnit.equiv({a:1}, new SafeObject()), false, "object literal vs. instantiation");
108 equal(QUnit.equiv({a:undefined}, new SafeObject()), false, "object literal vs. instantiation");
109 equal(QUnit.equiv(new SafeObject(), {a:undefined}), false, "object literal vs. instantiation");
112 test("Objects Basics.", function() {
113 equal(QUnit.equiv({}, {}), true);
114 equal(QUnit.equiv({}, null), false);
115 equal(QUnit.equiv({}, undefined), false);
116 equal(QUnit.equiv({}, 0), false);
117 equal(QUnit.equiv({}, false), false);
119 // This test is a hard one, it is very important
121 // 1) They are of the same type "object"
122 // 2) [] instanceof Object is true
123 // 3) Their properties are the same (doesn't exists)
124 equal(QUnit.equiv({}, []), false);
126 equal(QUnit.equiv({a:1}, {a:1}), true);
127 equal(QUnit.equiv({a:1}, {a:"1"}), false);
128 equal(QUnit.equiv({a:[]}, {a:[]}), true);
129 equal(QUnit.equiv({a:{}}, {a:null}), false);
130 equal(QUnit.equiv({a:1}, {}), false);
131 equal(QUnit.equiv({}, {a:1}), false);
134 equal(QUnit.equiv({a:undefined}, {}), false);
135 equal(QUnit.equiv({}, {a:undefined}), false);
138 a: [{ bar: undefined }]
141 a: [{ bat: undefined }]
145 // Objects with no prototype, created via Object.create(null), are used e.g. as dictionaries.
146 // Being able to test equivalence against object literals is quite useful.
147 if (typeof Object.create === 'function') {
148 equal(QUnit.equiv(Object.create(null), {}), true, "empty object without prototype VS empty object");
150 var nonEmptyWithNoProto = Object.create(null);
151 nonEmptyWithNoProto.foo = "bar";
153 equal(QUnit.equiv(nonEmptyWithNoProto, { foo: "bar" }), true, "object without prototype VS object");
158 test("Arrays Basics.", function() {
160 equal(QUnit.equiv([], []), true);
162 // May be a hard one, can invoke a crash at execution.
163 // because their types are both "object" but null isn't
164 // like a true object, it doesn't have any property at all.
165 equal(QUnit.equiv([], null), false);
167 equal(QUnit.equiv([], undefined), false);
168 equal(QUnit.equiv([], false), false);
169 equal(QUnit.equiv([], 0), false);
170 equal(QUnit.equiv([], ""), false);
172 // May be a hard one, but less hard
173 // than {} with [] (note the order)
174 equal(QUnit.equiv([], {}), false);
176 equal(QUnit.equiv([null],[]), false);
177 equal(QUnit.equiv([undefined],[]), false);
178 equal(QUnit.equiv([],[null]), false);
179 equal(QUnit.equiv([],[undefined]), false);
180 equal(QUnit.equiv([null],[undefined]), false);
181 equal(QUnit.equiv([[]],[[]]), true);
182 equal(QUnit.equiv([[],[],[]],[[],[],[]]), true);
184 [[],[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]],
185 [[],[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]),
188 [[],[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]],
189 [[],[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]), // shorter
192 [[],[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[{}]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]],
193 [[],[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]), // deepest element not an array
196 // same multidimensional
198 [1,2,3,4,5,6,7,8,9, [
219 [1,2,3,4,5,6,7,8,9, [
240 true, "Multidimensional");
242 // different multidimensional
244 [1,2,3,4,5,6,7,8,9, [
265 [1,2,3,4,5,6,7,8,9, [
273 '1',2,3,4,[ // string instead of number
286 false, "Multidimensional");
288 // different multidimensional
290 [1,2,3,4,5,6,7,8,9, [
311 [1,2,3,4,5,6,7,8,9, [
317 2,3,[ // missing an element (4)
332 false, "Multidimensional");
335 test("Functions.", function() {
336 var f0 = function () {};
337 var f1 = function () {};
339 // f2 and f3 have the same code, formatted differently
340 var f2 = function () {var i = 0;};
341 var f3 = function () {
343 var i = 0 // this comment and no semicoma as difference
346 equal(QUnit.equiv(function() {}, function() {}), false, "Anonymous functions"); // exact source code
347 equal(QUnit.equiv(function() {}, function() {return true;}), false, "Anonymous functions");
349 equal(QUnit.equiv(f0, f0), true, "Function references"); // same references
350 equal(QUnit.equiv(f0, f1), false, "Function references"); // exact source code, different references
351 equal(QUnit.equiv(f2, f3), false, "Function references"); // equivalent source code, different references
352 equal(QUnit.equiv(f1, f2), false, "Function references"); // different source code, different references
353 equal(QUnit.equiv(function() {}, true), false);
354 equal(QUnit.equiv(function() {}, undefined), false);
355 equal(QUnit.equiv(function() {}, null), false);
356 equal(QUnit.equiv(function() {}, {}), false);
360 test("Date instances.", function() {
361 // Date, we don't need to test Date.parse() because it returns a number.
362 // Only test the Date instances by setting them a fix date.
363 // The date use is midnight January 1, 1970
366 d1.setTime(0); // fix the date
369 d2.setTime(0); // fix the date
371 var d3 = new Date(); // The very now
373 // Anyway their types differs, just in case the code fails in the order in which it deals with date
374 equal(QUnit.equiv(d1, 0), false); // d1.valueOf() returns 0, but d1 and 0 are different
375 // test same values date and different instances equality
376 equal(QUnit.equiv(d1, d2), true);
377 // test different date and different instances difference
378 equal(QUnit.equiv(d1, d3), false);
382 test("RegExp.", function() {
383 // Must test cases that imply those traps:
385 // a instanceof Object; // Oops
386 // a instanceof RegExp; // Oops
387 // typeof a === "function"; // Oops, false in IE and Opera, true in FF and Safari ("object")
389 // Tests same regex with same modifiers in different order
404 equal(QUnit.equiv(r5, r6), true, "Modifier order");
405 equal(QUnit.equiv(r5, r7), true, "Modifier order");
406 equal(QUnit.equiv(r5, r8), true, "Modifier order");
407 equal(QUnit.equiv(r5, r9), true, "Modifier order");
408 equal(QUnit.equiv(r5, r10), true, "Modifier order");
409 equal(QUnit.equiv(r, r5), false, "Modifier");
411 equal(QUnit.equiv(ri1, ri2), true, "Modifier");
412 equal(QUnit.equiv(r, ri1), false, "Modifier");
413 equal(QUnit.equiv(ri1, rm1), false, "Modifier");
414 equal(QUnit.equiv(r, rm1), false, "Modifier");
415 equal(QUnit.equiv(rm1, ri1), false, "Modifier");
416 equal(QUnit.equiv(rm1, rm2), true, "Modifier");
417 equal(QUnit.equiv(rg1, rm1), false, "Modifier");
418 equal(QUnit.equiv(rm1, rg1), false, "Modifier");
419 equal(QUnit.equiv(rg1, rg2), true, "Modifier");
421 // Different regex, same modifiers
423 var r13 = /[0-9]/gi; // oops! different
424 equal(QUnit.equiv(r11, r13), false, "Regex pattern");
427 var r15 = /"0"/ig; // oops! different
428 equal(QUnit.equiv(r14, r15), false, "Regex pattern");
430 var r1 = /[\n\r\u2028\u2029]/g;
431 var r2 = /[\n\r\u2028\u2029]/g;
432 var r3 = /[\n\r\u2028\u2028]/g; // differs from r1
433 var r4 = /[\n\r\u2028\u2029]/; // differs from r1
435 equal(QUnit.equiv(r1, r2), true, "Regex pattern");
436 equal(QUnit.equiv(r1, r3), false, "Regex pattern");
437 equal(QUnit.equiv(r1, r4), false, "Regex pattern");
439 // More complex regex
440 var regex1 = "^[-_.a-z0-9]+@([-_a-z0-9]+\\.)+([A-Za-z][A-Za-z]|[A-Za-z][A-Za-z][A-Za-z])|(([0-9][0-9]?|[0-1][0-9][0-9]|[2][0-4][0-9]|[2][5][0-5]))$";
441 var regex2 = "^[-_.a-z0-9]+@([-_a-z0-9]+\\.)+([A-Za-z][A-Za-z]|[A-Za-z][A-Za-z][A-Za-z])|(([0-9][0-9]?|[0-1][0-9][0-9]|[2][0-4][0-9]|[2][5][0-5]))$";
442 // regex 3 is different: '.' not escaped
443 var regex3 = "^[-_.a-z0-9]+@([-_a-z0-9]+.)+([A-Za-z][A-Za-z]|[A-Za-z][A-Za-z][A-Za-z])|(([0-9][0-9]?|[0-1][0-9][0-9]|[2][0-4][0-9]|[2][5][0-5]))$";
445 var r21 = new RegExp(regex1);
446 var r22 = new RegExp(regex2);
447 var r23 = new RegExp(regex3); // diff from r21, not same pattern
448 var r23a = new RegExp(regex3, "gi"); // diff from r23, not same modifier
449 var r24a = new RegExp(regex3, "ig"); // same as r23a
451 equal(QUnit.equiv(r21, r22), true, "Complex Regex");
452 equal(QUnit.equiv(r21, r23), false, "Complex Regex");
453 equal(QUnit.equiv(r23, r23a), false, "Complex Regex");
454 equal(QUnit.equiv(r23a, r24a), true, "Complex Regex");
456 // typeof r1 is "function" in some browsers and "object" in others so we must cover this test
458 equal(QUnit.equiv(re, function () {}), false, "Regex internal");
459 equal(QUnit.equiv(re, {}), false, "Regex internal");
463 test("Complex Objects.", function() {
472 // Try to invert the order of some properties to make sure it is covered.
473 // It can failed when properties are compared between unsorted arrays.
585 //r: "r", // different: missing a property
728 //t: undefined, // different: missing a property with an undefined value
836 q: {} // different was []
856 "string", null, 0, "1", 1, {
858 foo: [1,2,null,{}, [], [1,2,3]],
860 }, 3, "Hey!", "Κάνε πάντα γνωÏίζουμε ας των, μηχανής επιδιόÏθωσης επιδιοÏθώσεις ÏŽÏ‚ μια. Κλπ ας"
862 unicode: "è€ æ±‰è¯ä¸å˜åœ¨ 港澳和海外的åŽäººåœˆä¸ 贵州 我去了书店 现在尚有争",
869 "string", null, 0, "1", 1, {
871 foo: [1,2,null,{}, [], [1,2,3]],
873 }, 3, "Hey!", "Κάνε πάντα γνωÏίζουμε ας των, μηχανής επιδιόÏθωσης επιδιοÏθώσεις ÏŽÏ‚ μια. Κλπ ας"
875 unicode: "è€ æ±‰è¯ä¸å˜åœ¨ 港澳和海外的åŽäººåœˆä¸ 贵州 我去了书店 现在尚有争",
882 "string", null, 0, "1", 1, {
884 foo: [1,2,null,{}, [], [1,2,3,4]], // different: 4 was add to the array
886 }, 3, "Hey!", "Κάνε πάντα γνωÏίζουμε ας των, μηχανής επιδιόÏθωσης επιδιοÏθώσεις ÏŽÏ‚ μια. Κλπ ας"
888 unicode: "è€ æ±‰è¯ä¸å˜åœ¨ 港澳和海外的åŽäººåœˆä¸ 贵州 我去了书店 现在尚有争",
895 "string", null, 0, "1", 1, {
897 foo: [1,2,null,{}, [], [1,2,3]],
898 newprop: undefined, // different: newprop was added
900 }, 3, "Hey!", "Κάνε πάντα γνωÏίζουμε ας των, μηχανής επιδιόÏθωσης επιδιοÏθώσεις ÏŽÏ‚ μια. Κλπ ας"
902 unicode: "è€ æ±‰è¯ä¸å˜åœ¨ 港澳和海外的åŽäººåœˆä¸ 贵州 我去了书店 现在尚有争",
909 "string", null, 0, "1", 1, {
911 foo: [1,2,null,{}, [], [1,2,3]],
913 }, 3, "Hey!", "Κάνε πάντα γνωÏίζουμε ας των, μηχανής επιδιόÏθωσης επιδιοÏθώσεις ÏŽÏ‚ μια. Κλπ α" // different: missing last char
915 unicode: "è€ æ±‰è¯ä¸å˜åœ¨ 港澳和海外的åŽäººåœˆä¸ 贵州 我去了书店 现在尚有争",
922 "string", null, 0, "1", 1, {
924 foo: [1,2,undefined,{}, [], [1,2,3]], // different: undefined instead of null
926 }, 3, "Hey!", "Κάνε πάντα γνωÏίζουμε ας των, μηχανής επιδιόÏθωσης επιδιοÏθώσεις ÏŽÏ‚ μια. Κλπ ας"
928 unicode: "è€ æ±‰è¯ä¸å˜åœ¨ 港澳和海外的åŽäººåœˆä¸ 贵州 我去了书店 现在尚有争",
935 "string", null, 0, "1", 1, {
937 foo: [1,2,null,{}, [], [1,2,3]],
938 bat: undefined // different: property name not "bar"
939 }, 3, "Hey!", "Κάνε πάντα γνωÏίζουμε ας των, μηχανής επιδιόÏθωσης επιδιοÏθώσεις ÏŽÏ‚ μια. Κλπ ας"
941 unicode: "è€ æ±‰è¯ä¸å˜åœ¨ 港澳和海外的åŽäººåœˆä¸ 贵州 我去了书店 现在尚有争",
946 equal(QUnit.equiv(same1, same2), true);
947 equal(QUnit.equiv(same2, same1), true);
948 equal(QUnit.equiv(same2, diff1), false);
949 equal(QUnit.equiv(diff1, same2), false);
951 equal(QUnit.equiv(same1, diff1), false);
952 equal(QUnit.equiv(same1, diff2), false);
953 equal(QUnit.equiv(same1, diff3), false);
954 equal(QUnit.equiv(same1, diff3), false);
955 equal(QUnit.equiv(same1, diff4), false);
956 equal(QUnit.equiv(same1, diff5), false);
957 equal(QUnit.equiv(diff5, diff1), false);
961 test("Complex Arrays.", function() {
967 [1, 2, 3, true, {}, null, [
973 [1, 2, 3, true, {}, null, [
982 [1, 2, 3, true, {}, null, [
988 [1, 2, 3, true, {}, null, [
990 b: ["", '1', 0] // not same property name
999 "do": "reserved word",
1001 ar: [3,5,9,"hey!", [], {
1003 3,4,6,9, null, [], []
1010 }, 5, "string", 0, fn, false, null, undefined, 0, [
1011 4,5,6,7,8,9,11,22,33,44,55,"66", null, [], [[[[[3]]]], "3"], {}, 1/0
1012 ], [], [[[], "foo", null, {
1015 a: [3,4,5,6,"yep!", undefined, undefined],
1020 equal(QUnit.equiv(a,
1024 "do": "reserved word",
1026 ar: [3,5,9,"hey!", [], {
1028 3,4,6,9, null, [], []
1035 }, 5, "string", 0, fn, false, null, undefined, 0, [
1036 4,5,6,7,8,9,11,22,33,44,55,"66", null, [], [[[[[3]]]], "3"], {}, 1/0
1037 ], [], [[[], "foo", null, {
1040 a: [3,4,5,6,"yep!", undefined, undefined],
1045 equal(QUnit.equiv(a,
1049 "do": "reserved word",
1051 ar: [3,5,9,"hey!", [], {
1053 3,4,6,9, null, [], []
1060 }, 5, "string", 0, fn, false, null, undefined, 0, [
1061 4,5,6,7,8,9,11,22,33,44,55,"66", null, [], [[[[[2]]]], "3"], {}, 1/0 // different: [[[[[2]]]]] instead of [[[[[3]]]]]
1062 ], [], [[[], "foo", null, {
1065 a: [3,4,5,6,"yep!", undefined, undefined],
1070 equal(QUnit.equiv(a,
1074 "do": "reserved word",
1076 ar: [3,5,9,"hey!", [], {
1078 3,4,6,9, null, [], []
1085 }, 5, "string", 0, fn, false, null, undefined, 0, [
1086 4,5,6,7,8,9,11,22,33,44,55,"66", null, [], [[[[[3]]]], "3"], {}, 1/0
1087 ], [], [[[], "foo", null, {
1088 n: -1/0, // different, -Infinity instead of Infinity
1090 a: [3,4,5,6,"yep!", undefined, undefined],
1095 equal(QUnit.equiv(a,
1099 "do": "reserved word",
1101 ar: [3,5,9,"hey!", [], {
1103 3,4,6,9, null, [], []
1110 }, 5, "string", 0, fn, false, null, undefined, 0, [
1111 4,5,6,7,8,9,11,22,33,44,55,"66", null, [], [[[[[3]]]], "3"], {}, 1/0
1112 ], [], [[[], "foo", { // different: null is missing
1115 a: [3,4,5,6,"yep!", undefined, undefined],
1120 equal(QUnit.equiv(a,
1124 "do": "reserved word",
1126 ar: [3,5,9,"hey!", [], {
1128 3,4,6,9, null, [], []
1131 // different: missing property f: undefined
1135 }, 5, "string", 0, fn, false, null, undefined, 0, [
1136 4,5,6,7,8,9,11,22,33,44,55,"66", null, [], [[[[[3]]]], "3"], {}, 1/0
1137 ], [], [[[], "foo", null, {
1140 a: [3,4,5,6,"yep!", undefined, undefined],
1147 test("Prototypal inheritance", function() {
1148 function Gizmo(id) {
1152 function Hoozit(id) {
1155 Hoozit.prototype = new Gizmo();
1157 var gizmo = new Gizmo("ok");
1158 var hoozit = new Hoozit("ok");
1160 // Try this test many times after test on instances that hold function
1161 // to make sure that our code does not mess with last object constructor memoization.
1162 equal(QUnit.equiv(function () {}, function () {}), false);
1164 // Hoozit inherit from Gizmo
1165 // hoozit instanceof Hoozit; // true
1166 // hoozit instanceof Gizmo; // true
1167 equal(QUnit.equiv(hoozit, gizmo), true);
1169 Gizmo.prototype.bar = true; // not a function just in case we skip them
1171 // Hoozit inherit from Gizmo
1172 // They are equivalent
1173 equal(QUnit.equiv(hoozit, gizmo), true);
1175 // Make sure this is still true !important
1176 // The reason for this is that I forgot to reset the last
1177 // caller to where it were called from.
1178 equal(QUnit.equiv(function () {}, function () {}), false);
1180 // Make sure this is still true !important
1181 equal(QUnit.equiv(hoozit, gizmo), true);
1183 Hoozit.prototype.foo = true; // not a function just in case we skip them
1185 // Gizmo does not inherit from Hoozit
1186 // gizmo instanceof Gizmo; // true
1187 // gizmo instanceof Hoozit; // false
1188 // They are not equivalent
1189 equal(QUnit.equiv(hoozit, gizmo), false);
1191 // Make sure this is still true !important
1192 equal(QUnit.equiv(function () {}, function () {}), false);
1196 test("Instances", function() {
1202 this.fn = function () {};
1207 equal(QUnit.equiv(a1, a2), true, "Same property, same constructor");
1209 // b1.fn and b2.fn are functions but they are different references
1210 // But we decided to skip function for instances.
1211 equal(QUnit.equiv(b1, b2), true, "Same property, same constructor");
1212 equal(QUnit.equiv(a1, b1), false, "Same properties but different constructor"); // failed
1214 function Car(year) {
1217 this.isOld = function() {
1222 function Human(year) {
1225 this.isOld = function() {
1230 var car = new Car(30);
1231 var carSame = new Car(30);
1232 var carDiff = new Car(10);
1233 var human = new Human(30);
1241 isOld: function () {}
1244 equal(QUnit.equiv(car, car), true);
1245 equal(QUnit.equiv(car, carDiff), false);
1246 equal(QUnit.equiv(car, carSame), true);
1247 equal(QUnit.equiv(car, human), false);
1251 test("Complex Instances Nesting (with function value in literals and/or in nested instances)", function() {
1261 this.fn1 = function () {};
1262 this.a = new A(function () {});
1265 function fnOutside() {
1269 function fnInside() {
1273 this.fn1 = function () {};
1274 this.fn2 = fnInside;
1277 b: fnOutside // ok make reference to a function in all instances scope
1281 // This function will be ignored.
1282 // Even if it is not visible for all instances (e.g. locked in a closures),
1283 // it is from a property that makes part of an instance (e.g. from the C constructor)
1284 this.b1 = new B(function () {});
1287 b2: new B(function() {})
1293 function fnInside() {
1297 this.fn1 = function () {};
1298 this.fn2 = fnInside;
1301 b: fnOutside, // ok make reference to a function in all instances scope
1303 // This function won't be ingored.
1304 // It isn't visible for all C insances
1305 // and it is not in a property of an instance. (in an Object instances e.g. the object literal)
1310 // This function will be ignored.
1311 // Even if it is not visible for all instances (e.g. locked in a closures),
1312 // it is from a property that makes part of an instance (e.g. from the C constructor)
1313 this.b1 = new B(function () {});
1316 b2: new B(function() {})
1322 function fnInside() {
1326 this.fn1 = function () {};
1327 this.fn2 = fnInside;
1330 b: fnOutside // ok make reference to a function in all instances scope
1334 // This function will be ignored.
1335 // Even if it is not visible for all instances (e.g. locked in a closures),
1336 // it is from a property that makes part of an instance (e.g. from the C constructor)
1337 this.b1 = new B(function () {});
1340 b1: new B({a: function() {}}),
1341 b2: new B(function() {})
1347 var a1 = new A(function () {});
1348 var a2 = new A(function () {});
1349 equal(QUnit.equiv(a1, a2), true);
1351 equal(QUnit.equiv(a1, a2), true); // different instances
1353 var b1 = new B(function () {});
1354 var b2 = new B(function () {});
1355 equal(QUnit.equiv(b1, b2), true);
1357 var c1 = new C(function () {});
1358 var c2 = new C(function () {});
1359 equal(QUnit.equiv(c1, c2), true);
1361 var d1 = new D(function () {});
1362 var d2 = new D(function () {});
1363 equal(QUnit.equiv(d1, d2), false);
1365 var e1 = new E(function () {});
1366 var e2 = new E(function () {});
1367 equal(QUnit.equiv(e1, e2), false);
1372 test('object with references to self wont loop', function() {
1378 circularA.abc = circularA;
1379 circularB.abc = circularB;
1380 equal(QUnit.equiv(circularA, circularB), true, "Should not repeat test on object (ambigous test)");
1384 equal(QUnit.equiv(circularA, circularB), true, "Should not repeat test on object (ambigous test)");
1388 equal(QUnit.equiv(circularA, circularB), false, "Should not repeat test on object (unambigous test)");
1391 test('array with references to self wont loop', function() {
1394 circularA.push(circularA);
1395 circularB.push(circularB);
1396 equal(QUnit.equiv(circularA, circularB), true, "Should not repeat test on array (ambigous test)");
1398 circularA.push( 'abc' );
1399 circularB.push( 'abc' );
1400 equal(QUnit.equiv(circularA, circularB), true, "Should not repeat test on array (ambigous test)");
1402 circularA.push( 'hello' );
1403 circularB.push( 'goodbye' );
1404 equal(QUnit.equiv(circularA, circularB), false, "Should not repeat test on array (unambigous test)");
1407 test('mixed object/array with references to self wont loop', function() {
1408 var circularA = [{abc:null}],
1409 circularB = [{abc:null}];
1410 circularA[0].abc = circularA;
1411 circularB[0].abc = circularB;
1413 circularA.push(circularA);
1414 circularB.push(circularB);
1415 equal(QUnit.equiv(circularA, circularB), true, "Should not repeat test on object/array (ambigous test)");
1417 circularA[0].def = 1;
1418 circularB[0].def = 1;
1419 equal(QUnit.equiv(circularA, circularB), true, "Should not repeat test on object/array (ambigous test)");
1421 circularA[0].def = 1;
1422 circularB[0].def = 0;
1423 equal(QUnit.equiv(circularA, circularB), false, "Should not repeat test on object/array (unambigous test)");
1426 test("Test that must be done at the end because they extend some primitive's prototype", function() {
1427 // Try that a function looks like our regular expression.
1428 // This tests if we check that a and b are really both instance of RegExp
1429 Function.prototype.global = true;
1430 Function.prototype.multiline = true;
1431 Function.prototype.ignoreCase = false;
1432 Function.prototype.source = "my regex";
1433 var re = /my regex/gm;
1434 equal(QUnit.equiv(re, function () {}), false, "A function that looks that a regex isn't a regex");
1435 // This test will ensures it works in both ways, and ALSO especially that we can make differences
1436 // between RegExp and Function constructor because typeof on a RegExpt instance is "function"
1437 equal(QUnit.equiv(function () {}, re), false, "Same conversely, but ensures that function and regexp are distinct because their constructor are different");