private.tests.js 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911
  1. /*global _document:true, _Error:true, _args, _extend, _deepCopy, _pick, _omit, _deleteOwnProperties, _containedBy, _getDirPathOfUrl, _getCurrentScriptUrlFromErrorStack, _getCurrentScriptUrlFromError:true, _getCurrentScriptUrl, _getUnanimousScriptParentDir, _getDefaultSwfPath */
  2. (function(module, test) {
  3. "use strict";
  4. var doc, errorDef, getUrlFromError;
  5. module("shared/private.js unit tests", {
  6. setup: function() {
  7. doc = _document;
  8. errorDef = _Error;
  9. getUrlFromError = _getCurrentScriptUrlFromError;
  10. },
  11. teardown: function() {
  12. _document = doc;
  13. _Error = errorDef;
  14. _getCurrentScriptUrlFromError = getUrlFromError;
  15. }
  16. });
  17. test("`_args` works", function(assert) {
  18. assert.expect(4);
  19. // Arrange
  20. var _arguments = function() {
  21. return arguments;
  22. };
  23. var fn = function() {};
  24. var expectedOutput1 = [1, 2, 3];
  25. var expectedOutput2 = [fn];
  26. var expectedOutput3 = [{ foo: "bar" }];
  27. var expectedOutput4 = [[1, 2, 3]];
  28. var inputArgs1 = _arguments(1, 2, 3);
  29. var inputArgs2 = _arguments(fn);
  30. var inputArgs3 = _arguments({ foo: "bar" });
  31. var inputArgs4 = _arguments([1, 2, 3]);
  32. // Act
  33. var actualOutput1 = _args(inputArgs1);
  34. var actualOutput2 = _args(inputArgs2);
  35. var actualOutput3 = _args(inputArgs3);
  36. var actualOutput4 = _args(inputArgs4);
  37. // Arrange
  38. assert.deepEqual(actualOutput1, expectedOutput1);
  39. assert.deepEqual(actualOutput2, expectedOutput2);
  40. assert.deepEqual(actualOutput3, expectedOutput3);
  41. assert.deepEqual(actualOutput4, expectedOutput4);
  42. });
  43. test("`_extend` works on plain objects", function(assert) {
  44. assert.expect(5);
  45. // Plain objects
  46. var a = {
  47. "a": "apple",
  48. "c": "cantalope"
  49. },
  50. b = {
  51. "b": "banana",
  52. "c": "cherry" // cuz cantalope sucks ;)
  53. },
  54. c = {
  55. "a": "apple",
  56. "b": "banana",
  57. "c": "cherry"
  58. };
  59. assert.deepEqual(_extend({}, a), a, "actual equals expected, `target` is updated, `source` is unaffected");
  60. assert.deepEqual(_extend({}, b), b, "actual equals expected, `target` is updated, `source` is unaffected");
  61. assert.deepEqual(_extend({}, c), c, "actual equals expected, `target` is updated, `source` is unaffected");
  62. assert.deepEqual(_extend(a, b), c, "actual equals expected");
  63. assert.deepEqual(a, c, "`a` equals `c` because `_extend` updates the `target` argument");
  64. });
  65. test("`_extend` only copies owned properties", function(assert) {
  66. assert.expect(1);
  67. // Now prototypes...
  68. var SomeClass = function() {
  69. this.b = "banana";
  70. };
  71. SomeClass.prototype.c = "cantalope"; // cuz cantalope sucks ;)
  72. var a = {
  73. "a": "apple",
  74. "c": "cherry"
  75. },
  76. b = new SomeClass(),
  77. c = {
  78. "a": "apple",
  79. "b": "banana",
  80. "c": "cherry"
  81. };
  82. assert.deepEqual(_extend(a, b), c, "actual equals expected because `_extend` does not copy over prototype properties");
  83. });
  84. test("`_extend` only copies owned properties from Array source", function(assert) {
  85. assert.expect(3);
  86. var a = {
  87. "a": "apple",
  88. "b": "banana"
  89. },
  90. b = ["zero", "one", "two"],
  91. c = {
  92. "a": "apple",
  93. "b": "banana",
  94. "0": "zero",
  95. "1": "one",
  96. "2": "two"
  97. };
  98. assert.deepEqual(_extend(a, b), c, "actual equals expected because `_extend` does not copy over prototype properties");
  99. assert.strictEqual("length" in a, false, "`a` should not have gained a `length` property");
  100. assert.strictEqual("length" in b, true, "`b` should still have a `length` property");
  101. });
  102. test("`_extend` will merge multiple objects", function(assert) {
  103. assert.expect(2);
  104. var a = {
  105. "a": "apple",
  106. "c": "cantalope",
  107. "d": "dragon fruit"
  108. },
  109. b = {
  110. "b": "banana",
  111. "c": "cherry" // cuz cantalope sucks ;)
  112. },
  113. c = {
  114. "a": "apricot",
  115. "b": "blueberry"
  116. },
  117. d = {
  118. "a": "apricot",
  119. "b": "blueberry",
  120. "c": "cherry",
  121. "d": "dragon fruit"
  122. };
  123. assert.deepEqual(_extend({}, a, b, c), d, "actual equals expected, `target` is updated, `source` is unaffected");
  124. assert.deepEqual(_extend(a, b, c), d, "actual equals expected");
  125. });
  126. test("`_deepCopy` works", function(assert) {
  127. assert.expect(13);
  128. // Arrange
  129. var input1 = {
  130. "a": "b",
  131. "b": {
  132. "c": "d"
  133. }
  134. };
  135. var input2 = [[1, 2], 2];
  136. var expected1 = {
  137. "a": "b",
  138. "b": {
  139. "c": "d"
  140. }
  141. };
  142. var expected2 = [[1, 2], 2];
  143. // Act
  144. var actual1 = _deepCopy(input1);
  145. var actual2 = _deepCopy(input2);
  146. // Assert
  147. assert.deepEqual(actual1, expected1, "Objects are deeply equal");
  148. assert.notStrictEqual(actual1, expected1, "Objects are not strictly equal");
  149. assert.strictEqual(actual1.a, expected1.a, "Objects' non-object properties are strictly equal");
  150. assert.deepEqual(actual1.b, expected1.b, "Objects' object properties are deeply equal");
  151. assert.notStrictEqual(actual1.b, expected1.b, "Objects' object properties are not strictly equal");
  152. assert.strictEqual(actual1.b.c, expected1.b.c, "Objects' object properties' non-object properties are strictly equal");
  153. assert.deepEqual(actual2, expected2, "Arrays are deeply equal");
  154. assert.notStrictEqual(actual2, expected2, "Arrays are not strictly equal");
  155. assert.deepEqual(actual2[0], expected2[0], "Sub-arrays are deeply equal");
  156. assert.notStrictEqual(actual2[0], expected2[0], "Sub-arrays are not strictly equal");
  157. assert.strictEqual(actual2[0][0], expected2[0][0], "Sub-arrays' first items are strictly equal");
  158. assert.strictEqual(actual2[0][1], expected2[0][1], "Sub-arrays' second items are strictly equal");
  159. assert.strictEqual(actual2[1], expected2[1], "Sub-items are strictly equal");
  160. });
  161. test("`_pick` works", function(assert) {
  162. assert.expect(6);
  163. // Arrange
  164. var obj1 = {};
  165. var obj2 = {
  166. "name": "Zero",
  167. "version": "v2.x",
  168. "other": "test"
  169. };
  170. var filter1 = [];
  171. var filter2 = ["name", "version"];
  172. var filter3 = ["name", "version", "other"];
  173. var expected1x = {};
  174. var expected21 = {};
  175. var expected22 = {
  176. "name": "Zero",
  177. "version": "v2.x"
  178. };
  179. var expected23 = {
  180. "name": "Zero",
  181. "version": "v2.x",
  182. "other": "test"
  183. };
  184. // Act
  185. var result11 = _pick(obj1, filter1);
  186. var result12 = _pick(obj1, filter2);
  187. var result13 = _pick(obj1, filter3);
  188. var result21 = _pick(obj2, filter1);
  189. var result22 = _pick(obj2, filter2);
  190. var result23 = _pick(obj2, filter3);
  191. // Assert
  192. assert.deepEqual(result11, expected1x, "An empty object cannot have any properties picked");
  193. assert.deepEqual(result12, expected1x, "An empty object cannot have any properties picked");
  194. assert.deepEqual(result13, expected1x, "An empty object cannot have any properties picked");
  195. assert.deepEqual(result21, expected21, "An object with an empty pick list will have nothing picked");
  196. assert.deepEqual(result22, expected22, "An object with a subset pick list will have only those properties picked");
  197. assert.deepEqual(result23, expected23, "An object with a complete pick list will have all of its properties picked");
  198. });
  199. test("`_omit` works", function(assert) {
  200. assert.expect(6);
  201. // Arrange
  202. var obj1 = {};
  203. var obj2 = {
  204. "name": "Zero",
  205. "version": "v2.x",
  206. "other": "test"
  207. };
  208. var filter1 = [];
  209. var filter2 = ["name", "version"];
  210. var filter3 = ["name", "version", "other"];
  211. var expected1x = {};
  212. var expected21 = {
  213. "name": "Zero",
  214. "version": "v2.x",
  215. "other": "test"
  216. };
  217. var expected22 = {
  218. "other": "test"
  219. };
  220. var expected23 = {};
  221. // Act
  222. var result11 = _omit(obj1, filter1);
  223. var result12 = _omit(obj1, filter2);
  224. var result13 = _omit(obj1, filter3);
  225. var result21 = _omit(obj2, filter1);
  226. var result22 = _omit(obj2, filter2);
  227. var result23 = _omit(obj2, filter3);
  228. // Assert
  229. assert.deepEqual(result11, expected1x, "An empty object cannot have any properties picked");
  230. assert.deepEqual(result12, expected1x, "An empty object cannot have any properties picked");
  231. assert.deepEqual(result13, expected1x, "An empty object cannot have any properties picked");
  232. assert.deepEqual(result21, expected21, "An object with an empty omit list will have everything picked");
  233. assert.deepEqual(result22, expected22, "An object with a subset omit list will have everything but those properties picked");
  234. assert.deepEqual(result23, expected23, "An object with a complete omit list will have nothing picked");
  235. });
  236. test("`_deleteOwnProperties` will delete all owned enumerable properties", function(assert) {
  237. assert.expect(24);
  238. var getNonObjectKeys = function(obj) {
  239. var prop,
  240. keys = [];
  241. if (obj) {
  242. for (prop in obj) {
  243. if (obj.hasOwnProperty(prop)) {
  244. keys.push(prop);
  245. }
  246. }
  247. }
  248. return keys;
  249. };
  250. var getProtoKeys = function(obj) {
  251. var prop,
  252. keys = [];
  253. if (obj) {
  254. for (prop in obj) {
  255. if (!obj.hasOwnProperty(prop)) {
  256. keys.push(prop);
  257. }
  258. }
  259. }
  260. return keys;
  261. };
  262. var a = {
  263. "a": "apple",
  264. "c": "cantalope",
  265. "d": "dragon fruit"
  266. },
  267. b = {},
  268. c = ["banana", "cherry"],
  269. d = (function() {
  270. function SomePrototype() {
  271. this.protoProp = "foo";
  272. }
  273. function SomeClass() {
  274. this.ownedProp = "bar";
  275. }
  276. SomeClass.prototype = new SomePrototype();
  277. SomeClass.prototype.constructor = SomeClass;
  278. return new SomeClass();
  279. })(),
  280. e = null,
  281. f; // = undefined;
  282. assert.deepEqual(Object.keys(a), ["a", "c", "d"]);
  283. assert.deepEqual(getProtoKeys(a), []);
  284. _deleteOwnProperties(a);
  285. assert.deepEqual(Object.keys(a), []);
  286. assert.deepEqual(getProtoKeys(a), []);
  287. assert.deepEqual(Object.keys(b), []);
  288. assert.deepEqual(getProtoKeys(b), []);
  289. _deleteOwnProperties(b);
  290. assert.deepEqual(Object.keys(b), []);
  291. assert.deepEqual(getProtoKeys(b), []);
  292. assert.deepEqual(getNonObjectKeys(c), ["0", "1"]);
  293. assert.deepEqual(getProtoKeys(c), []);
  294. _deleteOwnProperties(c);
  295. assert.deepEqual(getNonObjectKeys(c), []);
  296. assert.deepEqual(getProtoKeys(c), []);
  297. assert.deepEqual(Object.keys(d), ["ownedProp"]);
  298. assert.deepEqual(getProtoKeys(d), ["protoProp", "constructor"]);
  299. _deleteOwnProperties(d);
  300. assert.deepEqual(Object.keys(d), []);
  301. assert.deepEqual(getProtoKeys(d), ["protoProp", "constructor"]);
  302. assert.deepEqual(getNonObjectKeys(e), []);
  303. assert.deepEqual(getProtoKeys(e), []);
  304. _deleteOwnProperties(e);
  305. assert.deepEqual(getNonObjectKeys(e), []);
  306. assert.deepEqual(getProtoKeys(e), []);
  307. assert.deepEqual(getNonObjectKeys(f), []);
  308. assert.deepEqual(getProtoKeys(f), []);
  309. _deleteOwnProperties(f);
  310. assert.deepEqual(getNonObjectKeys(f), []);
  311. assert.deepEqual(getProtoKeys(f), []);
  312. });
  313. test("`_containedBy` works", function(assert) {
  314. /*jshint camelcase:false */
  315. assert.expect(29);
  316. // Arrange
  317. var fixture = document.getElementById("qunit-fixture");
  318. fixture.innerHTML =
  319. "<div id='container'>" +
  320. "<div id='contained1'>" +
  321. "<div id='contained1_1'></div>" +
  322. "<div id='contained1_2'>" +
  323. "<div id='contained1_2_1'></div>" +
  324. "</div>" +
  325. "</div>" +
  326. "<div id='contained2'></div>" +
  327. "</div>" +
  328. "<div id='not_container'>" +
  329. "<div id='not_contained'></div>" +
  330. "</div>";
  331. var container = document.getElementById("container");
  332. var contained1 = document.getElementById("contained1");
  333. var contained1_1 = document.getElementById("contained1_1");
  334. var contained1_2 = document.getElementById("contained1_2");
  335. var contained1_2_1 = document.getElementById("contained1_2_1");
  336. var contained2 = document.getElementById("contained2");
  337. var not_container = document.getElementById("not_container");
  338. var not_contained = document.getElementById("not_contained");
  339. // Act & Assert
  340. assert.strictEqual(_containedBy(contained1_2_1, contained1_2_1), true);
  341. assert.strictEqual(_containedBy(contained1_2_1, contained1_2), true);
  342. assert.strictEqual(_containedBy(contained1_2_1, contained1), true);
  343. assert.strictEqual(_containedBy(contained1_2_1, container), true);
  344. assert.strictEqual(_containedBy(contained1_2_1, fixture), true);
  345. assert.strictEqual(_containedBy(contained1_2_1, not_container), false);
  346. assert.strictEqual(_containedBy(contained1_1, contained1_1), true);
  347. assert.strictEqual(_containedBy(contained1_1, contained1), true);
  348. assert.strictEqual(_containedBy(contained1_1, container), true);
  349. assert.strictEqual(_containedBy(contained1_1, fixture), true);
  350. assert.strictEqual(_containedBy(contained1_1, not_container), false);
  351. assert.strictEqual(_containedBy(contained1, contained1), true);
  352. assert.strictEqual(_containedBy(contained1, container), true);
  353. assert.strictEqual(_containedBy(contained1, fixture), true);
  354. assert.strictEqual(_containedBy(contained1, not_container), false);
  355. assert.strictEqual(_containedBy(contained2, contained2), true);
  356. assert.strictEqual(_containedBy(contained2, container), true);
  357. assert.strictEqual(_containedBy(contained2, fixture), true);
  358. assert.strictEqual(_containedBy(contained2, not_container), false);
  359. assert.strictEqual(_containedBy(container, container), true);
  360. assert.strictEqual(_containedBy(container, fixture), true);
  361. assert.strictEqual(_containedBy(container, not_container), false);
  362. assert.strictEqual(_containedBy(not_contained, not_contained), true);
  363. assert.strictEqual(_containedBy(not_contained, not_container), true);
  364. assert.strictEqual(_containedBy(not_contained, fixture), true);
  365. assert.strictEqual(_containedBy(not_contained, container), false);
  366. assert.strictEqual(_containedBy(not_container, not_container), true);
  367. assert.strictEqual(_containedBy(not_container, fixture), true);
  368. assert.strictEqual(_containedBy(not_container, container), false);
  369. });
  370. test("`_getDirPathOfUrl` works", function(assert) {
  371. assert.expect(8);
  372. // Arrange
  373. var input1 = "http://example.com/blah/foo/index.html";
  374. var input2 = "http://example.com/blah/foo/index.html?q=p";
  375. var input3 = "http://example.com/blah/foo/index.html?q=p&x=z";
  376. var input4 = "http://example.com/blah/foo/index.html?#xyz";
  377. var input5 = "http://example.com/blah/foo/index.html?q=p#xyz";
  378. var input6 = "http://example.com/blah/foo/index.html?q=p&x=z#xyz";
  379. var input7 = "http://example.com/blah/foo/";
  380. var input8 = "";
  381. var expected1 = "http://example.com/blah/foo/";
  382. var expected2 = "http://example.com/blah/foo/";
  383. var expected3 = "http://example.com/blah/foo/";
  384. var expected4 = "http://example.com/blah/foo/";
  385. var expected5 = "http://example.com/blah/foo/";
  386. var expected6 = "http://example.com/blah/foo/";
  387. var expected7 = "http://example.com/blah/foo/";
  388. var expected8;
  389. // Act
  390. var actual1 = _getDirPathOfUrl(input1);
  391. var actual2 = _getDirPathOfUrl(input2);
  392. var actual3 = _getDirPathOfUrl(input3);
  393. var actual4 = _getDirPathOfUrl(input4);
  394. var actual5 = _getDirPathOfUrl(input5);
  395. var actual6 = _getDirPathOfUrl(input6);
  396. var actual7 = _getDirPathOfUrl(input7);
  397. var actual8 = _getDirPathOfUrl(input8);
  398. // Assert
  399. assert.strictEqual(actual1, expected1);
  400. assert.strictEqual(actual2, expected2);
  401. assert.strictEqual(actual3, expected3);
  402. assert.strictEqual(actual4, expected4);
  403. assert.strictEqual(actual5, expected5);
  404. assert.strictEqual(actual6, expected6);
  405. assert.strictEqual(actual7, expected7);
  406. assert.strictEqual(actual8, expected8);
  407. });
  408. test("`_getCurrentScriptUrlFromErrorStack` works", function(assert) {
  409. assert.expect(25);
  410. // Arrange
  411. var localStacks = [
  412. "Error: my uncaught error\n at http://example.com/index.html:123:4\n at jQuery.event.dispatch (http://code.jquery.com/blah.js:567:8)\n at foo",
  413. "http://example.com/index.html:123:4\ndispatch@http://code.jquery.com/blah.js:567:8\nfoo",
  414. "@http://example.com/index.html:123\ndispatch@http://code.jquery.com/blah.js:567\nfoo",
  415. "<anonymous function>([arguments not available])@http://example.com/index.html:123\n<anonymous function: dispatch>([arguments not available])@http://code.jquery.com/blah.js:567\nfoo",
  416. "Error: my error\n at http://example.com/index.html:123\n at http://code.jquery.com/blah.js:567\nfoo",
  417. "Error(\"my error\")@:0\u000a([object Object])@http://example.com/index.html:123\u000a([object Object])@http://code.jquery.com/blah.js:567\u000afoo",
  418. "Error: my error\n at Anonymous function (http://example.com/index.html:123:4)\n at dispatch (http://code.jquery.com/blah.js:567:8)\n at foo",
  419. "Error: my sneaky error message has a URL in it at http://google.com/mean.js:987\n at Anonymous function (http://example.com/index.html:123:4)\n at dispatch (http://code.jquery.com/blah.js:567:8)\n at foo"
  420. ];
  421. var remoteStacks = [
  422. "Error: my error\n at window.onload (http://example.com/blah/foo.js:95:11)\n at jQuery.event.dispatch (http://code.jquery.com/blah.js:567:8)\n at foo",
  423. "onload@http://example.com/blah/foo.js:95:11\ndispatch@http://code.jquery.com/blah.js:567:8\nfoo",
  424. "onload@http://example.com/blah/foo.js:95\ndispatch@http://code.jquery.com/blah.js:567\nfoo",
  425. "<anonymous function: window.onload>([arguments not available])@http://example.com/blah/foo.js:95\n<anonymous function: dispatch>([arguments not available])@http://code.jquery.com/blah.js:567\nfoo",
  426. "Error: my error\n at http://example.com/blah/foo.js:95\n at http://code.jquery.com/blah.js:567\nfoo",
  427. "Error(\"my error\")@:0\u000a@http://example.com/blah/foo.js:95\u000a([object Object])@http://code.jquery.com/blah.js:567\u000afoo",
  428. "Error: my error\n at onload (http://example.com/blah/foo.js:95:11)\n at dispatch (http://code.jquery.com/blah.js:567:8)\n at foo",
  429. "Error: my sneaky error message has a URL in it at http://google.com/mean.js:987\n at onload (http://example.com/blah/foo.js:95:11)\n at dispatch (http://code.jquery.com/blah.js:567:8)\n at foo"
  430. ];
  431. var badStacks = [
  432. "blah",
  433. "",
  434. [],
  435. {},
  436. null,
  437. undefined
  438. ];
  439. var localExpected = "http://example.com/index.html",
  440. remoteExpected = "http://example.com/blah/foo.js",
  441. badExpected;
  442. // Act & Assert
  443. assert.strictEqual(localStacks.length, 8, "Local stacks x 8");
  444. assert.strictEqual(_getCurrentScriptUrlFromErrorStack(localStacks[0]), localExpected, "Inline script: Chrome");
  445. assert.strictEqual(_getCurrentScriptUrlFromErrorStack(localStacks[1]), localExpected, "Inline script: Safari 6.1+");
  446. assert.strictEqual(_getCurrentScriptUrlFromErrorStack(localStacks[2]), localExpected, "Inline script: Safari 6.0");
  447. assert.strictEqual(_getCurrentScriptUrlFromErrorStack(localStacks[3]), localExpected, "Inline script: Opera");
  448. assert.strictEqual(_getCurrentScriptUrlFromErrorStack(localStacks[4]), localExpected, "Inline script: PhantomJS");
  449. assert.strictEqual(_getCurrentScriptUrlFromErrorStack(localStacks[5]), localExpected, "Inline script: Firefox 3.6");
  450. assert.strictEqual(_getCurrentScriptUrlFromErrorStack(localStacks[6]), localExpected, "Inline script: IE 10.0");
  451. assert.strictEqual(_getCurrentScriptUrlFromErrorStack(localStacks[7]), localExpected, "Inline script: SneakyError");
  452. assert.strictEqual(remoteStacks.length, 8, "Remote stacks x 8");
  453. assert.strictEqual(_getCurrentScriptUrlFromErrorStack(remoteStacks[0]), remoteExpected, "External script: Chrome");
  454. assert.strictEqual(_getCurrentScriptUrlFromErrorStack(remoteStacks[1]), remoteExpected, "External script: Safari 6.1+");
  455. assert.strictEqual(_getCurrentScriptUrlFromErrorStack(remoteStacks[2]), remoteExpected, "External script: Safari 6.0");
  456. assert.strictEqual(_getCurrentScriptUrlFromErrorStack(remoteStacks[3]), remoteExpected, "External script: Opera");
  457. assert.strictEqual(_getCurrentScriptUrlFromErrorStack(remoteStacks[4]), remoteExpected, "External script: PhantomJS");
  458. assert.strictEqual(_getCurrentScriptUrlFromErrorStack(remoteStacks[5]), remoteExpected, "External script: Firefox 3.6");
  459. assert.strictEqual(_getCurrentScriptUrlFromErrorStack(remoteStacks[6]), remoteExpected, "External script: IE 10.0");
  460. assert.strictEqual(_getCurrentScriptUrlFromErrorStack(remoteStacks[7]), remoteExpected, "External script: SneakyError");
  461. assert.strictEqual(badStacks.length, 6, "Bad stacks x 6");
  462. assert.strictEqual(_getCurrentScriptUrlFromErrorStack(badStacks[0]), badExpected, "Useless stack");
  463. assert.strictEqual(_getCurrentScriptUrlFromErrorStack(badStacks[1]), badExpected, "Empty string");
  464. assert.strictEqual(_getCurrentScriptUrlFromErrorStack(badStacks[2]), badExpected, "Array");
  465. assert.strictEqual(_getCurrentScriptUrlFromErrorStack(badStacks[3]), badExpected, "Object");
  466. assert.strictEqual(_getCurrentScriptUrlFromErrorStack(badStacks[4]), badExpected, "`null`");
  467. assert.strictEqual(_getCurrentScriptUrlFromErrorStack(badStacks[5]), badExpected, "`undefined`");
  468. });
  469. test("`_getCurrentScriptUrlFromError` works", function(assert) {
  470. assert.expect(4);
  471. // Arrange
  472. var actual1, actual2, actual3, actual4;
  473. var expected = "http://example.com/blah/foo.js";
  474. var _sourceUrl, _fileName, _stack;
  475. // Do NOT inherit from the real `Error` definition
  476. _Error = function() {
  477. this.sourceURL = _sourceUrl;
  478. this.fileName = _fileName;
  479. this.stack = _stack;
  480. };
  481. // Act
  482. _sourceUrl = expected;
  483. _fileName = undefined;
  484. _stack = undefined;
  485. actual1 = _getCurrentScriptUrlFromError();
  486. _sourceUrl = undefined;
  487. _fileName = expected;
  488. _stack = undefined;
  489. actual2 = _getCurrentScriptUrlFromError();
  490. _sourceUrl = undefined;
  491. _fileName = undefined;
  492. _stack = "Error: my uncaught error\n at " + expected + ":123:4\n at jQuery.event.dispatch (http://code.jquery.com/blah.js:123:0)\n at foo";
  493. actual3 = _getCurrentScriptUrlFromError();
  494. _sourceUrl = undefined;
  495. _fileName = undefined;
  496. _stack = undefined;
  497. actual4 = _getCurrentScriptUrlFromError();
  498. // Assert
  499. assert.strictEqual(actual1, expected, "Current script derived from `err.sourceURL`");
  500. assert.strictEqual(actual2, expected, "Current script derived from `err.fileName`");
  501. assert.strictEqual(actual3, expected, "Current script derived from `err.stack`");
  502. assert.strictEqual(actual4, undefined, "Current script cannot be derived from the Error");
  503. });
  504. test("`_getCurrentScriptUrl` works", function(assert) {
  505. assert.expect(9);
  506. // Arrange
  507. var actual1, actual2, actual3, actual4, actual5, actual6, actual7, actual8, actual9;
  508. var expected1, expected2, expected3, expected4, expected5, expected6, expected7, expected8, expected9;
  509. expected1 = expected2 = expected3 = expected4 = expected5 = "http://example.com/blah/foo/bar.js";
  510. // Arrange & Act
  511. _document = {
  512. currentScript: {
  513. src: "http://example.com/blah/foo/bar.js"
  514. }
  515. };
  516. _getCurrentScriptUrlFromError = function() {};
  517. actual1 = _getCurrentScriptUrl();
  518. _document = {
  519. getElementsByTagName: function(/* tagName */) {
  520. return [
  521. { src: "http://example.com/blah/foo/bar.js" }
  522. ];
  523. }
  524. };
  525. actual2 = _getCurrentScriptUrl();
  526. _document = {
  527. getElementsByTagName: function(/* tagName */) {
  528. return [
  529. { src: "http://example.com/blah/foo.js", readyState: "complete" },
  530. { src: "http://example.com/blah/foo/bar.js", readyState: "interactive" }
  531. ];
  532. }
  533. };
  534. actual3 = _getCurrentScriptUrl();
  535. _document = {
  536. readyState: "loading",
  537. getElementsByTagName: function(/* tagName */) {
  538. return [
  539. { src: "http://example.com/blah/foo.js" },
  540. { src: "http://example.com/blah/wat.js" },
  541. { src: "http://example.com/blah/foo/bar.js" }
  542. ];
  543. }
  544. };
  545. actual4 = _getCurrentScriptUrl();
  546. _document = {
  547. getElementsByTagName: function(/* tagName */) {
  548. return [
  549. { src: "http://example.com/blah/foo.js" },
  550. { src: "http://example.com/blah/wat.js" },
  551. { src: "http://example.com/blah/foo/bar.js" }
  552. ];
  553. }
  554. };
  555. _getCurrentScriptUrlFromError = function() {
  556. return "http://example.com/blah/foo/bar.js";
  557. };
  558. actual5 = _getCurrentScriptUrl();
  559. _document = {
  560. getElementsByTagName: function(/* tagName */) {
  561. return [
  562. { src: "http://example.com/blah/foo.js" },
  563. { src: "http://example.com/blah/wat.js" }
  564. ];
  565. }
  566. };
  567. _getCurrentScriptUrlFromError = function() {};
  568. actual6 = _getCurrentScriptUrl();
  569. _document = {
  570. getElementsByTagName: function(/* tagName */) {
  571. return [
  572. { src: "http://example.com/blah/foo.js" },
  573. { /* inline script */ },
  574. { src: "http://example.com/blah/wat.js" }
  575. ];
  576. }
  577. };
  578. actual7 = _getCurrentScriptUrl();
  579. _document = {
  580. getElementsByTagName: function(/* tagName */) {
  581. return [
  582. { src: "http://example.com/blah/foo.js" },
  583. { src: "http://example.com/blah/wat.js" },
  584. { /* inline script */ }
  585. ];
  586. }
  587. };
  588. actual8 = _getCurrentScriptUrl();
  589. _document = {
  590. getElementsByTagName: function(/* tagName */) {
  591. return [
  592. { /* inline script */ }
  593. ];
  594. }
  595. };
  596. actual9 = _getCurrentScriptUrl();
  597. assert.strictEqual(actual1, expected1, "Value from `document.currentScript`");
  598. assert.strictEqual(actual2, expected2, "Value from the only script");
  599. assert.strictEqual(actual3, expected3, "Value from `scripts[i].readyState === \"interactive\"`");
  600. assert.strictEqual(actual4, expected4, "Value from last script while `document.readyState === \"loading\"");
  601. assert.strictEqual(actual5, expected5, "Value from `_getCurrentScriptUrlFromError`");
  602. assert.strictEqual(actual6, expected6, "No value can be confirmed");
  603. assert.strictEqual(actual7, expected7, "No value can be confirmed as there is at least one inline script (middle)");
  604. assert.strictEqual(actual8, expected8, "No value can be confirmed as there is at least one inline script (last)");
  605. assert.strictEqual(actual9, expected9, "No value can be confirmed as the only script tag is an inline script");
  606. });
  607. test("`_getUnanimousScriptParentDir` works", function(assert) {
  608. assert.expect(5);
  609. // Arrange
  610. var actual1, actual2, actual3, actual4, actual5;
  611. var expected1, expected2, expected3, expected4, expected5;
  612. var _scripts = [];
  613. _document = {
  614. getElementsByTagName: function(/* tagName */) {
  615. return _scripts;
  616. }
  617. };
  618. expected1 = "http://example.com/blah/";
  619. // Arrange & Act
  620. _scripts.length = 0;
  621. _scripts.push.apply(_scripts, [
  622. { src: "http://example.com/blah/foo.js" },
  623. { src: "http://example.com/blah/wat.js" },
  624. { src: "http://example.com/blah/bar.js" }
  625. ]);
  626. actual1 = _getUnanimousScriptParentDir();
  627. _scripts.length = 0;
  628. _scripts.push.apply(_scripts, [
  629. { src: "http://example.org/blah/foo.js" },
  630. { src: "http://example.net/blah/wat.js" },
  631. { src: "http://example.com/blah/bar.js" }
  632. ]);
  633. actual2 = _getUnanimousScriptParentDir();
  634. _scripts.length = 0;
  635. _scripts.push.apply(_scripts, [
  636. { src: "http://example.com/blah/foo.js" },
  637. { src: "http://example.com/blah/wat.js" },
  638. { src: "http://example.com/blah/foo/bar.js" }
  639. ]);
  640. actual3 = _getUnanimousScriptParentDir();
  641. _scripts.length = 0;
  642. _scripts.push.apply(_scripts, [
  643. { src: "http://example.com/blah/foo.js" },
  644. { /* inline script */ },
  645. { src: "http://example.com/blah/foo/bar.js" }
  646. ]);
  647. actual4 = _getUnanimousScriptParentDir();
  648. _scripts.length = 0;
  649. _scripts.push.apply(_scripts, [
  650. { src: "http://example.com/blah/foo.js" },
  651. { src: "http://example.com/blah/wat.js" },
  652. { /* inline script */ }
  653. ]);
  654. actual5 = _getUnanimousScriptParentDir();
  655. // Assert
  656. assert.strictEqual(actual1, expected1, "All script tags have the same parent directory");
  657. assert.strictEqual(actual2, expected2, "Not all script tags have the same domains");
  658. assert.strictEqual(actual3, expected3, "Not all script tags have the same parent directory");
  659. assert.strictEqual(actual4, expected4, "Not all script tags have `src` URLs (middle)");
  660. assert.strictEqual(actual5, expected5, "Not all script tags have `src` URLs (last)");
  661. });
  662. test("`_getDefaultSwfPath` works", function(assert) {
  663. assert.expect(11);
  664. // Arrange
  665. var actual1, actual2, actual3, actual4, actual5, actual6, actual7, actual8, actual9, actual10, actual11;
  666. var expected1, expected2, expected3, expected4, expected5, expected6, expected7, expected8, expected9, expected10, expected11;
  667. expected1 = expected2 = expected3 = expected4 = expected5 = "http://example.com/blah/foo/ZeroClipboard.swf";
  668. expected6 = "http://example.com/blah/ZeroClipboard.swf";
  669. expected7 = expected8 = expected9 = expected10 = expected11 = "ZeroClipboard.swf";
  670. // Arrange & Act
  671. _document = {
  672. currentScript: {
  673. src: "http://example.com/blah/foo/bar.js"
  674. }
  675. };
  676. actual1 = _getDefaultSwfPath();
  677. _document = {
  678. getElementsByTagName: function(/* tagName */) {
  679. return [
  680. { src: "http://example.com/blah/foo/bar.js" }
  681. ];
  682. }
  683. };
  684. actual2 = _getDefaultSwfPath();
  685. _document = {
  686. getElementsByTagName: function(/* tagName */) {
  687. return [
  688. { src: "http://example.com/blah/foo.js", readyState: "complete" },
  689. { src: "http://example.com/blah/foo/bar.js", readyState: "interactive" }
  690. ];
  691. }
  692. };
  693. actual3 = _getDefaultSwfPath();
  694. _document = {
  695. readyState: "loading",
  696. getElementsByTagName: function(/* tagName */) {
  697. return [
  698. { src: "http://example.com/blah/foo.js" },
  699. { src: "http://example.com/blah/wat.js" },
  700. { src: "http://example.com/blah/foo/bar.js" }
  701. ];
  702. }
  703. };
  704. actual4 = _getDefaultSwfPath();
  705. _document = {
  706. getElementsByTagName: function(/* tagName */) {
  707. return [
  708. { src: "http://example.com/blah/foo.js" },
  709. { src: "http://example.com/blah/wat.js" },
  710. { src: "http://example.com/blah/foo/bar.js" }
  711. ];
  712. }
  713. };
  714. _getCurrentScriptUrlFromError = function() {
  715. return "http://example.com/blah/foo/bar.js";
  716. };
  717. actual5 = _getDefaultSwfPath();
  718. _document = {
  719. getElementsByTagName: function(/* tagName */) {
  720. return [
  721. { src: "http://example.com/blah/foo.js" },
  722. { src: "http://example.com/blah/wat.js" },
  723. { src: "http://example.com/blah/bar.js" }
  724. ];
  725. }
  726. };
  727. _getCurrentScriptUrlFromError = function() {};
  728. actual6 = _getDefaultSwfPath();
  729. _document = {
  730. getElementsByTagName: function(/* tagName */) {
  731. return [
  732. { src: "http://example.org/blah/foo.js" },
  733. { src: "http://example.net/blah/wat.js" },
  734. { src: "http://example.com/blah/bar.js" }
  735. ];
  736. }
  737. };
  738. actual7 = _getDefaultSwfPath();
  739. _document = {
  740. getElementsByTagName: function(/* tagName */) {
  741. return [
  742. { src: "http://example.com/blah/foo.js" },
  743. { src: "http://example.com/blah/wat.js" },
  744. { src: "http://example.com/blah/foo/bar.js" }
  745. ];
  746. }
  747. };
  748. actual8 = _getDefaultSwfPath();
  749. _document = {
  750. getElementsByTagName: function(/* tagName */) {
  751. return [
  752. { src: "http://example.com/blah/foo.js" },
  753. { /* inline script */ },
  754. { src: "http://example.com/blah/foo/bar.js" }
  755. ];
  756. }
  757. };
  758. actual9 = _getDefaultSwfPath();
  759. _document = {
  760. getElementsByTagName: function(/* tagName */) {
  761. return [
  762. { src: "http://example.com/blah/foo.js" },
  763. { src: "http://example.com/blah/wat.js" },
  764. { /* inline script */ }
  765. ];
  766. }
  767. };
  768. actual10 = _getDefaultSwfPath();
  769. _document = {
  770. getElementsByTagName: function(/* tagName */) {
  771. return [
  772. { /* inline script */ }
  773. ];
  774. }
  775. };
  776. actual11 = _getDefaultSwfPath();
  777. assert.strictEqual(actual1, expected1, "Value derived from `document.currentScript`");
  778. assert.strictEqual(actual2, expected2, "Value derived from the only script");
  779. assert.strictEqual(actual3, expected3, "Value derived from `scripts[i].readyState === \"interactive\"`");
  780. assert.strictEqual(actual4, expected4, "Value derived from last script while `document.readyState === \"loading\"");
  781. assert.strictEqual(actual5, expected5, "Value derived from Error stack");
  782. assert.strictEqual(actual6, expected6, "Value derived from confirming all scripts have the same parent directory");
  783. assert.strictEqual(actual7, expected7, "No value can be confirmed due to differing script domains");
  784. assert.strictEqual(actual8, expected8, "No value can be confirmed due to differing script parent directories");
  785. assert.strictEqual(actual9, expected9, "No value can be confirmed due to the existence of inline scripts");
  786. assert.strictEqual(actual10, expected10, "No value can be confirmed as the last script is an inline script");
  787. assert.strictEqual(actual11, expected11, "No value can be confirmed as the only script is an inline script");
  788. });
  789. })(QUnit.module, QUnit.test);