PageRenderTime 50ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/test/test.js

https://github.com/jineeshjohn/qunit
JavaScript | 628 lines | 487 code | 106 blank | 35 comment | 25 complexity | 100d2fce08954e3a27d25a3e3b8af044 MD5 | raw file
  1. test("module without setup/teardown (default)", function() {
  2. expect(1);
  3. ok(true);
  4. });
  5. test("expect in test", 3, function() {
  6. ok(true);
  7. ok(true);
  8. ok(true);
  9. });
  10. test("expect in test", 1, function() {
  11. ok(true);
  12. });
  13. test("expect query and multiple issue", function() {
  14. expect(2);
  15. ok(true);
  16. var expected = expect();
  17. equal(expected, 2);
  18. expect(expected + 1);
  19. ok(true);
  20. });
  21. QUnit.module("assertion helpers");
  22. QUnit.test( "QUnit.assert compatibility", 5, function( assert ) {
  23. assert.ok( true, "Calling method on `assert` argument to test() callback" );
  24. // Should also work, although discouraged and not documented
  25. QUnit.assert.ok( true, "Calling method on QUnit.assert object" );
  26. // Test compatibility aliases
  27. QUnit.ok( true, "Calling aliased method in QUnit root object" );
  28. ok( true, "Calling aliased function in global namespace" );
  29. // Regression fix for #341
  30. // The assert-context way of testing discouraged global variables,
  31. // it doesn't make sense of it itself to be a global variable.
  32. // Only allows for mistakes (e.g. forgetting to list 'assert' as parameter)
  33. assert.notStrictEqual( window.assert, QUnit.assert, "Assert does not get exposed as a global variable" );
  34. });
  35. module("setup test", {
  36. setup: function() {
  37. ok(true);
  38. }
  39. });
  40. test("module with setup", function() {
  41. expect(2);
  42. ok(true);
  43. });
  44. test("module with setup, expect in test call", 2, function() {
  45. ok(true);
  46. });
  47. var state;
  48. module("setup/teardown test", {
  49. setup: function() {
  50. state = true;
  51. ok(true);
  52. // Assert that we can introduce and delete globals in setup/teardown
  53. // without noglobals sounding any alarm.
  54. // Using an implied global variable instead of explicit window property
  55. // because there is no way to delete a window.property in IE6-8
  56. // `delete x` only works for `x = 1, and `delete window.x` throws exception.
  57. // No one-code fits all solution possible afaic. Resort to @cc.
  58. /*@cc_on
  59. @if (@_jscript_version < 9)
  60. x = 1;
  61. @else @*/
  62. window.x = 1;
  63. /*@end
  64. @*/
  65. },
  66. teardown: function() {
  67. ok(true);
  68. /*@cc_on
  69. @if (@_jscript_version < 9)
  70. delete x;
  71. @else @*/
  72. delete window.x;
  73. /*@end
  74. @*/
  75. }
  76. });
  77. test("module with setup/teardown", function() {
  78. expect(3);
  79. ok(true);
  80. });
  81. module("setup/teardown test 2");
  82. test("module without setup/teardown", function() {
  83. expect(1);
  84. ok(true);
  85. });
  86. var orgDate;
  87. module("Date test", {
  88. setup: function() {
  89. orgDate = Date;
  90. window.Date = function () {
  91. ok( false, 'QUnit should internally be independant from Date-related manipulation and testing' );
  92. return new orgDate();
  93. };
  94. },
  95. teardown: function() {
  96. window.Date = orgDate;
  97. }
  98. });
  99. test("sample test for Date test", function () {
  100. expect(1);
  101. ok(true);
  102. });
  103. if (typeof setTimeout !== 'undefined') {
  104. state = 'fail';
  105. module("teardown and stop", {
  106. teardown: function() {
  107. equal(state, "done", "Test teardown.");
  108. }
  109. });
  110. test("teardown must be called after test ended", function() {
  111. expect(1);
  112. stop();
  113. setTimeout(function() {
  114. state = "done";
  115. start();
  116. }, 13);
  117. });
  118. test("parameter passed to stop increments semaphore n times", function() {
  119. expect(1);
  120. stop(3);
  121. setTimeout(function() {
  122. state = "not enough starts";
  123. start();
  124. start();
  125. }, 13);
  126. setTimeout(function() {
  127. state = "done";
  128. start();
  129. }, 15);
  130. });
  131. test("parameter passed to start decrements semaphore n times", function() {
  132. expect(1);
  133. stop();
  134. stop();
  135. stop();
  136. setTimeout(function() {
  137. state = "done";
  138. start(3);
  139. }, 18);
  140. });
  141. module("async setup test", {
  142. setup: function() {
  143. stop();
  144. setTimeout(function() {
  145. ok(true);
  146. start();
  147. }, 500);
  148. }
  149. });
  150. asyncTest("module with async setup", function() {
  151. expect(2);
  152. ok(true);
  153. start();
  154. });
  155. module("async teardown test", {
  156. teardown: function() {
  157. stop();
  158. setTimeout(function() {
  159. ok(true);
  160. start();
  161. }, 500);
  162. }
  163. });
  164. asyncTest("module with async teardown", function() {
  165. expect(2);
  166. ok(true);
  167. start();
  168. });
  169. module("asyncTest");
  170. asyncTest("asyncTest", function() {
  171. expect(2);
  172. ok(true);
  173. setTimeout(function() {
  174. state = "done";
  175. ok(true);
  176. start();
  177. }, 13);
  178. });
  179. asyncTest("asyncTest", 2, function() {
  180. ok(true);
  181. setTimeout(function() {
  182. state = "done";
  183. ok(true);
  184. start();
  185. }, 13);
  186. });
  187. test("sync", 2, function() {
  188. stop();
  189. setTimeout(function() {
  190. ok(true);
  191. start();
  192. }, 13);
  193. stop();
  194. setTimeout(function() {
  195. ok(true);
  196. start();
  197. }, 125);
  198. });
  199. test("test synchronous calls to stop", 2, function() {
  200. stop();
  201. setTimeout(function() {
  202. ok(true, 'first');
  203. start();
  204. stop();
  205. setTimeout(function() {
  206. ok(true, 'second');
  207. start();
  208. }, 150);
  209. }, 150);
  210. });
  211. }
  212. module("save scope", {
  213. setup: function() {
  214. this.foo = "bar";
  215. },
  216. teardown: function() {
  217. deepEqual(this.foo, "bar");
  218. }
  219. });
  220. test("scope check", function() {
  221. expect(2);
  222. deepEqual(this.foo, "bar");
  223. });
  224. module("simple testEnvironment setup", {
  225. foo: "bar",
  226. // example of meta-data
  227. bugid: "#5311"
  228. });
  229. test("scope check", function() {
  230. deepEqual(this.foo, "bar");
  231. });
  232. test("modify testEnvironment",function() {
  233. expect(0);
  234. this.foo="hamster";
  235. });
  236. test("testEnvironment reset for next test",function() {
  237. deepEqual(this.foo, "bar");
  238. });
  239. module("testEnvironment with object", {
  240. options:{
  241. recipe:"soup",
  242. ingredients:["hamster","onions"]
  243. }
  244. });
  245. test("scope check", function() {
  246. deepEqual(this.options, {recipe:"soup",ingredients:["hamster","onions"]}) ;
  247. });
  248. test("modify testEnvironment",function() {
  249. expect(0);
  250. // since we do a shallow copy, the testEnvironment can be modified
  251. this.options.ingredients.push("carrots");
  252. });
  253. test("testEnvironment reset for next test",function() {
  254. deepEqual(this.options, {recipe:"soup",ingredients:["hamster","onions","carrots"]}, "Is this a bug or a feature? Could do a deep copy") ;
  255. });
  256. module("testEnvironment tests");
  257. function makeurl() {
  258. var testEnv = QUnit.current_testEnvironment;
  259. var url = testEnv.url || 'http://example.com/search';
  260. var q = testEnv.q || 'a search test';
  261. return url + '?q='+encodeURIComponent(q);
  262. }
  263. test("makeurl working",function() {
  264. equal( QUnit.current_testEnvironment, this, 'The current testEnvironment is global');
  265. equal( makeurl(), 'http://example.com/search?q=a%20search%20test', 'makeurl returns a default url if nothing specified in the testEnvironment');
  266. });
  267. module("testEnvironment with makeurl settings", {
  268. url: 'http://google.com/',
  269. q: 'another_search_test'
  270. });
  271. test("makeurl working with settings from testEnvironment", function() {
  272. equal( makeurl(), 'http://google.com/?q=another_search_test', 'rather than passing arguments, we use test metadata to from the url');
  273. });
  274. module("jsDump");
  275. test("jsDump output", function() {
  276. equal( QUnit.jsDump.parse([1, 2]), "[\n 1,\n 2\n]" );
  277. equal( QUnit.jsDump.parse({top: 5, left: 0}), "{\n \"left\": 0,\n \"top\": 5\n}" );
  278. if (typeof document !== 'undefined' && document.getElementById("qunit-header")) {
  279. equal( QUnit.jsDump.parse(document.getElementById("qunit-header")), "<h1 id=\"qunit-header\"></h1>" );
  280. equal( QUnit.jsDump.parse(document.getElementsByTagName("h1")), "[\n <h1 id=\"qunit-header\"></h1>\n]" );
  281. }
  282. });
  283. module("assertions");
  284. test("raises",function() {
  285. function CustomError( message ) {
  286. this.message = message;
  287. }
  288. CustomError.prototype.toString = function() {
  289. return this.message;
  290. };
  291. throws(
  292. function() {
  293. throw "my error";
  294. }
  295. );
  296. throws(
  297. function() {
  298. throw "my error";
  299. },
  300. "simple string throw, no 'expected' value given"
  301. );
  302. throws(
  303. function() {
  304. throw new CustomError();
  305. },
  306. CustomError,
  307. 'thrown error is an instance of CustomError'
  308. );
  309. throws(
  310. function() {
  311. throw new CustomError("some error description");
  312. },
  313. /description/,
  314. "use a regex to match against the stringified error"
  315. );
  316. throws(
  317. function() {
  318. throw new CustomError("some error description");
  319. },
  320. function( err ) {
  321. if ( (err instanceof CustomError) && /description/.test(err) ) {
  322. return true;
  323. }
  324. },
  325. "custom validation function"
  326. );
  327. throws(
  328. function() {
  329. /*jshint evil:true */
  330. ( window.execScript || function( data ) {
  331. window["eval"].call( window, data );
  332. })( "throw 'error';" );
  333. },
  334. 'globally-executed errors caught'
  335. );
  336. this.CustomError = CustomError;
  337. throws(
  338. function() {
  339. throw new this.CustomError("some error description");
  340. },
  341. /description/,
  342. "throw error from property of 'this' context"
  343. );
  344. raises(
  345. function() {
  346. throw "error";
  347. },
  348. "simple throw, asserting with deprecated raises() function"
  349. );
  350. });
  351. if (typeof document !== "undefined") {
  352. module("fixture");
  353. test("setup", function() {
  354. expect(0);
  355. document.getElementById("qunit-fixture").innerHTML = "foobar";
  356. });
  357. test("basics", function() {
  358. equal( document.getElementById("qunit-fixture").innerHTML, "test markup", "automatically reset" );
  359. });
  360. test("running test name displayed", function() {
  361. expect(2);
  362. var displaying = document.getElementById("qunit-testresult");
  363. ok( /running test name displayed/.test(displaying.innerHTML), "Expect test name to be found in displayed text" );
  364. ok( /fixture/.test(displaying.innerHTML), "Expect module name to be found in displayed text" );
  365. });
  366. }
  367. module("custom assertions");
  368. (function() {
  369. function mod2(value, expected, message) {
  370. var actual = value % 2;
  371. QUnit.push(actual == expected, actual, expected, message);
  372. }
  373. test("mod2", function() {
  374. mod2(2, 0, "2 % 2 == 0");
  375. mod2(3, 1, "3 % 2 == 1");
  376. });
  377. })();
  378. module("recursions");
  379. function Wrap(x) {
  380. this.wrap = x;
  381. if (x === undefined) {
  382. this.first = true;
  383. }
  384. }
  385. function chainwrap(depth, first, prev) {
  386. depth = depth || 0;
  387. var last = prev || new Wrap();
  388. first = first || last;
  389. if (depth == 1) {
  390. first.wrap = last;
  391. }
  392. if (depth > 1) {
  393. last = chainwrap(depth-1, first, new Wrap(last));
  394. }
  395. return last;
  396. }
  397. test("check jsDump recursion", function() {
  398. expect(4);
  399. var noref = chainwrap(0);
  400. var nodump = QUnit.jsDump.parse(noref);
  401. equal(nodump, '{\n "first": true,\n "wrap": undefined\n}');
  402. var selfref = chainwrap(1);
  403. var selfdump = QUnit.jsDump.parse(selfref);
  404. equal(selfdump, '{\n "first": true,\n "wrap": recursion(-1)\n}');
  405. var parentref = chainwrap(2);
  406. var parentdump = QUnit.jsDump.parse(parentref);
  407. equal(parentdump, '{\n "wrap": {\n "first": true,\n "wrap": recursion(-2)\n }\n}');
  408. var circref = chainwrap(10);
  409. var circdump = QUnit.jsDump.parse(circref);
  410. ok(new RegExp("recursion\\(-10\\)").test(circdump), "(" +circdump + ") should show -10 recursion level");
  411. });
  412. test("check (deep-)equal recursion", function() {
  413. var noRecursion = chainwrap(0);
  414. equal(noRecursion, noRecursion, "I should be equal to me.");
  415. deepEqual(noRecursion, noRecursion, "... and so in depth.");
  416. var selfref = chainwrap(1);
  417. equal(selfref, selfref, "Even so if I nest myself.");
  418. deepEqual(selfref, selfref, "... into the depth.");
  419. var circref = chainwrap(10);
  420. equal(circref, circref, "Or hide that through some levels of indirection.");
  421. deepEqual(circref, circref, "... and checked on all levels!");
  422. });
  423. test('Circular reference with arrays', function() {
  424. // pure array self-ref
  425. var arr = [];
  426. arr.push(arr);
  427. var arrdump = QUnit.jsDump.parse(arr);
  428. equal(arrdump, '[\n recursion(-1)\n]');
  429. equal(arr, arr[0], 'no endless stack when trying to dump arrays with circular ref');
  430. // mix obj-arr circular ref
  431. var obj = {};
  432. var childarr = [obj];
  433. obj.childarr = childarr;
  434. var objdump = QUnit.jsDump.parse(obj);
  435. var childarrdump = QUnit.jsDump.parse(childarr);
  436. equal(objdump, '{\n "childarr": [\n recursion(-2)\n ]\n}');
  437. equal(childarrdump, '[\n {\n "childarr": recursion(-2)\n }\n]');
  438. equal(obj.childarr, childarr, 'no endless stack when trying to dump array/object mix with circular ref');
  439. equal(childarr[0], obj, 'no endless stack when trying to dump array/object mix with circular ref');
  440. });
  441. test('Circular reference - test reported by soniciq in #105', function() {
  442. var MyObject = function() {};
  443. MyObject.prototype.parent = function(obj) {
  444. if (obj === undefined) { return this._parent; }
  445. this._parent = obj;
  446. };
  447. MyObject.prototype.children = function(obj) {
  448. if (obj === undefined) { return this._children; }
  449. this._children = obj;
  450. };
  451. var a = new MyObject(),
  452. b = new MyObject();
  453. var barr = [b];
  454. a.children(barr);
  455. b.parent(a);
  456. equal(a.children(), barr);
  457. deepEqual(a.children(), [b]);
  458. });
  459. (function() {
  460. var reset = QUnit.reset;
  461. module("reset");
  462. test("reset runs assertions", function() {
  463. expect(0);
  464. QUnit.reset = function() {
  465. ok( false, "reset should not modify test status" );
  466. reset.apply( this, arguments );
  467. };
  468. });
  469. test("reset runs assertions, cleanup", function() {
  470. expect(0);
  471. QUnit.reset = reset;
  472. });
  473. })();
  474. function testAfterDone() {
  475. var testName = "ensure has correct number of assertions";
  476. function secondAfterDoneTest() {
  477. QUnit.config.done = [];
  478. // Because when this does happen, the assertion count parameter doesn't actually
  479. // work we use this test to check the assertion count.
  480. module("check previous test's assertion counts");
  481. test('count previous two test\'s assertions', function () {
  482. var i, countNodes,
  483. spans = document.getElementsByTagName('span'),
  484. tests = [];
  485. // Find these two tests
  486. for (i = 0; i < spans.length; i++) {
  487. if (spans[i].innerHTML.indexOf(testName) !== -1) {
  488. tests.push(spans[i]);
  489. }
  490. }
  491. // Walk dom to counts.
  492. countNodes = tests[0].nextSibling.nextSibling.getElementsByTagName('b');
  493. equal(countNodes[1].innerHTML, "99");
  494. countNodes = tests[1].nextSibling.nextSibling.getElementsByTagName('b');
  495. equal(countNodes[1].innerHTML, "99");
  496. });
  497. }
  498. QUnit.config.done = [];
  499. QUnit.done(secondAfterDoneTest);
  500. module("Synchronous test after load of page");
  501. asyncTest('Async test', function() {
  502. start();
  503. for (var i = 1; i < 100; i++) {
  504. ok(i);
  505. }
  506. });
  507. test(testName, 99, function() {
  508. for (var i = 1; i < 100; i++) {
  509. ok(i);
  510. }
  511. });
  512. // We need two of these types of tests in order to ensure that assertions
  513. // don't move between tests.
  514. test(testName + ' 2', 99, function() {
  515. for (var i = 1; i < 100; i++) {
  516. ok(i);
  517. }
  518. });
  519. }
  520. if (typeof setTimeout !== 'undefined') {
  521. QUnit.done(testAfterDone);
  522. }