same.js 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421
  1. module("equiv");
  2. test("Primitive types and constants", function () {
  3. equals(QUnit.equiv(null, null), true, "null");
  4. equals(QUnit.equiv(null, {}), false, "null");
  5. equals(QUnit.equiv(null, undefined), false, "null");
  6. equals(QUnit.equiv(null, 0), false, "null");
  7. equals(QUnit.equiv(null, false), false, "null");
  8. equals(QUnit.equiv(null, ''), false, "null");
  9. equals(QUnit.equiv(null, []), false, "null");
  10. equals(QUnit.equiv(undefined, undefined), true, "undefined");
  11. equals(QUnit.equiv(undefined, null), false, "undefined");
  12. equals(QUnit.equiv(undefined, 0), false, "undefined");
  13. equals(QUnit.equiv(undefined, false), false, "undefined");
  14. equals(QUnit.equiv(undefined, {}), false, "undefined");
  15. equals(QUnit.equiv(undefined, []), false, "undefined");
  16. equals(QUnit.equiv(undefined, ""), false, "undefined");
  17. // Nan usually doest not equal to Nan using the '==' operator.
  18. // Only isNaN() is able to do it.
  19. equals(QUnit.equiv(0/0, 0/0), true, "NaN"); // NaN VS NaN
  20. equals(QUnit.equiv(1/0, 2/0), true, "Infinity"); // Infinity VS Infinity
  21. equals(QUnit.equiv(-1/0, 2/0), false, "-Infinity, Infinity"); // -Infinity VS Infinity
  22. equals(QUnit.equiv(-1/0, -2/0), true, "-Infinity, -Infinity"); // -Infinity VS -Infinity
  23. equals(QUnit.equiv(0/0, 1/0), false, "NaN, Infinity"); // Nan VS Infinity
  24. equals(QUnit.equiv(1/0, 0/0), false, "NaN, Infinity"); // Nan VS Infinity
  25. equals(QUnit.equiv(0/0, null), false, "NaN");
  26. equals(QUnit.equiv(0/0, undefined), false, "NaN");
  27. equals(QUnit.equiv(0/0, 0), false, "NaN");
  28. equals(QUnit.equiv(0/0, false), false, "NaN");
  29. equals(QUnit.equiv(0/0, function () {}), false, "NaN");
  30. equals(QUnit.equiv(1/0, null), false, "NaN, Infinity");
  31. equals(QUnit.equiv(1/0, undefined), false, "NaN, Infinity");
  32. equals(QUnit.equiv(1/0, 0), false, "NaN, Infinity");
  33. equals(QUnit.equiv(1/0, 1), false, "NaN, Infinity");
  34. equals(QUnit.equiv(1/0, false), false, "NaN, Infinity");
  35. equals(QUnit.equiv(1/0, true), false, "NaN, Infinity");
  36. equals(QUnit.equiv(1/0, function () {}), false, "NaN, Infinity");
  37. equals(QUnit.equiv(0, 0), true, "number");
  38. equals(QUnit.equiv(0, 1), false, "number");
  39. equals(QUnit.equiv(1, 0), false, "number");
  40. equals(QUnit.equiv(1, 1), true, "number");
  41. equals(QUnit.equiv(1.1, 1.1), true, "number");
  42. equals(QUnit.equiv(0.0000005, 0.0000005), true, "number");
  43. equals(QUnit.equiv(0, ''), false, "number");
  44. equals(QUnit.equiv(0, '0'), false, "number");
  45. equals(QUnit.equiv(1, '1'), false, "number");
  46. equals(QUnit.equiv(0, false), false, "number");
  47. equals(QUnit.equiv(1, true), false, "number");
  48. equals(QUnit.equiv(true, true), true, "boolean");
  49. equals(QUnit.equiv(true, false), false, "boolean");
  50. equals(QUnit.equiv(false, true), false, "boolean");
  51. equals(QUnit.equiv(false, 0), false, "boolean");
  52. equals(QUnit.equiv(false, null), false, "boolean");
  53. equals(QUnit.equiv(false, undefined), false, "boolean");
  54. equals(QUnit.equiv(true, 1), false, "boolean");
  55. equals(QUnit.equiv(true, null), false, "boolean");
  56. equals(QUnit.equiv(true, undefined), false, "boolean");
  57. equals(QUnit.equiv('', ''), true, "string");
  58. equals(QUnit.equiv('a', 'a'), true, "string");
  59. equals(QUnit.equiv("foobar", "foobar"), true, "string");
  60. equals(QUnit.equiv("foobar", "foo"), false, "string");
  61. equals(QUnit.equiv('', 0), false, "string");
  62. equals(QUnit.equiv('', false), false, "string");
  63. equals(QUnit.equiv('', null), false, "string");
  64. equals(QUnit.equiv('', undefined), false, "string");
  65. // Short annotation VS new annotation
  66. equals(QUnit.equiv(0, new Number()), true, "short annotation VS new annotation");
  67. equals(QUnit.equiv(new Number(), 0), true, "short annotation VS new annotation");
  68. equals(QUnit.equiv(1, new Number(1)), true, "short annotation VS new annotation");
  69. equals(QUnit.equiv(new Number(1), 1), true, "short annotation VS new annotation");
  70. equals(QUnit.equiv(new Number(0), 1), false, "short annotation VS new annotation");
  71. equals(QUnit.equiv(0, new Number(1)), false, "short annotation VS new annotation");
  72. equals(QUnit.equiv(new String(), ""), true, "short annotation VS new annotation");
  73. equals(QUnit.equiv("", new String()), true, "short annotation VS new annotation");
  74. equals(QUnit.equiv(new String("My String"), "My String"), true, "short annotation VS new annotation");
  75. equals(QUnit.equiv("My String", new String("My String")), true, "short annotation VS new annotation");
  76. equals(QUnit.equiv("Bad String", new String("My String")), false, "short annotation VS new annotation");
  77. equals(QUnit.equiv(new String("Bad String"), "My String"), false, "short annotation VS new annotation");
  78. equals(QUnit.equiv(false, new Boolean()), true, "short annotation VS new annotation");
  79. equals(QUnit.equiv(new Boolean(), false), true, "short annotation VS new annotation");
  80. equals(QUnit.equiv(true, new Boolean(true)), true, "short annotation VS new annotation");
  81. equals(QUnit.equiv(new Boolean(true), true), true, "short annotation VS new annotation");
  82. equals(QUnit.equiv(true, new Boolean(1)), true, "short annotation VS new annotation");
  83. equals(QUnit.equiv(false, new Boolean(false)), true, "short annotation VS new annotation");
  84. equals(QUnit.equiv(new Boolean(false), false), true, "short annotation VS new annotation");
  85. equals(QUnit.equiv(false, new Boolean(0)), true, "short annotation VS new annotation");
  86. equals(QUnit.equiv(true, new Boolean(false)), false, "short annotation VS new annotation");
  87. equals(QUnit.equiv(new Boolean(false), true), false, "short annotation VS new annotation");
  88. equals(QUnit.equiv(new Object(), {}), true, "short annotation VS new annotation");
  89. equals(QUnit.equiv({}, new Object()), true, "short annotation VS new annotation");
  90. equals(QUnit.equiv(new Object(), {a:1}), false, "short annotation VS new annotation");
  91. equals(QUnit.equiv({a:1}, new Object()), false, "short annotation VS new annotation");
  92. equals(QUnit.equiv({a:undefined}, new Object()), false, "short annotation VS new annotation");
  93. equals(QUnit.equiv(new Object(), {a:undefined}), false, "short annotation VS new annotation");
  94. });
  95. test("Objects Basics.", function() {
  96. equals(QUnit.equiv({}, {}), true);
  97. equals(QUnit.equiv({}, null), false);
  98. equals(QUnit.equiv({}, undefined), false);
  99. equals(QUnit.equiv({}, 0), false);
  100. equals(QUnit.equiv({}, false), false);
  101. // This test is a hard one, it is very important
  102. // REASONS:
  103. // 1) They are of the same type "object"
  104. // 2) [] instanceof Object is true
  105. // 3) Their properties are the same (doesn't exists)
  106. equals(QUnit.equiv({}, []), false);
  107. equals(QUnit.equiv({a:1}, {a:1}), true);
  108. equals(QUnit.equiv({a:1}, {a:"1"}), false);
  109. equals(QUnit.equiv({a:[]}, {a:[]}), true);
  110. equals(QUnit.equiv({a:{}}, {a:null}), false);
  111. equals(QUnit.equiv({a:1}, {}), false);
  112. equals(QUnit.equiv({}, {a:1}), false);
  113. // Hard ones
  114. equals(QUnit.equiv({a:undefined}, {}), false);
  115. equals(QUnit.equiv({}, {a:undefined}), false);
  116. equals(QUnit.equiv(
  117. {
  118. a: [{ bar: undefined }]
  119. },
  120. {
  121. a: [{ bat: undefined }]
  122. }
  123. ), false);
  124. });
  125. test("Arrays Basics.", function() {
  126. equals(QUnit.equiv([], []), true);
  127. // May be a hard one, can invoke a crash at execution.
  128. // because their types are both "object" but null isn't
  129. // like a true object, it doesn't have any property at all.
  130. equals(QUnit.equiv([], null), false);
  131. equals(QUnit.equiv([], undefined), false);
  132. equals(QUnit.equiv([], false), false);
  133. equals(QUnit.equiv([], 0), false);
  134. equals(QUnit.equiv([], ""), false);
  135. // May be a hard one, but less hard
  136. // than {} with [] (note the order)
  137. equals(QUnit.equiv([], {}), false);
  138. equals(QUnit.equiv([null],[]), false);
  139. equals(QUnit.equiv([undefined],[]), false);
  140. equals(QUnit.equiv([],[null]), false);
  141. equals(QUnit.equiv([],[undefined]), false);
  142. equals(QUnit.equiv([null],[undefined]), false);
  143. equals(QUnit.equiv([[]],[[]]), true);
  144. equals(QUnit.equiv([[],[],[]],[[],[],[]]), true);
  145. equals(QUnit.equiv(
  146. [[],[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]],
  147. [[],[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]),
  148. true);
  149. equals(QUnit.equiv(
  150. [[],[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]],
  151. [[],[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]), // shorter
  152. false);
  153. equals(QUnit.equiv(
  154. [[],[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[{}]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]],
  155. [[],[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]), // deepest element not an array
  156. false);
  157. // same multidimensional
  158. equals(QUnit.equiv(
  159. [1,2,3,4,5,6,7,8,9, [
  160. 1,2,3,4,5,6,7,8,9, [
  161. 1,2,3,4,5,[
  162. [6,7,8,9, [
  163. [
  164. 1,2,3,4,[
  165. 2,3,4,[
  166. 1,2,[
  167. 1,2,3,4,[
  168. 1,2,3,4,5,6,7,8,9,[
  169. 0
  170. ],1,2,3,4,5,6,7,8,9
  171. ],5,6,7,8,9
  172. ],4,5,6,7,8,9
  173. ],5,6,7,8,9
  174. ],5,6,7
  175. ]
  176. ]
  177. ]
  178. ]
  179. ]]],
  180. [1,2,3,4,5,6,7,8,9, [
  181. 1,2,3,4,5,6,7,8,9, [
  182. 1,2,3,4,5,[
  183. [6,7,8,9, [
  184. [
  185. 1,2,3,4,[
  186. 2,3,4,[
  187. 1,2,[
  188. 1,2,3,4,[
  189. 1,2,3,4,5,6,7,8,9,[
  190. 0
  191. ],1,2,3,4,5,6,7,8,9
  192. ],5,6,7,8,9
  193. ],4,5,6,7,8,9
  194. ],5,6,7,8,9
  195. ],5,6,7
  196. ]
  197. ]
  198. ]
  199. ]
  200. ]]]),
  201. true, "Multidimensional");
  202. // different multidimensional
  203. equals(QUnit.equiv(
  204. [1,2,3,4,5,6,7,8,9, [
  205. 1,2,3,4,5,6,7,8,9, [
  206. 1,2,3,4,5,[
  207. [6,7,8,9, [
  208. [
  209. 1,2,3,4,[
  210. 2,3,4,[
  211. 1,2,[
  212. 1,2,3,4,[
  213. 1,2,3,4,5,6,7,8,9,[
  214. 0
  215. ],1,2,3,4,5,6,7,8,9
  216. ],5,6,7,8,9
  217. ],4,5,6,7,8,9
  218. ],5,6,7,8,9
  219. ],5,6,7
  220. ]
  221. ]
  222. ]
  223. ]
  224. ]]],
  225. [1,2,3,4,5,6,7,8,9, [
  226. 1,2,3,4,5,6,7,8,9, [
  227. 1,2,3,4,5,[
  228. [6,7,8,9, [
  229. [
  230. 1,2,3,4,[
  231. 2,3,4,[
  232. 1,2,[
  233. '1',2,3,4,[ // string instead of number
  234. 1,2,3,4,5,6,7,8,9,[
  235. 0
  236. ],1,2,3,4,5,6,7,8,9
  237. ],5,6,7,8,9
  238. ],4,5,6,7,8,9
  239. ],5,6,7,8,9
  240. ],5,6,7
  241. ]
  242. ]
  243. ]
  244. ]
  245. ]]]),
  246. false, "Multidimensional");
  247. // different multidimensional
  248. equals(QUnit.equiv(
  249. [1,2,3,4,5,6,7,8,9, [
  250. 1,2,3,4,5,6,7,8,9, [
  251. 1,2,3,4,5,[
  252. [6,7,8,9, [
  253. [
  254. 1,2,3,4,[
  255. 2,3,4,[
  256. 1,2,[
  257. 1,2,3,4,[
  258. 1,2,3,4,5,6,7,8,9,[
  259. 0
  260. ],1,2,3,4,5,6,7,8,9
  261. ],5,6,7,8,9
  262. ],4,5,6,7,8,9
  263. ],5,6,7,8,9
  264. ],5,6,7
  265. ]
  266. ]
  267. ]
  268. ]
  269. ]]],
  270. [1,2,3,4,5,6,7,8,9, [
  271. 1,2,3,4,5,6,7,8,9, [
  272. 1,2,3,4,5,[
  273. [6,7,8,9, [
  274. [
  275. 1,2,3,4,[
  276. 2,3,[ // missing an element (4)
  277. 1,2,[
  278. 1,2,3,4,[
  279. 1,2,3,4,5,6,7,8,9,[
  280. 0
  281. ],1,2,3,4,5,6,7,8,9
  282. ],5,6,7,8,9
  283. ],4,5,6,7,8,9
  284. ],5,6,7,8,9
  285. ],5,6,7
  286. ]
  287. ]
  288. ]
  289. ]
  290. ]]]),
  291. false, "Multidimensional");
  292. });
  293. test("Functions.", function() {
  294. var f0 = function () {};
  295. var f1 = function () {};
  296. // f2 and f3 have the same code, formatted differently
  297. var f2 = function () {var i = 0;};
  298. var f3 = function () {
  299. var i = 0 // this comment and no semicoma as difference
  300. };
  301. equals(QUnit.equiv(function() {}, function() {}), false, "Anonymous functions"); // exact source code
  302. equals(QUnit.equiv(function() {}, function() {return true;}), false, "Anonymous functions");
  303. equals(QUnit.equiv(f0, f0), true, "Function references"); // same references
  304. equals(QUnit.equiv(f0, f1), false, "Function references"); // exact source code, different references
  305. equals(QUnit.equiv(f2, f3), false, "Function references"); // equivalent source code, different references
  306. equals(QUnit.equiv(f1, f2), false, "Function references"); // different source code, different references
  307. equals(QUnit.equiv(function() {}, true), false);
  308. equals(QUnit.equiv(function() {}, undefined), false);
  309. equals(QUnit.equiv(function() {}, null), false);
  310. equals(QUnit.equiv(function() {}, {}), false);
  311. });
  312. test("Date instances.", function() {
  313. // Date, we don't need to test Date.parse() because it returns a number.
  314. // Only test the Date instances by setting them a fix date.
  315. // The date use is midnight January 1, 1970
  316. var d1 = new Date();
  317. d1.setTime(0); // fix the date
  318. var d2 = new Date();
  319. d2.setTime(0); // fix the date
  320. var d3 = new Date(); // The very now
  321. // Anyway their types differs, just in case the code fails in the order in which it deals with date
  322. equals(QUnit.equiv(d1, 0), false); // d1.valueOf() returns 0, but d1 and 0 are different
  323. // test same values date and different instances equality
  324. equals(QUnit.equiv(d1, d2), true);
  325. // test different date and different instances difference
  326. equals(QUnit.equiv(d1, d3), false);
  327. });
  328. test("RegExp.", function() {
  329. // Must test cases that imply those traps:
  330. // var a = /./;
  331. // a instanceof Object; // Oops
  332. // a instanceof RegExp; // Oops
  333. // typeof a === "function"; // Oops, false in IE and Opera, true in FF and Safari ("object")
  334. // Tests same regex with same modifiers in different order
  335. var r = /foo/;
  336. var r5 = /foo/gim;
  337. var r6 = /foo/gmi;
  338. var r7 = /foo/igm;
  339. var r8 = /foo/img;
  340. var r9 = /foo/mig;
  341. var r10 = /foo/mgi;
  342. var ri1 = /foo/i;
  343. var ri2 = /foo/i;
  344. var rm1 = /foo/m;
  345. var rm2 = /foo/m;
  346. var rg1 = /foo/g;
  347. var rg2 = /foo/g;
  348. equals(QUnit.equiv(r5, r6), true, "Modifier order");
  349. equals(QUnit.equiv(r5, r7), true, "Modifier order");
  350. equals(QUnit.equiv(r5, r8), true, "Modifier order");
  351. equals(QUnit.equiv(r5, r9), true, "Modifier order");
  352. equals(QUnit.equiv(r5, r10), true, "Modifier order");
  353. equals(QUnit.equiv(r, r5), false, "Modifier");
  354. equals(QUnit.equiv(ri1, ri2), true, "Modifier");
  355. equals(QUnit.equiv(r, ri1), false, "Modifier");
  356. equals(QUnit.equiv(ri1, rm1), false, "Modifier");
  357. equals(QUnit.equiv(r, rm1), false, "Modifier");
  358. equals(QUnit.equiv(rm1, ri1), false, "Modifier");
  359. equals(QUnit.equiv(rm1, rm2), true, "Modifier");
  360. equals(QUnit.equiv(rg1, rm1), false, "Modifier");
  361. equals(QUnit.equiv(rm1, rg1), false, "Modifier");
  362. equals(QUnit.equiv(rg1, rg2), true, "Modifier");
  363. // Different regex, same modifiers
  364. var r11 = /[a-z]/gi;
  365. var r13 = /[0-9]/gi; // oops! different
  366. equals(QUnit.equiv(r11, r13), false, "Regex pattern");
  367. var r14 = /0/ig;
  368. var r15 = /"0"/ig; // oops! different
  369. equals(QUnit.equiv(r14, r15), false, "Regex pattern");
  370. var r1 = /[\n\r\u2028\u2029]/g;
  371. var r2 = /[\n\r\u2028\u2029]/g;
  372. var r3 = /[\n\r\u2028\u2028]/g; // differs from r1
  373. var r4 = /[\n\r\u2028\u2029]/; // differs from r1
  374. equals(QUnit.equiv(r1, r2), true, "Regex pattern");
  375. equals(QUnit.equiv(r1, r3), false, "Regex pattern");
  376. equals(QUnit.equiv(r1, r4), false, "Regex pattern");
  377. // More complex regex
  378. 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]))$";
  379. 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]))$";
  380. // regex 3 is different: '.' not escaped
  381. 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]))$";
  382. var r21 = new RegExp(regex1);
  383. var r22 = new RegExp(regex2);
  384. var r23 = new RegExp(regex3); // diff from r21, not same pattern
  385. var r23a = new RegExp(regex3, "gi"); // diff from r23, not same modifier
  386. var r24a = new RegExp(regex3, "ig"); // same as r23a
  387. equals(QUnit.equiv(r21, r22), true, "Complex Regex");
  388. equals(QUnit.equiv(r21, r23), false, "Complex Regex");
  389. equals(QUnit.equiv(r23, r23a), false, "Complex Regex");
  390. equals(QUnit.equiv(r23a, r24a), true, "Complex Regex");
  391. // typeof r1 is "function" in some browsers and "object" in others so we must cover this test
  392. var re = / /;
  393. equals(QUnit.equiv(re, function () {}), false, "Regex internal");
  394. equals(QUnit.equiv(re, {}), false, "Regex internal");
  395. });
  396. test("Complex Objects.", function() {
  397. function fn1() {
  398. return "fn1";
  399. }
  400. function fn2() {
  401. return "fn2";
  402. }
  403. // Try to invert the order of some properties to make sure it is covered.
  404. // It can failed when properties are compared between unsorted arrays.
  405. equals(QUnit.equiv(
  406. {
  407. a: 1,
  408. b: null,
  409. c: [{}],
  410. d: {
  411. a: 3.14159,
  412. b: false,
  413. c: {
  414. e: fn1,
  415. f: [[[]]],
  416. g: {
  417. j: {
  418. k: {
  419. n: {
  420. r: "r",
  421. s: [1,2,3],
  422. t: undefined,
  423. u: 0,
  424. v: {
  425. w: {
  426. x: {
  427. y: "Yahoo!",
  428. z: null
  429. }
  430. }
  431. }
  432. },
  433. q: [],
  434. p: 1/0,
  435. o: 99
  436. },
  437. l: undefined,
  438. m: null
  439. }
  440. },
  441. d: 0,
  442. i: true,
  443. h: "false"
  444. }
  445. },
  446. e: undefined,
  447. g: "",
  448. h: "h",
  449. f: {},
  450. i: []
  451. },
  452. {
  453. a: 1,
  454. b: null,
  455. c: [{}],
  456. d: {
  457. b: false,
  458. a: 3.14159,
  459. c: {
  460. d: 0,
  461. e: fn1,
  462. f: [[[]]],
  463. g: {
  464. j: {
  465. k: {
  466. n: {
  467. r: "r",
  468. t: undefined,
  469. u: 0,
  470. s: [1,2,3],
  471. v: {
  472. w: {
  473. x: {
  474. z: null,
  475. y: "Yahoo!"
  476. }
  477. }
  478. }
  479. },
  480. o: 99,
  481. p: 1/0,
  482. q: []
  483. },
  484. l: undefined,
  485. m: null
  486. }
  487. },
  488. i: true,
  489. h: "false"
  490. }
  491. },
  492. e: undefined,
  493. g: "",
  494. f: {},
  495. h: "h",
  496. i: []
  497. }
  498. ), true);
  499. equals(QUnit.equiv(
  500. {
  501. a: 1,
  502. b: null,
  503. c: [{}],
  504. d: {
  505. a: 3.14159,
  506. b: false,
  507. c: {
  508. d: 0,
  509. e: fn1,
  510. f: [[[]]],
  511. g: {
  512. j: {
  513. k: {
  514. n: {
  515. //r: "r", // different: missing a property
  516. s: [1,2,3],
  517. t: undefined,
  518. u: 0,
  519. v: {
  520. w: {
  521. x: {
  522. y: "Yahoo!",
  523. z: null
  524. }
  525. }
  526. }
  527. },
  528. o: 99,
  529. p: 1/0,
  530. q: []
  531. },
  532. l: undefined,
  533. m: null
  534. }
  535. },
  536. h: "false",
  537. i: true
  538. }
  539. },
  540. e: undefined,
  541. f: {},
  542. g: "",
  543. h: "h",
  544. i: []
  545. },
  546. {
  547. a: 1,
  548. b: null,
  549. c: [{}],
  550. d: {
  551. a: 3.14159,
  552. b: false,
  553. c: {
  554. d: 0,
  555. e: fn1,
  556. f: [[[]]],
  557. g: {
  558. j: {
  559. k: {
  560. n: {
  561. r: "r",
  562. s: [1,2,3],
  563. t: undefined,
  564. u: 0,
  565. v: {
  566. w: {
  567. x: {
  568. y: "Yahoo!",
  569. z: null
  570. }
  571. }
  572. }
  573. },
  574. o: 99,
  575. p: 1/0,
  576. q: []
  577. },
  578. l: undefined,
  579. m: null
  580. }
  581. },
  582. h: "false",
  583. i: true
  584. }
  585. },
  586. e: undefined,
  587. f: {},
  588. g: "",
  589. h: "h",
  590. i: []
  591. }
  592. ), false);
  593. equals(QUnit.equiv(
  594. {
  595. a: 1,
  596. b: null,
  597. c: [{}],
  598. d: {
  599. a: 3.14159,
  600. b: false,
  601. c: {
  602. d: 0,
  603. e: fn1,
  604. f: [[[]]],
  605. g: {
  606. j: {
  607. k: {
  608. n: {
  609. r: "r",
  610. s: [1,2,3],
  611. t: undefined,
  612. u: 0,
  613. v: {
  614. w: {
  615. x: {
  616. y: "Yahoo!",
  617. z: null
  618. }
  619. }
  620. }
  621. },
  622. o: 99,
  623. p: 1/0,
  624. q: []
  625. },
  626. l: undefined,
  627. m: null
  628. }
  629. },
  630. h: "false",
  631. i: true
  632. }
  633. },
  634. e: undefined,
  635. f: {},
  636. g: "",
  637. h: "h",
  638. i: []
  639. },
  640. {
  641. a: 1,
  642. b: null,
  643. c: [{}],
  644. d: {
  645. a: 3.14159,
  646. b: false,
  647. c: {
  648. d: 0,
  649. e: fn1,
  650. f: [[[]]],
  651. g: {
  652. j: {
  653. k: {
  654. n: {
  655. r: "r",
  656. s: [1,2,3],
  657. //t: undefined, // different: missing a property with an undefined value
  658. u: 0,
  659. v: {
  660. w: {
  661. x: {
  662. y: "Yahoo!",
  663. z: null
  664. }
  665. }
  666. }
  667. },
  668. o: 99,
  669. p: 1/0,
  670. q: []
  671. },
  672. l: undefined,
  673. m: null
  674. }
  675. },
  676. h: "false",
  677. i: true
  678. }
  679. },
  680. e: undefined,
  681. f: {},
  682. g: "",
  683. h: "h",
  684. i: []
  685. }
  686. ), false);
  687. equals(QUnit.equiv(
  688. {
  689. a: 1,
  690. b: null,
  691. c: [{}],
  692. d: {
  693. a: 3.14159,
  694. b: false,
  695. c: {
  696. d: 0,
  697. e: fn1,
  698. f: [[[]]],
  699. g: {
  700. j: {
  701. k: {
  702. n: {
  703. r: "r",
  704. s: [1,2,3],
  705. t: undefined,
  706. u: 0,
  707. v: {
  708. w: {
  709. x: {
  710. y: "Yahoo!",
  711. z: null
  712. }
  713. }
  714. }
  715. },
  716. o: 99,
  717. p: 1/0,
  718. q: []
  719. },
  720. l: undefined,
  721. m: null
  722. }
  723. },
  724. h: "false",
  725. i: true
  726. }
  727. },
  728. e: undefined,
  729. f: {},
  730. g: "",
  731. h: "h",
  732. i: []
  733. },
  734. {
  735. a: 1,
  736. b: null,
  737. c: [{}],
  738. d: {
  739. a: 3.14159,
  740. b: false,
  741. c: {
  742. d: 0,
  743. e: fn1,
  744. f: [[[]]],
  745. g: {
  746. j: {
  747. k: {
  748. n: {
  749. r: "r",
  750. s: [1,2,3],
  751. t: undefined,
  752. u: 0,
  753. v: {
  754. w: {
  755. x: {
  756. y: "Yahoo!",
  757. z: null
  758. }
  759. }
  760. }
  761. },
  762. o: 99,
  763. p: 1/0,
  764. q: {} // different was []
  765. },
  766. l: undefined,
  767. m: null
  768. }
  769. },
  770. h: "false",
  771. i: true
  772. }
  773. },
  774. e: undefined,
  775. f: {},
  776. g: "",
  777. h: "h",
  778. i: []
  779. }
  780. ), false);
  781. var same1 = {
  782. a: [
  783. "string", null, 0, "1", 1, {
  784. prop: null,
  785. foo: [1,2,null,{}, [], [1,2,3]],
  786. bar: undefined
  787. }, 3, "Hey!", "Κάνε πάντα γνωρίζουμε ας των, μηχανής επιδιόρθωσης επιδιορθώσεις ώς μια. Κλπ ας"
  788. ],
  789. unicode: "老 汉语中存在 港澳和海外的华人圈中 贵州 我去了书店 现在尚有争",
  790. b: "b",
  791. c: fn1
  792. };
  793. var same2 = {
  794. a: [
  795. "string", null, 0, "1", 1, {
  796. prop: null,
  797. foo: [1,2,null,{}, [], [1,2,3]],
  798. bar: undefined
  799. }, 3, "Hey!", "Κάνε πάντα γνωρίζουμε ας των, μηχανής επιδιόρθωσης επιδιορθώσεις ώς μια. Κλπ ας"
  800. ],
  801. unicode: "老 汉语中存在 港澳和海外的华人圈中 贵州 我去了书店 现在尚有争",
  802. b: "b",
  803. c: fn1
  804. };
  805. var diff1 = {
  806. a: [
  807. "string", null, 0, "1", 1, {
  808. prop: null,
  809. foo: [1,2,null,{}, [], [1,2,3,4]], // different: 4 was add to the array
  810. bar: undefined
  811. }, 3, "Hey!", "Κάνε πάντα γνωρίζουμε ας των, μηχανής επιδιόρθωσης επιδιορθώσεις ώς μια. Κλπ ας"
  812. ],
  813. unicode: "老 汉语中存在 港澳和海外的华人圈中 贵州 我去了书店 现在尚有争",
  814. b: "b",
  815. c: fn1
  816. };
  817. var diff2 = {
  818. a: [
  819. "string", null, 0, "1", 1, {
  820. prop: null,
  821. foo: [1,2,null,{}, [], [1,2,3]],
  822. newprop: undefined, // different: newprop was added
  823. bar: undefined
  824. }, 3, "Hey!", "Κάνε πάντα γνωρίζουμε ας των, μηχανής επιδιόρθωσης επιδιορθώσεις ώς μια. Κλπ ας"
  825. ],
  826. unicode: "老 汉语中存在 港澳和海外的华人圈中 贵州 我去了书店 现在尚有争",
  827. b: "b",
  828. c: fn1
  829. };
  830. var diff3 = {
  831. a: [
  832. "string", null, 0, "1", 1, {
  833. prop: null,
  834. foo: [1,2,null,{}, [], [1,2,3]],
  835. bar: undefined
  836. }, 3, "Hey!", "Κάνε πάντα γνωρίζουμε ας των, μηχανής επιδιόρθωσης επιδιορθώσεις ώς μια. Κλπ α" // different: missing last char
  837. ],
  838. unicode: "老 汉语中存在 港澳和海外的华人圈中 贵州 我去了书店 现在尚有争",
  839. b: "b",
  840. c: fn1
  841. };
  842. var diff4 = {
  843. a: [
  844. "string", null, 0, "1", 1, {
  845. prop: null,
  846. foo: [1,2,undefined,{}, [], [1,2,3]], // different: undefined instead of null
  847. bar: undefined
  848. }, 3, "Hey!", "Κάνε πάντα γνωρίζουμε ας των, μηχανής επιδιόρθωσης επιδιορθώσεις ώς μια. Κλπ ας"
  849. ],
  850. unicode: "老 汉语中存在 港澳和海外的华人圈中 贵州 我去了书店 现在尚有争",
  851. b: "b",
  852. c: fn1
  853. };
  854. var diff5 = {
  855. a: [
  856. "string", null, 0, "1", 1, {
  857. prop: null,
  858. foo: [1,2,null,{}, [], [1,2,3]],
  859. bat: undefined // different: property name not "bar"
  860. }, 3, "Hey!", "Κάνε πάντα γνωρίζουμε ας των, μηχανής επιδιόρθωσης επιδιορθώσεις ώς μια. Κλπ ας"
  861. ],
  862. unicode: "老 汉语中存在 港澳和海外的华人圈中 贵州 我去了书店 现在尚有争",
  863. b: "b",
  864. c: fn1
  865. };
  866. equals(QUnit.equiv(same1, same2), true);
  867. equals(QUnit.equiv(same2, same1), true);
  868. equals(QUnit.equiv(same2, diff1), false);
  869. equals(QUnit.equiv(diff1, same2), false);
  870. equals(QUnit.equiv(same1, diff1), false);
  871. equals(QUnit.equiv(same1, diff2), false);
  872. equals(QUnit.equiv(same1, diff3), false);
  873. equals(QUnit.equiv(same1, diff3), false);
  874. equals(QUnit.equiv(same1, diff4), false);
  875. equals(QUnit.equiv(same1, diff5), false);
  876. equals(QUnit.equiv(diff5, diff1), false);
  877. });
  878. test("Complex Arrays.", function() {
  879. function fn() {
  880. }
  881. equals(QUnit.equiv(
  882. [1, 2, 3, true, {}, null, [
  883. {
  884. a: ["", '1', 0]
  885. },
  886. 5, 6, 7
  887. ], "foo"],
  888. [1, 2, 3, true, {}, null, [
  889. {
  890. a: ["", '1', 0]
  891. },
  892. 5, 6, 7
  893. ], "foo"]),
  894. true);
  895. equals(QUnit.equiv(
  896. [1, 2, 3, true, {}, null, [
  897. {
  898. a: ["", '1', 0]
  899. },
  900. 5, 6, 7
  901. ], "foo"],
  902. [1, 2, 3, true, {}, null, [
  903. {
  904. b: ["", '1', 0] // not same property name
  905. },
  906. 5, 6, 7
  907. ], "foo"]),
  908. false);
  909. var a = [{
  910. b: fn,
  911. c: false,
  912. "do": "reserved word",
  913. "for": {
  914. ar: [3,5,9,"hey!", [], {
  915. ar: [1,[
  916. 3,4,6,9, null, [], []
  917. ]],
  918. e: fn,
  919. f: undefined
  920. }]
  921. },
  922. e: 0.43445
  923. }, 5, "string", 0, fn, false, null, undefined, 0, [
  924. 4,5,6,7,8,9,11,22,33,44,55,"66", null, [], [[[[[3]]]], "3"], {}, 1/0
  925. ], [], [[[], "foo", null, {
  926. n: 1/0,
  927. z: {
  928. a: [3,4,5,6,"yep!", undefined, undefined],
  929. b: {}
  930. }
  931. }, {}]]];
  932. equals(QUnit.equiv(a,
  933. [{
  934. b: fn,
  935. c: false,
  936. "do": "reserved word",
  937. "for": {
  938. ar: [3,5,9,"hey!", [], {
  939. ar: [1,[
  940. 3,4,6,9, null, [], []
  941. ]],
  942. e: fn,
  943. f: undefined
  944. }]
  945. },
  946. e: 0.43445
  947. }, 5, "string", 0, fn, false, null, undefined, 0, [
  948. 4,5,6,7,8,9,11,22,33,44,55,"66", null, [], [[[[[3]]]], "3"], {}, 1/0
  949. ], [], [[[], "foo", null, {
  950. n: 1/0,
  951. z: {
  952. a: [3,4,5,6,"yep!", undefined, undefined],
  953. b: {}
  954. }
  955. }, {}]]]), true);
  956. equals(QUnit.equiv(a,
  957. [{
  958. b: fn,
  959. c: false,
  960. "do": "reserved word",
  961. "for": {
  962. ar: [3,5,9,"hey!", [], {
  963. ar: [1,[
  964. 3,4,6,9, null, [], []
  965. ]],
  966. e: fn,
  967. f: undefined
  968. }]
  969. },
  970. e: 0.43445
  971. }, 5, "string", 0, fn, false, null, undefined, 0, [
  972. 4,5,6,7,8,9,11,22,33,44,55,"66", null, [], [[[[[2]]]], "3"], {}, 1/0 // different: [[[[[2]]]]] instead of [[[[[3]]]]]
  973. ], [], [[[], "foo", null, {
  974. n: 1/0,
  975. z: {
  976. a: [3,4,5,6,"yep!", undefined, undefined],
  977. b: {}
  978. }
  979. }, {}]]]), false);
  980. equals(QUnit.equiv(a,
  981. [{
  982. b: fn,
  983. c: false,
  984. "do": "reserved word",
  985. "for": {
  986. ar: [3,5,9,"hey!", [], {
  987. ar: [1,[
  988. 3,4,6,9, null, [], []
  989. ]],
  990. e: fn,
  991. f: undefined
  992. }]
  993. },
  994. e: 0.43445
  995. }, 5, "string", 0, fn, false, null, undefined, 0, [
  996. 4,5,6,7,8,9,11,22,33,44,55,"66", null, [], [[[[[3]]]], "3"], {}, 1/0
  997. ], [], [[[], "foo", null, {
  998. n: -1/0, // different, -Infinity instead of Infinity
  999. z: {
  1000. a: [3,4,5,6,"yep!", undefined, undefined],
  1001. b: {}
  1002. }
  1003. }, {}]]]), false);
  1004. equals(QUnit.equiv(a,
  1005. [{
  1006. b: fn,
  1007. c: false,
  1008. "do": "reserved word",
  1009. "for": {
  1010. ar: [3,5,9,"hey!", [], {
  1011. ar: [1,[
  1012. 3,4,6,9, null, [], []
  1013. ]],
  1014. e: fn,
  1015. f: undefined
  1016. }]
  1017. },
  1018. e: 0.43445
  1019. }, 5, "string", 0, fn, false, null, undefined, 0, [
  1020. 4,5,6,7,8,9,11,22,33,44,55,"66", null, [], [[[[[3]]]], "3"], {}, 1/0
  1021. ], [], [[[], "foo", { // different: null is missing
  1022. n: 1/0,
  1023. z: {
  1024. a: [3,4,5,6,"yep!", undefined, undefined],
  1025. b: {}
  1026. }
  1027. }, {}]]]), false);
  1028. equals(QUnit.equiv(a,
  1029. [{
  1030. b: fn,
  1031. c: false,
  1032. "do": "reserved word",
  1033. "for": {
  1034. ar: [3,5,9,"hey!", [], {
  1035. ar: [1,[
  1036. 3,4,6,9, null, [], []
  1037. ]],
  1038. e: fn
  1039. // different: missing property f: undefined
  1040. }]
  1041. },
  1042. e: 0.43445
  1043. }, 5, "string", 0, fn, false, null, undefined, 0, [
  1044. 4,5,6,7,8,9,11,22,33,44,55,"66", null, [], [[[[[3]]]], "3"], {}, 1/0
  1045. ], [], [[[], "foo", null, {
  1046. n: 1/0,
  1047. z: {
  1048. a: [3,4,5,6,"yep!", undefined, undefined],
  1049. b: {}
  1050. }
  1051. }, {}]]]), false);
  1052. });
  1053. test("Prototypal inheritance", function() {
  1054. function Gizmo(id) {
  1055. this.id = id;
  1056. }
  1057. function Hoozit(id) {
  1058. this.id = id;
  1059. }
  1060. Hoozit.prototype = new Gizmo();
  1061. var gizmo = new Gizmo("ok");
  1062. var hoozit = new Hoozit("ok");
  1063. // Try this test many times after test on instances that hold function
  1064. // to make sure that our code does not mess with last object constructor memoization.
  1065. equals(QUnit.equiv(function () {}, function () {}), false);
  1066. // Hoozit inherit from Gizmo
  1067. // hoozit instanceof Hoozit; // true
  1068. // hoozit instanceof Gizmo; // true
  1069. equals(QUnit.equiv(hoozit, gizmo), true);
  1070. Gizmo.prototype.bar = true; // not a function just in case we skip them
  1071. // Hoozit inherit from Gizmo
  1072. // They are equivalent
  1073. equals(QUnit.equiv(hoozit, gizmo), true);
  1074. // Make sure this is still true !important
  1075. // The reason for this is that I forgot to reset the last
  1076. // caller to where it were called from.
  1077. equals(QUnit.equiv(function () {}, function () {}), false);
  1078. // Make sure this is still true !important
  1079. equals(QUnit.equiv(hoozit, gizmo), true);
  1080. Hoozit.prototype.foo = true; // not a function just in case we skip them
  1081. // Gizmo does not inherit from Hoozit
  1082. // gizmo instanceof Gizmo; // true
  1083. // gizmo instanceof Hoozit; // false
  1084. // They are not equivalent
  1085. equals(QUnit.equiv(hoozit, gizmo), false);
  1086. // Make sure this is still true !important
  1087. equals(QUnit.equiv(function () {}, function () {}), false);
  1088. });
  1089. test("Instances", function() {
  1090. function A() {}
  1091. var a1 = new A();
  1092. var a2 = new A();
  1093. function B() {
  1094. this.fn = function () {};
  1095. }
  1096. var b1 = new B();
  1097. var b2 = new B();
  1098. equals(QUnit.equiv(a1, a2), true, "Same property, same constructor");
  1099. // b1.fn and b2.fn are functions but they are different references
  1100. // But we decided to skip function for instances.
  1101. equals(QUnit.equiv(b1, b2), true, "Same property, same constructor");
  1102. equals(QUnit.equiv(a1, b1), false, "Same properties but different constructor"); // failed
  1103. function Car(year) {
  1104. var privateVar = 0;
  1105. this.year = year;
  1106. this.isOld = function() {
  1107. return year > 10;
  1108. };
  1109. }
  1110. function Human(year) {
  1111. var privateVar = 1;
  1112. this.year = year;
  1113. this.isOld = function() {
  1114. return year > 80;
  1115. };
  1116. }
  1117. var car = new Car(30);
  1118. var carSame = new Car(30);
  1119. var carDiff = new Car(10);
  1120. var human = new Human(30);
  1121. var diff = {
  1122. year: 30
  1123. };
  1124. var same = {
  1125. year: 30,
  1126. isOld: function () {}
  1127. };
  1128. equals(QUnit.equiv(car, car), true);
  1129. equals(QUnit.equiv(car, carDiff), false);
  1130. equals(QUnit.equiv(car, carSame), true);
  1131. equals(QUnit.equiv(car, human), false);
  1132. });
  1133. test("Complex Instances Nesting (with function value in literals and/or in nested instances)", function() {
  1134. function A(fn) {
  1135. this.a = {};
  1136. this.fn = fn;
  1137. this.b = {a: []};
  1138. this.o = {};
  1139. this.fn1 = fn;
  1140. }
  1141. function B(fn) {
  1142. this.fn = fn;
  1143. this.fn1 = function () {};
  1144. this.a = new A(function () {});
  1145. }
  1146. function fnOutside() {
  1147. }
  1148. function C(fn) {
  1149. function fnInside() {
  1150. }
  1151. this.x = 10;
  1152. this.fn = fn;
  1153. this.fn1 = function () {};
  1154. this.fn2 = fnInside;
  1155. this.fn3 = {
  1156. a: true,
  1157. b: fnOutside // ok make reference to a function in all instances scope
  1158. };
  1159. this.o1 = {};
  1160. // This function will be ignored.
  1161. // Even if it is not visible for all instances (e.g. locked in a closures),
  1162. // it is from a property that makes part of an instance (e.g. from the C constructor)
  1163. this.b1 = new B(function () {});
  1164. this.b2 = new B({
  1165. x: {
  1166. b2: new B(function() {})
  1167. }
  1168. });
  1169. }
  1170. function D(fn) {
  1171. function fnInside() {
  1172. }
  1173. this.x = 10;
  1174. this.fn = fn;
  1175. this.fn1 = function () {};
  1176. this.fn2 = fnInside;
  1177. this.fn3 = {
  1178. a: true,
  1179. b: fnOutside, // ok make reference to a function in all instances scope
  1180. // This function won't be ingored.
  1181. // It isn't visible for all C insances
  1182. // and it is not in a property of an instance. (in an Object instances e.g. the object literal)
  1183. c: fnInside
  1184. };
  1185. this.o1 = {};
  1186. // This function will be ignored.
  1187. // Even if it is not visible for all instances (e.g. locked in a closures),
  1188. // it is from a property that makes part of an instance (e.g. from the C constructor)
  1189. this.b1 = new B(function () {});
  1190. this.b2 = new B({
  1191. x: {
  1192. b2: new B(function() {})
  1193. }
  1194. });
  1195. }
  1196. function E(fn) {
  1197. function fnInside() {
  1198. }
  1199. this.x = 10;
  1200. this.fn = fn;
  1201. this.fn1 = function () {};
  1202. this.fn2 = fnInside;
  1203. this.fn3 = {
  1204. a: true,
  1205. b: fnOutside // ok make reference to a function in all instances scope
  1206. };
  1207. this.o1 = {};
  1208. // This function will be ignored.
  1209. // Even if it is not visible for all instances (e.g. locked in a closures),
  1210. // it is from a property that makes part of an instance (e.g. from the C constructor)
  1211. this.b1 = new B(function () {});
  1212. this.b2 = new B({
  1213. x: {
  1214. b1: new B({a: function() {}}),
  1215. b2: new B(function() {})
  1216. }
  1217. });
  1218. }
  1219. var a1 = new A(function () {});
  1220. var a2 = new A(function () {});
  1221. equals(QUnit.equiv(a1, a2), true);
  1222. equals(QUnit.equiv(a1, a2), true); // different instances
  1223. var b1 = new B(function () {});
  1224. var b2 = new B(function () {});
  1225. equals(QUnit.equiv(b1, b2), true);
  1226. var c1 = new C(function () {});
  1227. var c2 = new C(function () {});
  1228. equals(QUnit.equiv(c1, c2), true);
  1229. var d1 = new D(function () {});
  1230. var d2 = new D(function () {});
  1231. equals(QUnit.equiv(d1, d2), false);
  1232. var e1 = new E(function () {});
  1233. var e2 = new E(function () {});
  1234. equals(QUnit.equiv(e1, e2), false);
  1235. });
  1236. test('object with references to self wont loop', function(){
  1237. var circularA = {
  1238. abc:null
  1239. }, circularB = {
  1240. abc:null
  1241. };
  1242. circularA.abc = circularA;
  1243. circularB.abc = circularB;
  1244. equals(QUnit.equiv(circularA, circularB), true, "Should not repeat test on object (ambigous test)");
  1245. circularA.def = 1;
  1246. circularB.def = 1;
  1247. equals(QUnit.equiv(circularA, circularB), true, "Should not repeat test on object (ambigous test)");
  1248. circularA.def = 1;
  1249. circularB.def = 0;
  1250. equals(QUnit.equiv(circularA, circularB), false, "Should not repeat test on object (unambigous test)");
  1251. });
  1252. test('array with references to self wont loop', function(){
  1253. var circularA = [],
  1254. circularB = [];
  1255. circularA.push(circularA);
  1256. circularB.push(circularB);
  1257. equals(QUnit.equiv(circularA, circularB), true, "Should not repeat test on array (ambigous test)");
  1258. circularA.push( 'abc' );
  1259. circularB.push( 'abc' );
  1260. equals(QUnit.equiv(circularA, circularB), true, "Should not repeat test on array (ambigous test)");
  1261. circularA.push( 'hello' );
  1262. circularB.push( 'goodbye' );
  1263. equals(QUnit.equiv(circularA, circularB), false, "Should not repeat test on array (unambigous test)");
  1264. });
  1265. test('mixed object/array with references to self wont loop', function(){
  1266. var circularA = [{abc:null}],
  1267. circularB = [{abc:null}];
  1268. circularA[0].abc = circularA;
  1269. circularB[0].abc = circularB;
  1270. circularA.push(circularA);
  1271. circularB.push(circularB);
  1272. equals(QUnit.equiv(circularA, circularB), true, "Should not repeat test on object/array (ambigous test)");
  1273. circularA[0].def = 1;
  1274. circularB[0].def = 1;
  1275. equals(QUnit.equiv(circularA, circularB), true, "Should not repeat test on object/array (ambigous test)");
  1276. circularA[0].def = 1;
  1277. circularB[0].def = 0;
  1278. equals(QUnit.equiv(circularA, circularB), false, "Should not repeat test on object/array (unambigous test)");
  1279. });
  1280. test("Test that must be done at the end because they extend some primitive's prototype", function() {
  1281. // Try that a function looks like our regular expression.
  1282. // This tests if we check that a and b are really both instance of RegExp
  1283. Function.prototype.global = true;
  1284. Function.prototype.multiline = true;
  1285. Function.prototype.ignoreCase = false;
  1286. Function.prototype.source = "my regex";
  1287. var re = /my regex/gm;
  1288. equals(QUnit.equiv(re, function () {}), false, "A function that looks that a regex isn't a regex");
  1289. // This test will ensures it works in both ways, and ALSO especially that we can make differences
  1290. // between RegExp and Function constructor because typeof on a RegExpt instance is "function"
  1291. equals(QUnit.equiv(function () {}, re), false, "Same conversely, but ensures that function and regexp are distinct because their constructor are different");
  1292. });