unit.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  1. /*globals chai, spooks, require, tryer, suite, setup, test, setTimeout, Promise */
  2. (function (require, spooks) {
  3. 'use strict';
  4. var assert, modulePath;
  5. if (require === undefined) {
  6. assert = chai.assert;
  7. require = function () { return tryer; };
  8. } else {
  9. assert = require('chai').assert;
  10. spooks = require('spooks');
  11. modulePath = '../src/tryer';
  12. }
  13. suite('tryer:', function () {
  14. test('require does not throw', function () {
  15. assert.doesNotThrow(function () {
  16. require(modulePath);
  17. });
  18. });
  19. suite('require:', function () {
  20. var tryer;
  21. setup(function () {
  22. tryer = require(modulePath);
  23. });
  24. test('function is exported', function () {
  25. assert.isFunction(tryer);
  26. });
  27. test('tryer does not throw when options is missing', function () {
  28. assert.doesNotThrow(function () {
  29. tryer();
  30. });
  31. });
  32. test('tryer does not throw when options is object', function () {
  33. assert.doesNotThrow(function () {
  34. tryer({});
  35. });
  36. });
  37. suite('when passing immediately:', function () {
  38. var log, predicate, action, fail, pass;
  39. setup(function (done) {
  40. log = {};
  41. predicate = spooks.fn({ name: 'predicate', log: log, results: [ true ] });
  42. action = spooks.fn({ name: 'action', log: log });
  43. fail = spooks.fn({ name: 'fail', log: log, callback: done });
  44. pass = spooks.fn({ name: 'pass', log: log, callback: done });
  45. tryer({
  46. when: predicate,
  47. action: action,
  48. fail: fail,
  49. pass: pass,
  50. interval: 0,
  51. limit: 3
  52. });
  53. });
  54. test('predicate was called once', function () {
  55. assert.strictEqual(log.counts.predicate, 1);
  56. });
  57. test('action was called once', function () {
  58. assert.strictEqual(log.counts.action, 1);
  59. });
  60. test('fail was not called', function () {
  61. assert.strictEqual(log.counts.fail, 0);
  62. });
  63. test('pass was called once', function () {
  64. assert.strictEqual(log.counts.pass, 1);
  65. });
  66. });
  67. suite('when failing three times:', function () {
  68. var log, predicate, action, fail, pass;
  69. setup(function (done) {
  70. log = {};
  71. predicate = spooks.fn({ name: 'predicate', log: log, results: [ false ] });
  72. action = spooks.fn({ name: 'action', log: log });
  73. fail = spooks.fn({ name: 'fail', log: log, callback: done });
  74. pass = spooks.fn({ name: 'pass', log: log, callback: done });
  75. tryer({
  76. when: predicate,
  77. action: action,
  78. fail: fail,
  79. pass: pass,
  80. interval: 0,
  81. limit: 3
  82. });
  83. });
  84. test('predicate was called three times', function () {
  85. assert.strictEqual(log.counts.predicate, 3);
  86. });
  87. test('action was not called', function () {
  88. assert.strictEqual(log.counts.action, 0);
  89. });
  90. test('fail was called once', function () {
  91. assert.strictEqual(log.counts.fail, 1);
  92. });
  93. test('pass was not called', function () {
  94. assert.strictEqual(log.counts.pass, 0);
  95. });
  96. });
  97. suite('when failing five times:', function () {
  98. var log, predicate, action, fail;
  99. setup(function (done) {
  100. log = {};
  101. predicate = spooks.fn({ name: 'predicate', log: log, results: [ false ] });
  102. action = spooks.fn({ name: 'action', log: log, callback: done });
  103. fail = spooks.fn({ name: 'fail', log: log, callback: done });
  104. tryer({ when: predicate, action: action, fail: fail, interval: 0, limit: 5 });
  105. });
  106. test('predicate was called five times', function () {
  107. assert.strictEqual(log.counts.predicate, 5);
  108. });
  109. test('action was not called', function () {
  110. assert.strictEqual(log.counts.action, 0);
  111. });
  112. test('fail was called once', function () {
  113. assert.strictEqual(log.counts.fail, 1);
  114. });
  115. });
  116. suite('when failing exponentially:', function () {
  117. var log, timestamps, predicate, action, fail;
  118. setup(function (done) {
  119. log = {};
  120. timestamps = [];
  121. predicate = spooks.fn({
  122. name: 'predicate',
  123. log: log,
  124. results: [ false ],
  125. callback: function () {
  126. timestamps.push(Date.now());
  127. }
  128. });
  129. action = spooks.fn({ name: 'action', log: log, callback: done });
  130. fail = spooks.fn({ name: 'fail', log: log, callback: done });
  131. timestamps.push(Date.now());
  132. tryer({ when: predicate, action: action, fail: fail, interval: -10, limit: 4 });
  133. });
  134. test('five timestamps were recorded', function () {
  135. assert.lengthOf(timestamps, 5);
  136. });
  137. test('first interval is immediate', function () {
  138. assert.isTrue(timestamps[1] < timestamps[0] + 5);
  139. });
  140. test('second interval is about 10 ms', function () {
  141. assert.isTrue(timestamps[2] >= timestamps[1] + 10);
  142. assert.isTrue(timestamps[2] < timestamps[1] + 15);
  143. });
  144. test('third interval is about 20 ms', function () {
  145. assert.isTrue(timestamps[3] >= timestamps[2] + 20);
  146. assert.isTrue(timestamps[3] < timestamps[2] + 30);
  147. });
  148. test('fourth interval is about 40 ms', function () {
  149. assert.isTrue(timestamps[4] >= timestamps[3] + 40);
  150. assert.isTrue(timestamps[4] < timestamps[3] + 50);
  151. });
  152. });
  153. suite('until passing immediately:', function () {
  154. var log, predicate, action, fail, pass;
  155. setup(function (done) {
  156. log = {};
  157. predicate = spooks.fn({ name: 'predicate', log: log, results: [ true ] });
  158. action = spooks.fn({ name: 'action', log: log });
  159. fail = spooks.fn({ name: 'fail', log: log, callback: done });
  160. pass = spooks.fn({ name: 'pass', log: log, callback: done });
  161. tryer({
  162. until: predicate,
  163. action: action,
  164. fail: fail,
  165. pass: pass,
  166. interval: 0,
  167. limit: 3
  168. });
  169. });
  170. test('predicate was called once', function () {
  171. assert.strictEqual(log.counts.predicate, 1);
  172. });
  173. test('action was called once', function () {
  174. assert.strictEqual(log.counts.action, 1);
  175. });
  176. test('fail was not called', function () {
  177. assert.strictEqual(log.counts.fail, 0);
  178. });
  179. test('pass was called once', function () {
  180. assert.strictEqual(log.counts.pass, 1);
  181. });
  182. test('pass was called once', function () {
  183. assert.strictEqual(log.counts.pass, 1);
  184. });
  185. });
  186. suite('until failing three times:', function () {
  187. var log, predicate, action, fail, pass;
  188. setup(function (done) {
  189. log = {};
  190. predicate = spooks.fn({ name: 'predicate', log: log, results: [ false ] });
  191. action = spooks.fn({ name: 'action', log: log });
  192. fail = spooks.fn({ name: 'fail', log: log, callback: done });
  193. pass = spooks.fn({ name: 'pass', log: log, callback: done });
  194. tryer({
  195. until: predicate,
  196. action: action,
  197. fail: fail,
  198. pass: pass,
  199. interval: 0,
  200. limit: 3
  201. });
  202. });
  203. test('predicate was called three times', function () {
  204. assert.strictEqual(log.counts.predicate, 3);
  205. });
  206. test('action was called three times', function () {
  207. assert.strictEqual(log.counts.action, 3);
  208. });
  209. test('fail was called once', function () {
  210. assert.strictEqual(log.counts.fail, 1);
  211. });
  212. test('pass was not called', function () {
  213. assert.strictEqual(log.counts.pass, 0);
  214. });
  215. });
  216. suite('until failing five times:', function () {
  217. var log, predicate, action, fail;
  218. setup(function (done) {
  219. log = {};
  220. predicate = spooks.fn({ name: 'predicate', log: log, results: [ false ] });
  221. action = spooks.fn({ name: 'action', log: log });
  222. fail = spooks.fn({ name: 'fail', log: log, callback: done });
  223. tryer({ until: predicate, action: action, fail: fail, interval: 0, limit: 5 });
  224. });
  225. test('predicate was called five times', function () {
  226. assert.strictEqual(log.counts.predicate, 5);
  227. });
  228. test('action was called five times', function () {
  229. assert.strictEqual(log.counts.action, 5);
  230. });
  231. test('fail was called once', function () {
  232. assert.strictEqual(log.counts.fail, 1);
  233. });
  234. });
  235. suite('until failing exponentially:', function () {
  236. var log, timestamps, predicate, action, fail;
  237. setup(function (done) {
  238. log = {};
  239. timestamps = [];
  240. predicate = spooks.fn({
  241. name: 'predicate',
  242. log: log,
  243. results: [ false ],
  244. callback: function () {
  245. timestamps.push(Date.now());
  246. }
  247. });
  248. action = spooks.fn({ name: 'action', log: log });
  249. fail = spooks.fn({ name: 'fail', log: log, callback: done });
  250. timestamps.push(Date.now());
  251. tryer({ until: predicate, action: action, fail: fail, interval: -10, limit: 4 });
  252. });
  253. test('five timestamps were recorded', function () {
  254. assert.lengthOf(timestamps, 5);
  255. });
  256. test('first interval is immediate', function () {
  257. assert.isTrue(timestamps[1] < timestamps[0] + 5);
  258. });
  259. test('second interval is about 10 ms', function () {
  260. assert.isTrue(timestamps[2] >= timestamps[1] + 10);
  261. assert.isTrue(timestamps[2] < timestamps[1] + 20);
  262. });
  263. test('third interval is about 20 ms', function () {
  264. assert.isTrue(timestamps[3] >= timestamps[2] + 20);
  265. assert.isTrue(timestamps[3] < timestamps[2] + 30);
  266. });
  267. test('fourth interval is about 40 ms', function () {
  268. assert.isTrue(timestamps[4] >= timestamps[3] + 40);
  269. assert.isTrue(timestamps[4] < timestamps[3] + 50);
  270. });
  271. });
  272. suite('when failing once then passing and until failing twice then passing', function () {
  273. var log, predicateLoggers, predicates, action, fail, pass;
  274. setup(function (done) {
  275. log = {};
  276. predicateLoggers = {
  277. when: spooks.fn({ name: 'when', log: log }),
  278. until: spooks.fn({ name: 'until', log: log })
  279. };
  280. predicates = {
  281. when: function () {
  282. predicateLoggers.when.apply(this, arguments);
  283. if (log.counts.when === 1) {
  284. return false;
  285. }
  286. return true;
  287. },
  288. until: function () {
  289. predicateLoggers.until.apply(this, arguments);
  290. if (log.counts.until < 3) {
  291. return false;
  292. }
  293. return true;
  294. }
  295. };
  296. action = spooks.fn({ name: 'action', log: log });
  297. fail = spooks.fn({ name: 'fail', log: log, callback: done });
  298. pass = spooks.fn({ name: 'pass', log: log, callback: done });
  299. tryer({
  300. when: predicates.when,
  301. until: predicates.until,
  302. action: action,
  303. fail: fail,
  304. pass: pass,
  305. interval: 0,
  306. limit: 4
  307. });
  308. });
  309. test('when was called twice', function () {
  310. assert.strictEqual(log.counts.when, 2);
  311. });
  312. test('action was called three times', function () {
  313. assert.strictEqual(log.counts.action, 3);
  314. });
  315. test('until was called three times', function () {
  316. assert.strictEqual(log.counts.until, 3);
  317. });
  318. test('fail was not called', function () {
  319. assert.strictEqual(log.counts.fail, 0);
  320. });
  321. test('pass was called once', function () {
  322. assert.strictEqual(log.counts.pass, 1);
  323. });
  324. });
  325. suite('asynchronous action:', function () {
  326. var log, timestamps, predicate, action;
  327. setup(function (done) {
  328. log = {};
  329. timestamps = [];
  330. predicate = function () {
  331. timestamps.push(Date.now());
  332. return false;
  333. };
  334. action = function (tryerDone) {
  335. setTimeout(tryerDone, 10);
  336. };
  337. timestamps.push(Date.now());
  338. tryer({ until: predicate, action: action, fail: done, interval: 0, limit: 3 });
  339. });
  340. test('four timestamps were recorded', function () {
  341. assert.lengthOf(timestamps, 4);
  342. });
  343. test('first interval is about 10 ms', function () {
  344. assert.isTrue(timestamps[1] >= timestamps[0] + 10);
  345. assert.isTrue(timestamps[1] < timestamps[0] + 20);
  346. });
  347. test('second interval is about 10 ms', function () {
  348. assert.isTrue(timestamps[2] >= timestamps[1] + 10);
  349. assert.isTrue(timestamps[2] < timestamps[1] + 20);
  350. });
  351. test('third interval is about 10 ms', function () {
  352. assert.isTrue(timestamps[3] >= timestamps[2] + 10);
  353. assert.isTrue(timestamps[3] < timestamps[2] + 20);
  354. });
  355. });
  356. if (typeof Promise === 'function') {
  357. suite('promise-resolving action:', function () {
  358. var log, timestamps, predicate, action;
  359. setup(function (done) {
  360. log = {};
  361. timestamps = [];
  362. predicate = function () {
  363. timestamps.push(Date.now());
  364. return false;
  365. };
  366. action = function () {
  367. return new Promise(function (resolve) {
  368. setTimeout(resolve, 10);
  369. });
  370. };
  371. timestamps.push(Date.now());
  372. tryer({ until: predicate, action: action, fail: done, interval: 0, limit: 3 });
  373. });
  374. test('four timestamps were recorded', function () {
  375. assert.lengthOf(timestamps, 4);
  376. });
  377. test('first interval is about 10 ms', function () {
  378. assert.isTrue(timestamps[1] >= timestamps[0] + 10);
  379. assert.isTrue(timestamps[1] < timestamps[0] + 20);
  380. });
  381. test('second interval is about 10 ms', function () {
  382. assert.isTrue(timestamps[2] >= timestamps[1] + 10);
  383. assert.isTrue(timestamps[2] < timestamps[1] + 20);
  384. });
  385. test('third interval is about 10 ms', function () {
  386. assert.isTrue(timestamps[3] >= timestamps[2] + 10);
  387. assert.isTrue(timestamps[3] < timestamps[2] + 20);
  388. });
  389. });
  390. suite('promise-rejecting action:', function () {
  391. var log, timestamps, predicate, action;
  392. setup(function (done) {
  393. log = {};
  394. timestamps = [];
  395. predicate = function () {
  396. timestamps.push(Date.now());
  397. return false;
  398. };
  399. action = function () {
  400. return new Promise(function (_, reject) {
  401. setTimeout(reject, 10);
  402. });
  403. };
  404. timestamps.push(Date.now());
  405. tryer({ until: predicate, action: action, fail: done, interval: 0, limit: 3 });
  406. });
  407. test('four timestamps were recorded', function () {
  408. assert.lengthOf(timestamps, 4);
  409. });
  410. test('first interval is about 10 ms', function () {
  411. assert.isTrue(timestamps[1] >= timestamps[0] + 10);
  412. assert.isTrue(timestamps[1] < timestamps[0] + 20);
  413. });
  414. test('second interval is about 10 ms', function () {
  415. assert.isTrue(timestamps[2] >= timestamps[1] + 10);
  416. assert.isTrue(timestamps[2] < timestamps[1] + 20);
  417. });
  418. test('third interval is about 10 ms', function () {
  419. assert.isTrue(timestamps[3] >= timestamps[2] + 10);
  420. assert.isTrue(timestamps[3] < timestamps[2] + 20);
  421. });
  422. });
  423. }
  424. });
  425. });
  426. }(
  427. typeof require === 'function' ? require : undefined,
  428. typeof spooks === 'object' ? spooks : undefined)
  429. );