job-test.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555
  1. 'use strict';
  2. var sinon = require('sinon');
  3. var main = require('../package.json').main;
  4. var schedule = require('../' + main);
  5. var es6;
  6. try {
  7. eval('(function* () {})()');
  8. es6 = require('./es6/job-test')(schedule);
  9. } catch (e) {}
  10. var clock;
  11. module.exports = {
  12. setUp: function(cb) {
  13. clock = sinon.useFakeTimers();
  14. cb();
  15. },
  16. "Job constructor": {
  17. "Accepts Job name and function to run": function(test) {
  18. var job = new schedule.Job('the job', function() {});
  19. test.equal(job.name, 'the job');
  20. test.done();
  21. },
  22. "Job name is optional and will be auto-generated": function(test) {
  23. var job = new schedule.Job();
  24. test.ok(job.name);
  25. test.done();
  26. },
  27. "Uses unique names across auto-generated Job names": function(test) {
  28. var job1 = new schedule.Job();
  29. var job2 = new schedule.Job();
  30. test.notEqual(job1.name, job2.name);
  31. test.done();
  32. }
  33. },
  34. "#schedule(Date)": {
  35. "Runs job once at some date": function(test) {
  36. test.expect(1);
  37. var job = new schedule.Job(function() {
  38. test.ok(true);
  39. });
  40. job.schedule(new Date(Date.now() + 3000));
  41. setTimeout(function() {
  42. test.done();
  43. }, 3250);
  44. clock.tick(3250);
  45. },
  46. "Cancel next job before it runs": function(test) {
  47. test.expect(1);
  48. var job = new schedule.Job(function() {
  49. test.ok(true);
  50. });
  51. job.schedule(new Date(Date.now() + 1500));
  52. job.schedule(new Date(Date.now() + 3000));
  53. job.cancelNext();
  54. setTimeout(function() {
  55. test.done();
  56. }, 3250);
  57. clock.tick(3250);
  58. },
  59. "Run job on specified date": function(test) {
  60. test.expect(1);
  61. var job = new schedule.Job(function() {
  62. test.ok(true);
  63. });
  64. job.runOnDate(new Date(Date.now() + 3000));
  65. setTimeout(function() {
  66. test.done();
  67. }, 3250);
  68. clock.tick(3250);
  69. },
  70. "Run job in generator": function(test) {
  71. if (!es6) {
  72. test.expect(0);
  73. test.done();
  74. return;
  75. }
  76. es6.jobInGenerator(test);
  77. clock.tick(3250);
  78. },
  79. "Context is passed into generator correctly": function(test) {
  80. if (!es6) {
  81. test.expect(0);
  82. test.done();
  83. return;
  84. }
  85. es6.jobContextInGenerator(test);
  86. clock.tick(3250);
  87. },
  88. "Won't run job if scheduled in the past": function(test) {
  89. test.expect(0);
  90. var job = new schedule.Job(function() {
  91. test.ok(false);
  92. });
  93. job.schedule(new Date(Date.now() - 3000));
  94. setTimeout(function() {
  95. test.done();
  96. }, 1000);
  97. clock.tick(1000);
  98. },
  99. "Jobs still run after scheduling a Job in the past": function(test) {
  100. test.expect(1);
  101. var pastJob = new schedule.Job(function() {
  102. // Should not run, blow up if it does
  103. test.ok(false);
  104. });
  105. pastJob.schedule(new Date(Date.now() - 3000));
  106. var job = new schedule.Job(function() {
  107. test.ok(true);
  108. });
  109. job.schedule(new Date(Date.now() + 3000));
  110. setTimeout(function() {
  111. test.done();
  112. }, 3250);
  113. clock.tick(3250);
  114. },
  115. "Job emits 'scheduled' event with 'run at' Date": function(test) {
  116. test.expect(1);
  117. var date = new Date(Date.now() + 3000);
  118. var job = new schedule.Job(function() {
  119. test.done();
  120. });
  121. job.on('scheduled', function(runAtDate) {
  122. test.equal(runAtDate.getTime(), date.getTime());
  123. });
  124. job.schedule(date);
  125. clock.tick(3250);
  126. }
  127. },
  128. "#schedule(Date, fn)": {
  129. "Runs job once at some date, calls callback when done": function(test) {
  130. test.expect(1);
  131. var job = new schedule.Job(function() {}, function() {
  132. test.ok(true);
  133. });
  134. job.schedule(new Date(Date.now() + 3000));
  135. setTimeout(function() {
  136. test.done();
  137. }, 3250);
  138. clock.tick(3250);
  139. }
  140. },
  141. "#schedule(RecurrenceRule)": {
  142. "Runs job at interval based on recur rule, repeating indefinitely": function(test) {
  143. test.expect(3);
  144. var job = new schedule.Job(function() {
  145. test.ok(true);
  146. });
  147. var rule = new schedule.RecurrenceRule();
  148. rule.second = null; // fire every second
  149. job.schedule(rule);
  150. setTimeout(function() {
  151. job.cancel();
  152. test.done();
  153. }, 3250);
  154. clock.tick(3250);
  155. },
  156. "Job emits 'scheduled' event for every next invocation": function(test) {
  157. // Job will run 3 times but be scheduled 4 times, 4th run never happens
  158. // due to cancel.
  159. test.expect(4);
  160. var job = new schedule.Job(function() {});
  161. job.on('scheduled', function(runOnDate) {
  162. test.ok(true);
  163. });
  164. var rule = new schedule.RecurrenceRule();
  165. rule.second = null; // fire every second
  166. job.schedule(rule);
  167. setTimeout(function() {
  168. job.cancel();
  169. test.done();
  170. }, 3250);
  171. clock.tick(3250);
  172. },
  173. "Doesn't invoke job if recur rule schedules it in the past": function(test) {
  174. test.expect(0);
  175. var job = new schedule.Job(function() {
  176. test.ok(false);
  177. });
  178. var rule = new schedule.RecurrenceRule();
  179. rule.year = 2000;
  180. job.schedule(rule);
  181. setTimeout(function() {
  182. job.cancel();
  183. test.done();
  184. }, 1000);
  185. clock.tick(1000);
  186. }
  187. },
  188. "#schedule({...})": {
  189. "Runs job at interval based on object, repeating indefinitely": function(test) {
  190. test.expect(3);
  191. var job = new schedule.Job(function() {
  192. test.ok(true);
  193. });
  194. job.schedule({
  195. second: null // fire every second
  196. });
  197. setTimeout(function() {
  198. job.cancel();
  199. test.done();
  200. }, 3250);
  201. clock.tick(3250);
  202. },
  203. "Job emits 'scheduled' event for every next invocation": function(test) {
  204. // Job will run 3 times but be scheduled 4 times, 4th run never happens
  205. // due to cancel.
  206. test.expect(4);
  207. var job = new schedule.Job(function() {});
  208. job.on('scheduled', function(runOnDate) {
  209. test.ok(true);
  210. });
  211. job.schedule({
  212. second: null // Fire every second
  213. });
  214. setTimeout(function() {
  215. job.cancel();
  216. test.done();
  217. }, 3250);
  218. clock.tick(3250);
  219. },
  220. "Doesn't invoke job if object schedules it in the past": function(test) {
  221. test.expect(0);
  222. var job = new schedule.Job(function() {
  223. test.ok(false);
  224. });
  225. job.schedule({
  226. year: 2000
  227. });
  228. setTimeout(function() {
  229. job.cancel();
  230. test.done();
  231. }, 1000);
  232. clock.tick(1000);
  233. }
  234. },
  235. "#schedule('jobName', {...})": {
  236. "Runs job with a custom name input": function(test) {
  237. test.expect(3);
  238. var job = new schedule.Job('jobName', function() {
  239. test.equal(job.name, 'jobName');
  240. });
  241. job.schedule({
  242. second: null // fire every second
  243. });
  244. setTimeout(function() {
  245. job.cancel();
  246. test.done();
  247. }, 3250);
  248. clock.tick(3250);
  249. }
  250. },
  251. "#schedule({...}, {...})": {
  252. "Runs job and run callback when job is done if callback is provided": function(test) {
  253. test.expect(3);
  254. var job = new schedule.Job(function() {}, function() {
  255. test.ok(true);
  256. });
  257. job.schedule({
  258. second: null // fire every second
  259. });
  260. setTimeout(function() {
  261. job.cancel();
  262. test.done();
  263. }, 3250);
  264. clock.tick(3250);
  265. },
  266. "Runs job with a custom name input and run callback when job is done": function(test) {
  267. test.expect(3);
  268. var job = new schedule.Job('MyJob', function() {}, function() {
  269. test.equal(job.name, 'MyJob');
  270. });
  271. job.schedule({
  272. second: null // fire every second
  273. });
  274. setTimeout(function() {
  275. job.cancel();
  276. test.done();
  277. }, 3250);
  278. clock.tick(3250);
  279. }
  280. },
  281. "#cancel": {
  282. "Prevents all future invocations": function(test) {
  283. test.expect(1);
  284. var job = new schedule.Job(function() {
  285. test.ok(true);
  286. });
  287. job.schedule({
  288. second: null // fire every second
  289. });
  290. setTimeout(function() {
  291. job.cancel();
  292. }, 1250);
  293. setTimeout(function() {
  294. test.done();
  295. }, 2250);
  296. clock.tick(2250);
  297. },
  298. "Cancelled job reschedules": function(test) {
  299. test.expect(1);
  300. var ok = false;
  301. var job = schedule.scheduleJob('*/1 * * * * *', function () {});
  302. setTimeout(function() {
  303. job.cancel(true);
  304. if (job.nextInvocation() !== null) ok = true;
  305. }, 1250);
  306. setTimeout(function() {
  307. job.cancel();
  308. test.ok(ok);
  309. test.done();
  310. }, 2250);
  311. clock.tick(2250);
  312. },
  313. "CancelNext job reschedules": function(test) {
  314. test.expect(1);
  315. var ok = false;
  316. var job = schedule.scheduleJob('*/1 * * * * *', function () {});
  317. setTimeout(function() {
  318. job.cancelNext();
  319. if (job.nextInvocation() !== null) ok = true;
  320. }, 1250);
  321. setTimeout(function() {
  322. job.cancel();
  323. test.ok(ok);
  324. test.done();
  325. }, 2250);
  326. clock.tick(2250);
  327. },
  328. "Job emits 'canceled' event": function(test) {
  329. test.expect(1);
  330. var job = new schedule.Job(function() {});
  331. job.on('canceled', function() {
  332. test.ok(true);
  333. });
  334. job.schedule({
  335. second: null // fire every second
  336. });
  337. setTimeout(function() {
  338. job.cancel();
  339. }, 1250);
  340. setTimeout(function() {
  341. test.done();
  342. }, 2250);
  343. clock.tick(2250);
  344. },
  345. "Job is added to scheduledJobs when created and removed when cancelled": function(test) {
  346. test.expect(4);
  347. var job1 = new schedule.Job('cancelJob', function() {});
  348. job1.schedule({
  349. second: null // fire every second
  350. });
  351. var job2 = schedule.scheduleJob('second',
  352. { second: null },
  353. function() {},
  354. function() {});
  355. test.strictEqual(schedule.scheduledJobs.cancelJob, job1);
  356. test.strictEqual(schedule.scheduledJobs.second, job2);
  357. setTimeout(function() {
  358. job1.cancel();
  359. job2.cancel();
  360. test.strictEqual(schedule.scheduledJobs.cancelJob, undefined);
  361. test.strictEqual(schedule.scheduledJobs.second, undefined);
  362. test.done();
  363. }, 1250);
  364. clock.tick(1250);
  365. }
  366. },
  367. "#reschedule": {
  368. "When rescheduled counter will be reset to zero": function(test) {
  369. var job = new schedule.scheduleJob({
  370. second: null
  371. }, function() {});
  372. setTimeout(function() {
  373. test.equal(job.triggeredJobs(), 3);
  374. schedule.rescheduleJob(job, {
  375. minute: null
  376. });
  377. }, 3250);
  378. setTimeout(function() {
  379. job.cancel();
  380. test.equal(job.triggeredJobs(), 0);
  381. test.done();
  382. }, 5000);
  383. clock.tick(5000);
  384. }
  385. },
  386. "When invoked": {
  387. "Job emits 'run' event": function(test) {
  388. test.expect(1);
  389. var job = new schedule.Job(function() {});
  390. job.on('run', function() {
  391. test.ok(true);
  392. });
  393. job.schedule(new Date(Date.now() + 3000));
  394. setTimeout(function() {
  395. test.done();
  396. }, 3250);
  397. clock.tick(3250);
  398. },
  399. "Job counter increase properly": function(test) {
  400. var job = new schedule.Job(function() {});
  401. job.schedule({
  402. second: null // fire every second
  403. });
  404. setTimeout(function() {
  405. job.cancel();
  406. test.equal(job.triggeredJobs(), 2);
  407. test.done();
  408. }, 2250);
  409. clock.tick(2250);
  410. },
  411. "Job gets invoked with the fire date": function (test) {
  412. test.expect(2);
  413. var prevFireDate;
  414. var job = new schedule.Job(function (fireDate) {
  415. if (!prevFireDate) {
  416. test.ok(fireDate instanceof Date);
  417. } else {
  418. test.equal(fireDate.getTime() - prevFireDate.getTime(), 1000);
  419. }
  420. prevFireDate = fireDate;
  421. });
  422. job.schedule({
  423. second: null // fire every second
  424. });
  425. setTimeout(function () {
  426. job.cancel();
  427. test.done();
  428. }, 2250);
  429. clock.tick(2250);
  430. }
  431. },
  432. tearDown: function(cb) {
  433. clock.restore();
  434. cb();
  435. }
  436. };