continuationtestcase_test.js 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. // Copyright 2009 The Closure Library Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. goog.provide('goog.testing.ContinuationTestCaseTest');
  15. goog.setTestOnly('goog.testing.ContinuationTestCaseTest');
  16. goog.require('goog.events');
  17. goog.require('goog.events.EventTarget');
  18. goog.require('goog.testing.ContinuationTestCase');
  19. goog.require('goog.testing.MockClock');
  20. goog.require('goog.testing.PropertyReplacer');
  21. goog.require('goog.testing.TestCase');
  22. goog.require('goog.testing.jsunit');
  23. /**
  24. * @fileoverview This test file uses the ContinuationTestCase to test itself,
  25. * which is a little confusing. It's also difficult to write a truly effective
  26. * test, since testing a failure causes an actual failure in the test runner.
  27. * All tests have been manually verified using a sophisticated combination of
  28. * alerts and false assertions.
  29. */
  30. var testCase = new goog.testing.ContinuationTestCase('Continuation Test Case');
  31. testCase.autoDiscoverTests();
  32. // Standalone Closure Test Runner.
  33. if (typeof G_testRunner != 'undefined') {
  34. G_testRunner.initialize(testCase);
  35. }
  36. var clock = new goog.testing.MockClock();
  37. var count = 0;
  38. var stubs = new goog.testing.PropertyReplacer();
  39. function setUpPage() {
  40. count = testCase.getCount();
  41. }
  42. /**
  43. * Resets the mock clock. Includes a wait step to verify that setUp routines
  44. * can contain continuations.
  45. */
  46. function setUp() {
  47. waitForTimeout(function() {
  48. // Pointless assertion to verify that setUp methods can contain waits.
  49. assertEquals(count, testCase.getCount());
  50. }, 0);
  51. clock.reset();
  52. }
  53. /**
  54. * Uninstalls the mock clock if it was installed, and restores the Step timeout
  55. * functions to the default window implementations.
  56. */
  57. function tearDown() {
  58. clock.uninstall();
  59. stubs.reset();
  60. waitForTimeout(function() {
  61. // Pointless assertion to verify that tearDown methods can contain waits.
  62. assertTrue(testCase.now() >= testCase.startTime_);
  63. }, 0);
  64. }
  65. /**
  66. * Installs the Mock Clock and replaces the Step timeouts with the mock
  67. * implementations.
  68. */
  69. function installMockClock() {
  70. clock.install();
  71. // Overwrite the "protected" setTimeout and clearTimeout with the versions
  72. // replaced by MockClock. Normal tests should never do this, but we need to
  73. // test the ContinuationTest itself.
  74. stubs.set(
  75. goog.testing.ContinuationTestCase.Step, 'protectedClearTimeout_',
  76. window.clearTimeout);
  77. stubs.set(
  78. goog.testing.ContinuationTestCase.Step, 'protectedSetTimeout_',
  79. window.setTimeout);
  80. }
  81. /**
  82. * @return {goog.testing.ContinuationTestCase.Step} A generic step in a
  83. * continuation test.
  84. */
  85. function getSampleStep() {
  86. return new goog.testing.ContinuationTestCase.Step('test', function() {});
  87. }
  88. /**
  89. * @return {goog.testing.ContinuationTestCase.ContinuationTest} A simple
  90. * continuation test with generic setUp, test, and tearDown functions.
  91. */
  92. function getSampleTest() {
  93. var setupStep = new goog.testing.TestCase.Test('setup', function() {});
  94. var testStep = new goog.testing.TestCase.Test('test', function() {});
  95. var teardownStep = new goog.testing.TestCase.Test('teardown', function() {});
  96. return new goog.testing.ContinuationTestCase.ContinuationTest(
  97. setupStep, testStep, teardownStep);
  98. }
  99. function testStepWaiting() {
  100. var step = getSampleStep();
  101. assertTrue(step.waiting);
  102. }
  103. function testStepSetTimeout() {
  104. installMockClock();
  105. var step = getSampleStep();
  106. var timeoutReached = false;
  107. step.setTimeout(function() { timeoutReached = true }, 100);
  108. clock.tick(50);
  109. assertFalse(timeoutReached);
  110. clock.tick(50);
  111. assertTrue(timeoutReached);
  112. }
  113. function testStepClearTimeout() {
  114. var step = new goog.testing.ContinuationTestCase.Step('test', function() {});
  115. var timeoutReached = false;
  116. step.setTimeout(function() { timeoutReached = true }, 100);
  117. clock.tick(50);
  118. assertFalse(timeoutReached);
  119. step.clearTimeout();
  120. clock.tick(50);
  121. assertFalse(timeoutReached);
  122. }
  123. function testTestPhases() {
  124. var test = getSampleTest();
  125. assertEquals('setup', test.getCurrentPhase()[0].name);
  126. test.cancelCurrentPhase();
  127. assertEquals('test', test.getCurrentPhase()[0].name);
  128. test.cancelCurrentPhase();
  129. assertEquals('teardown', test.getCurrentPhase()[0].name);
  130. test.cancelCurrentPhase();
  131. assertNull(test.getCurrentPhase());
  132. }
  133. function testTestSetError() {
  134. var test = getSampleTest();
  135. var error1 = new Error('Oh noes!');
  136. var error2 = new Error('B0rken.');
  137. assertNull(test.getError());
  138. test.setError(error1);
  139. assertEquals(error1, test.getError());
  140. test.setError(error2);
  141. assertEquals(
  142. 'Once an error has been set, it should not be overwritten.', error1,
  143. test.getError());
  144. }
  145. function testAddStep() {
  146. var test = getSampleTest();
  147. var step = getSampleStep();
  148. // Try adding a step to each phase and then cancelling the phase.
  149. for (var i = 0; i < 3; i++) {
  150. assertEquals(1, test.getCurrentPhase().length);
  151. test.addStep(step);
  152. assertEquals(2, test.getCurrentPhase().length);
  153. assertEquals(step, test.getCurrentPhase()[1]);
  154. test.cancelCurrentPhase();
  155. }
  156. assertNull(test.getCurrentPhase());
  157. }
  158. function testCancelTestPhase() {
  159. var test = getSampleTest();
  160. test.cancelTestPhase();
  161. assertEquals('teardown', test.getCurrentPhase()[0].name);
  162. test = getSampleTest();
  163. test.cancelCurrentPhase();
  164. test.cancelTestPhase();
  165. assertEquals('teardown', test.getCurrentPhase()[0].name);
  166. test = getSampleTest();
  167. test.cancelTestPhase();
  168. test.cancelTestPhase();
  169. assertEquals('teardown', test.getCurrentPhase()[0].name);
  170. }
  171. function testWaitForTimeout() {
  172. var reachedA = false;
  173. var reachedB = false;
  174. var reachedC = false;
  175. waitForTimeout(function a() {
  176. reachedA = true;
  177. assertTrue('A must be true at callback a.', reachedA);
  178. assertFalse('B must be false at callback a.', reachedB);
  179. assertFalse('C must be false at callback a.', reachedC);
  180. }, 10);
  181. waitForTimeout(function b() {
  182. reachedB = true;
  183. assertTrue('A must be true at callback b.', reachedA);
  184. assertTrue('B must be true at callback b.', reachedB);
  185. assertFalse('C must be false at callback b.', reachedC);
  186. }, 20);
  187. waitForTimeout(function c() {
  188. reachedC = true;
  189. assertTrue('A must be true at callback c.', reachedA);
  190. assertTrue('B must be true at callback c.', reachedB);
  191. assertTrue('C must be true at callback c.', reachedC);
  192. }, 20);
  193. assertFalse('a', reachedA);
  194. assertFalse('b', reachedB);
  195. assertFalse('c', reachedC);
  196. }
  197. function testWaitForEvent() {
  198. var et = new goog.events.EventTarget();
  199. var eventFired = false;
  200. goog.events.listen(et, 'testPrefire', function() {
  201. eventFired = true;
  202. et.dispatchEvent('test');
  203. });
  204. waitForEvent(et, 'test', function() { assertTrue(eventFired); });
  205. et.dispatchEvent('testPrefire');
  206. }
  207. function testWaitForCondition() {
  208. var counter = 0;
  209. waitForCondition(
  210. function() { return ++counter >= 2; },
  211. function() { assertEquals(2, counter); }, 10, 200);
  212. }
  213. function testOutOfOrderWaits() {
  214. var counter = 0;
  215. // Note that if the delta between the timeout is too small, two
  216. // continuation may be invoked at the same timer tick, using the
  217. // registration order.
  218. waitForTimeout(function() { assertEquals(3, ++counter); }, 200);
  219. waitForTimeout(function() { assertEquals(1, ++counter); }, 0);
  220. waitForTimeout(function() { assertEquals(2, ++counter); }, 100);
  221. }
  222. /*
  223. * Any of the test functions below (except the condition check passed into
  224. * waitForCondition) can raise an assertion successfully. Any level of nested
  225. * test steps should be possible, in any configuration.
  226. */
  227. var testObj;
  228. function testCrazyNestedWaitFunction() {
  229. testObj = {lock: true, et: new goog.events.EventTarget(), steps: 0};
  230. waitForTimeout(handleTimeout, 10);
  231. waitForEvent(testObj.et, 'test', handleEvent);
  232. waitForCondition(condition, handleCondition, 1);
  233. }
  234. function handleTimeout() {
  235. testObj.steps++;
  236. assertEquals('handleTimeout should be called first.', 1, testObj.steps);
  237. waitForTimeout(fireEvent, 10);
  238. }
  239. function fireEvent() {
  240. testObj.steps++;
  241. assertEquals('fireEvent should be called second.', 2, testObj.steps);
  242. testObj.et.dispatchEvent('test');
  243. }
  244. function handleEvent() {
  245. testObj.steps++;
  246. assertEquals('handleEvent should be called third.', 3, testObj.steps);
  247. testObj.lock = false;
  248. }
  249. function condition() {
  250. return !testObj.lock;
  251. }
  252. function handleCondition() {
  253. assertFalse(testObj.lock);
  254. testObj.steps++;
  255. assertEquals('handleCondition should be called last.', 4, testObj.steps);
  256. }