stacks 0.58.63 → 0.58.64

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/core/actions/dist/src/database/seed.js +0 -3
  2. package/core/actions/dist/src/deploy/index.js +1 -1
  3. package/core/actions/dist/src/index.js +3 -0
  4. package/core/actions/dist/src/release.js +5 -2
  5. package/core/actions/dist/src/upgrade.js +1 -1
  6. package/core/actions/package.json +1 -1
  7. package/core/actions/src/action.ts +4 -1
  8. package/core/actions/src/copy-types.ts +1 -1
  9. package/core/actions/src/database/seed.ts +3 -3
  10. package/core/actions/src/deploy/index.ts +1 -1
  11. package/core/actions/src/helpers/utils.ts +2 -2
  12. package/core/ai/package.json +1 -1
  13. package/core/alias/package.json +1 -1
  14. package/core/analytics/package.json +1 -1
  15. package/core/api/package.json +1 -1
  16. package/core/arrays/package.json +1 -1
  17. package/core/arrays/src/helpers.ts +3 -3
  18. package/core/auth/package.json +1 -1
  19. package/core/buddy/dist/cli.js +1 -1
  20. package/core/buddy/package.json +1 -1
  21. package/core/buddy/src/cli.ts +1 -1
  22. package/core/build/package.json +1 -1
  23. package/core/bun-create/bud/package.json +1 -1
  24. package/core/bun-create/buddy/package.json +1 -1
  25. package/core/bun-create/stack/package.json +1 -1
  26. package/core/bun-create/stacks/package.json +1 -1
  27. package/core/bun-create/stx/package.json +1 -1
  28. package/core/bun-plugin-yaml/package.json +1 -1
  29. package/core/cache/package.json +1 -1
  30. package/core/cache/tests/DynamoDB.test.ts +125 -125
  31. package/core/cache/tests/Memcached.test.ts +51 -51
  32. package/core/cache/tests/Redis.test.ts +84 -84
  33. package/core/chat/package.json +1 -1
  34. package/core/cli/dist/index.js +1 -1
  35. package/core/cli/package.json +1 -1
  36. package/core/cli/src/exec.ts +2 -2
  37. package/core/cloud/dist/index.js +7 -7
  38. package/core/cloud/package.json +1 -1
  39. package/core/cloud/src/cloud/ai.ts +3 -3
  40. package/core/cloud/src/cloud/aws-sdk-layer/nodejs/package.json +1 -1
  41. package/core/cloud/src/cloud/cli.ts +1 -1
  42. package/core/cloud/src/cloud/deployment.ts +3 -3
  43. package/core/cloud/src/cloud/router-layer/nodejs/package.json +2 -2
  44. package/core/collections/package.json +1 -1
  45. package/core/config/dist/index.js +4 -0
  46. package/core/config/package.json +1 -1
  47. package/core/database/package.json +1 -1
  48. package/core/database/src/kysely-bun-worker/driver.ts +1 -1
  49. package/core/datetime/package.json +1 -1
  50. package/core/desktop/package.json +1 -1
  51. package/core/development/package.json +1 -1
  52. package/core/dns/package.json +1 -1
  53. package/core/docs/package.json +1 -1
  54. package/core/email/package.json +2 -2
  55. package/core/enums/package.json +1 -1
  56. package/core/env/package.json +1 -1
  57. package/core/error-handling/package.json +1 -1
  58. package/core/error-handling/src/handler.ts +1 -1
  59. package/core/eslint-config/package.json +1 -1
  60. package/core/events/package.json +1 -1
  61. package/core/faker/package.json +1 -1
  62. package/core/git/package.json +1 -1
  63. package/core/health/package.json +1 -1
  64. package/core/http/package.json +1 -1
  65. package/core/lint/package.json +1 -1
  66. package/core/logging/package.json +1 -1
  67. package/core/notifications/package.json +1 -1
  68. package/core/objects/package.json +1 -1
  69. package/core/orm/package.json +1 -1
  70. package/core/path/dist/index.js +30 -0
  71. package/core/path/package.json +1 -1
  72. package/core/path/src/index.ts +30 -0
  73. package/core/payments/package.json +1 -1
  74. package/core/push/package.json +1 -1
  75. package/core/query-builder/package.json +1 -1
  76. package/core/queue/package.json +1 -1
  77. package/core/raycast/package.json +1 -1
  78. package/core/realtime/package.json +1 -1
  79. package/core/repl/package.json +1 -1
  80. package/core/router/dist/index.js +40 -2
  81. package/core/router/package.json +1 -1
  82. package/core/router/src/router.ts +21 -1
  83. package/core/router/src/server.ts +0 -2
  84. package/core/scheduler/dist/index.js +1 -2
  85. package/core/scheduler/package.json +2 -1
  86. package/core/scheduler/src/index.ts +1 -1
  87. package/core/scheduler/src/job.ts +2 -2
  88. package/core/scheduler/src/schedule.ts +2 -2
  89. package/core/scheduler/tests/cron.test.ts +1243 -1243
  90. package/core/scheduler/tests/crontime.test.ts +780 -778
  91. package/core/search-engine/dist/index.js +1 -3
  92. package/core/search-engine/package.json +1 -1
  93. package/core/search-engine/src/index.ts +5 -5
  94. package/core/security/package.json +1 -1
  95. package/core/server/package.json +1 -1
  96. package/core/signals/package.json +1 -1
  97. package/core/slug/package.json +1 -1
  98. package/core/sms/package.json +1 -1
  99. package/core/storage/dist/index.js +0 -1
  100. package/core/storage/package.json +1 -1
  101. package/core/storage/src/files.ts +2 -5
  102. package/core/storage/src/hash.ts +0 -2
  103. package/core/strings/package.json +1 -1
  104. package/core/tables/package.json +1 -1
  105. package/core/testing/dist/index.js +14978 -1
  106. package/core/testing/package.json +1 -1
  107. package/core/testing/src/index.ts +12 -2
  108. package/core/tinker/package.json +1 -1
  109. package/core/tunnel/package.json +1 -1
  110. package/core/types/package.json +1 -1
  111. package/core/types/src/cli.ts +1 -1
  112. package/core/types/src/cron-jobs.ts +0 -5
  113. package/core/types/src/errors.ts +1 -1
  114. package/core/types/src/router.ts +7 -5
  115. package/core/ui/package.json +1 -1
  116. package/core/utils/dist/index.js +4 -8
  117. package/core/utils/package.json +1 -1
  118. package/core/utils/scripts/export-size.ts +3 -3
  119. package/core/utils/src/base.ts +4 -4
  120. package/core/utils/src/helpers.ts +3 -3
  121. package/core/utils/src/retry.ts +2 -2
  122. package/core/validation/package.json +1 -1
  123. package/core/vite/dist/index.js +1 -1
  124. package/core/vite/package.json +1 -1
  125. package/core/vite/src/functions.ts +0 -1
  126. package/core/vite/src/index.ts +1 -1
  127. package/core/vite/src/plugin/docs.ts +2 -0
  128. package/core/vite/src/plugin/stacks.ts +3 -2
  129. package/core/vite/src/web-components.ts +2 -2
  130. package/core/whois/package.json +1 -1
  131. package/core/whois/src/index.ts +2 -2
  132. package/core/x-ray/package.json +1 -1
  133. package/core/zsh-buddy/package.json +1 -1
  134. package/ide/vscode/package.json +1 -1
  135. package/package.json +1 -1
  136. package/core/actions/src/database/mydb.sqlite +0 -0
  137. package/core/actions/src/database/stacks.sqlite +0 -0
  138. package/core/server/src/api.ts +0 -5
@@ -1,1243 +1,1243 @@
1
- /* eslint-disable no-new */
2
- import { DateTime } from 'luxon'
3
-
4
- // @ts-expect-error types aren't there
5
- import sinon from 'sinon'
6
- import { CronJob, CronTime } from '../src'
7
-
8
- describe('cron', () => {
9
- afterEach(() => expect.hasAssertions())
10
-
11
- describe('with seconds', () => {
12
- it('should run every second (* * * * * *)', () => {
13
- const clock = sinon.useFakeTimers()
14
- const callback = jest.fn()
15
- const job = new CronJob('* * * * * *', callback, null, true)
16
-
17
- expect(callback).not.toHaveBeenCalled()
18
- clock.tick(1000)
19
- job.stop()
20
- clock.restore()
21
- expect(callback).toHaveBeenCalledTimes(1)
22
- })
23
-
24
- it('should run second with onComplete (* * * * * *)', (done: any) => {
25
- const clock = sinon.useFakeTimers()
26
- const callback = jest.fn()
27
-
28
- const job = new CronJob(
29
- '* * * * * *',
30
- callback,
31
- () => {
32
- expect(callback).toHaveBeenCalledTimes(1)
33
- done()
34
- },
35
- true,
36
- )
37
-
38
- clock.tick(1000)
39
- job.stop()
40
- clock.restore()
41
- })
42
-
43
- it('should use standard cron no-seconds syntax (* * * * *)', () => {
44
- const clock = sinon.useFakeTimers()
45
- const callback = jest.fn()
46
- const job = new CronJob('* * * * *', callback, null, true)
47
-
48
- clock.tick(1000) // tick second
49
-
50
- clock.tick(59 * 1000) // tick minute
51
-
52
- job.stop()
53
- clock.restore()
54
-
55
- expect(callback).toHaveBeenCalledTimes(1)
56
- })
57
-
58
- it('should run every second for 5 seconds (* * * * * *)', () => {
59
- const clock = sinon.useFakeTimers()
60
- const callback = jest.fn()
61
- const job = new CronJob('* * * * * *', callback, null, true)
62
- for (let i = 0; i < 5; i++) clock.tick(1000)
63
- job.stop()
64
- clock.restore()
65
- expect(callback).toHaveBeenCalledTimes(5)
66
- })
67
-
68
- it('should run every second for 5 seconds with onComplete (* * * * * *)', (done: any) => {
69
- const callback = jest.fn()
70
- const clock = sinon.useFakeTimers()
71
- const job = new CronJob(
72
- '* * * * * *',
73
- callback,
74
- () => {
75
- expect(callback).toHaveBeenCalledTimes(5)
76
- done()
77
- },
78
- true,
79
- )
80
- for (let i = 0; i < 5; i++) clock.tick(1000)
81
- job.stop()
82
- clock.restore()
83
- })
84
-
85
- it('should run every second for 5 seconds (*/1 * * * * *)', () => {
86
- const clock = sinon.useFakeTimers()
87
- const callback = jest.fn()
88
- const job = new CronJob('*/1 * * * * *', callback, null, true)
89
- for (let i = 0; i < 5; i++) clock.tick(1000)
90
- job.stop()
91
- clock.restore()
92
- expect(callback).toHaveBeenCalledTimes(5)
93
- })
94
-
95
- it('should run every 2 seconds for 1 seconds (*/2 * * * * *)', () => {
96
- const clock = sinon.useFakeTimers()
97
- const callback = jest.fn()
98
- const job = new CronJob('*/2 * * * * *', callback, null, true)
99
- clock.tick(1000)
100
- job.stop()
101
- clock.restore()
102
- expect(callback).toHaveBeenCalledTimes(0)
103
- })
104
-
105
- it('should run every 2 seconds for 5 seconds (*/2 * * * * *)', () => {
106
- const clock = sinon.useFakeTimers()
107
- const callback = jest.fn()
108
- const job = new CronJob('*/2 * * * * *', callback, null, true)
109
- for (let i = 0; i < 5; i++) clock.tick(1000)
110
- job.stop()
111
- clock.restore()
112
- expect(callback).toHaveBeenCalledTimes(2)
113
- })
114
-
115
- it('should run every second for 5 seconds with onComplete (*/1 * * * * *)', (done: any) => {
116
- const clock = sinon.useFakeTimers()
117
- const callback = jest.fn()
118
- const job = new CronJob(
119
- '*/1 * * * * *',
120
- callback,
121
- () => {
122
- expect(callback).toHaveBeenCalledTimes(5)
123
- done()
124
- },
125
- true,
126
- )
127
- for (let i = 0; i < 5; i++) clock.tick(1000)
128
- job.stop()
129
- clock.restore()
130
- })
131
-
132
- it('should run every second for a range ([start]-[end] * * * * *)', () => {
133
- const clock = sinon.useFakeTimers()
134
- const callback = jest.fn()
135
- const job = new CronJob('0-8 * * * * *', callback, null, true)
136
- clock.tick(10000)
137
- job.stop()
138
- clock.restore()
139
- expect(callback).toHaveBeenCalledTimes(8)
140
- })
141
-
142
- it('should run every second for a range ([start]-[end] * * * * *) with onComplete', (done: any) => {
143
- const clock = sinon.useFakeTimers()
144
- const callback = jest.fn()
145
- const job = new CronJob(
146
- '0-8 * * * * *',
147
- callback,
148
- () => {
149
- expect(callback).toHaveBeenCalledTimes(8)
150
- done()
151
- },
152
- true,
153
- )
154
- clock.tick(10000)
155
- job.stop()
156
- clock.restore()
157
- })
158
-
159
- it('should default to full range when upper range not provided (1/2 * * * * *)', (done: any) => {
160
- const clock = sinon.useFakeTimers()
161
- const callback = jest.fn()
162
- const job = new CronJob(
163
- '1/2 * * * * *',
164
- callback,
165
- () => {
166
- expect(callback).toHaveBeenCalledTimes(30)
167
- done()
168
- },
169
- true,
170
- )
171
- clock.tick(1000 * 60)
172
- job.stop()
173
- clock.restore()
174
- })
175
-
176
- it('should run every second (* * * * * *) using the object constructor', () => {
177
- const clock = sinon.useFakeTimers()
178
- const callback = jest.fn()
179
- const job = CronJob.from({
180
- cronTime: '* * * * * *',
181
- onTick: callback,
182
- start: true,
183
- })
184
- clock.tick(1000)
185
- job.stop()
186
- clock.restore()
187
- expect(callback).toHaveBeenCalledTimes(1)
188
- })
189
-
190
- it('should run every second with onComplete (* * * * * *) using the object constructor', (done: any) => {
191
- const clock = sinon.useFakeTimers()
192
- const callback = jest.fn()
193
- const job = CronJob.from({
194
- cronTime: '* * * * * *',
195
- onTick: callback,
196
- onComplete: () => {
197
- expect(callback).toHaveBeenCalledTimes(1)
198
- done()
199
- },
200
- start: true,
201
- })
202
- clock.tick(1000)
203
- job.stop()
204
- clock.restore()
205
- })
206
- })
207
-
208
- describe('with minutes', () => {
209
- it('should fire every 60 min', () => {
210
- const clock = sinon.useFakeTimers()
211
- const m60 = 60 * 60 * 1000
212
- const l: number[] = []
213
- const job = new CronJob(
214
- '00 30 * * * *',
215
- () => {
216
- l.push(Math.floor(Date.now() / 60000))
217
- },
218
- null,
219
- true,
220
- )
221
-
222
- clock.tick(m60 * 10)
223
-
224
- expect(l).toHaveLength(10)
225
- expect(l.every(i => i % 30 === 0)).toBe(true)
226
-
227
- job.stop()
228
- clock.restore()
229
- })
230
-
231
- it('should run every 45 minutes for 2 hours (0 */45 * * * *)', () => {
232
- const clock = sinon.useFakeTimers()
233
- const callback = jest.fn()
234
- const job = new CronJob('0 */45 * * * *', callback, null, true)
235
- for (let i = 0; i < 2; i++) clock.tick(60 * 60 * 1000)
236
- job.stop()
237
- clock.restore()
238
- expect(callback).toHaveBeenCalledTimes(4)
239
- })
240
-
241
- it('should run every 45 minutes for 2 hours (0 */45 * * * *) with onComplete', (done: any) => {
242
- const clock = sinon.useFakeTimers()
243
- const callback = jest.fn()
244
- const job = new CronJob(
245
- '0 */45 * * * *',
246
- callback,
247
- () => {
248
- expect(callback).toHaveBeenCalledTimes(4)
249
- done()
250
- },
251
- true,
252
- )
253
- for (let i = 0; i < 2; i++) clock.tick(60 * 60 * 1000)
254
- job.stop()
255
- clock.restore()
256
- })
257
- })
258
-
259
- it('should start and stop job from outside', (done: any) => {
260
- const clock = sinon.useFakeTimers()
261
- const callback = jest.fn()
262
- const job = new CronJob(
263
- '* * * * * *',
264
- () => {
265
- callback()
266
- },
267
- () => {
268
- expect(callback).toHaveBeenCalledTimes(1)
269
- clock.restore()
270
- done()
271
- },
272
- true,
273
- )
274
- clock.tick(1000)
275
- job.stop()
276
- })
277
-
278
- it('should start and stop job from inside (default context)', (done: any) => {
279
- const clock = sinon.useFakeTimers()
280
- const callback = jest.fn()
281
- new CronJob(
282
- '* * * * * *',
283
- function () {
284
- callback()
285
- this.stop()
286
- },
287
- () => {
288
- expect(callback).toHaveBeenCalledTimes(1)
289
- clock.restore()
290
- done()
291
- },
292
- true,
293
- )
294
- clock.tick(1000)
295
- })
296
-
297
- describe('with date', () => {
298
- it('should run on a specific date', () => {
299
- const d = new Date()
300
- const clock = sinon.useFakeTimers(d.getTime())
301
- const s = d.getSeconds() + 1
302
- d.setSeconds(s)
303
- const callback = jest.fn()
304
- const job = new CronJob(
305
- d,
306
- () => {
307
- const t = new Date()
308
- expect(t.getSeconds()).toBe(d.getSeconds())
309
- callback()
310
- },
311
- null,
312
- true,
313
- )
314
- clock.tick(1000)
315
- clock.restore()
316
- job.stop()
317
- expect(callback).toHaveBeenCalledTimes(1)
318
- })
319
-
320
- it('should run on a specific date and call onComplete from onTick', async () => {
321
- const d = new Date()
322
- const clock = sinon.useFakeTimers(d.getTime())
323
- d.setSeconds(d.getSeconds() + 1)
324
- const callback = jest.fn()
325
-
326
- await new Promise<void>((resolve) => {
327
- const job = new CronJob(
328
- d,
329
- (onComplete) => {
330
- const t = new Date()
331
- expect(t.getSeconds()).toBe(d.getSeconds())
332
- void onComplete()
333
- },
334
- () => {
335
- callback()
336
- resolve()
337
- },
338
- true,
339
- )
340
- clock.tick(1000)
341
- clock.restore()
342
- job.stop()
343
- })
344
-
345
- // onComplete is called 2 times: once in onTick() & once when calling job.stop()
346
- expect(callback).toHaveBeenCalledTimes(2)
347
- })
348
-
349
- it('should run on a specific date and call onComplete from onTick using the object constructor', async () => {
350
- const d = new Date()
351
- const clock = sinon.useFakeTimers(d.getTime())
352
- d.setSeconds(d.getSeconds() + 1)
353
- const callback = jest.fn()
354
-
355
- await new Promise<void>((resolve) => {
356
- const job = CronJob.from({
357
- cronTime: d,
358
- onTick: (onComplete) => {
359
- const t = new Date()
360
- expect(t.getSeconds()).toBe(d.getSeconds())
361
- void onComplete()
362
- },
363
- onComplete: function () {
364
- callback()
365
- resolve()
366
- } as () => void,
367
- start: true,
368
- })
369
- clock.tick(1000)
370
- clock.restore()
371
- job.stop()
372
- })
373
-
374
- // onComplete is called 2 times: once in onTick() & once when calling job.stop()
375
- expect(callback).toHaveBeenCalledTimes(2)
376
- })
377
-
378
- it('should not be able to call onComplete from onTick if if wasn\'t provided', () => {
379
- expect.assertions(4)
380
- const d = new Date()
381
- const clock = sinon.useFakeTimers(d.getTime())
382
- d.setSeconds(d.getSeconds() + 1)
383
-
384
- const job = new CronJob(
385
- d,
386
- (onComplete) => {
387
- const t = new Date()
388
- expect(onComplete).toBeUndefined()
389
- try {
390
- // @ts-expect-error should be a TS warning and throw
391
- onComplete()
392
- }
393
- catch (e) {
394
- // we make sure this isn't skipped with `expect.assertions()`
395
- // at the beginning of the test
396
- expect(e).toBeInstanceOf(TypeError)
397
- }
398
- expect(onComplete).toBeUndefined()
399
- expect(t.getSeconds()).toBe(d.getSeconds())
400
- },
401
- null,
402
- true,
403
- )
404
- clock.tick(1000)
405
- job.stop()
406
- clock.restore()
407
- })
408
-
409
- it('should wait and not fire immediately', () => {
410
- const clock = sinon.useFakeTimers()
411
- const callback = jest.fn()
412
-
413
- const d = new Date().getTime() + 31 * 86400 * 1000
414
-
415
- const job = new CronJob(new Date(d), callback)
416
- job.start()
417
-
418
- clock.tick(1000)
419
-
420
- clock.restore()
421
- job.stop()
422
- expect(callback).toHaveBeenCalledTimes(0)
423
- })
424
-
425
- it('should wait but fire on init', () => {
426
- const clock = sinon.useFakeTimers()
427
- const callback = jest.fn()
428
-
429
- const d = new Date().getTime() + 31 * 86400 * 1000
430
-
431
- const job = CronJob.from({
432
- cronTime: new Date(d),
433
- onTick: callback,
434
- runOnInit: true,
435
- })
436
-
437
- expect(callback).toHaveBeenCalledTimes(1)
438
-
439
- job.start()
440
-
441
- clock.tick(1000)
442
-
443
- clock.restore()
444
- job.stop()
445
- expect(callback).toHaveBeenCalledTimes(1)
446
- })
447
-
448
- it('should fire on init but not run until started', () => {
449
- const clock = sinon.useFakeTimers()
450
- const callback = jest.fn()
451
-
452
- const job = CronJob.from({
453
- cronTime: '* * * * * *',
454
- onTick: callback,
455
- runOnInit: true,
456
- })
457
-
458
- expect(callback).toHaveBeenCalledTimes(1)
459
-
460
- job.start()
461
-
462
- clock.tick(3500)
463
-
464
- clock.restore()
465
- job.stop()
466
- expect(callback).toHaveBeenCalledTimes(4)
467
- })
468
- })
469
-
470
- describe('with timezone', () => {
471
- it('should run a job using cron syntax with a timezone', () => {
472
- const clock = sinon.useFakeTimers()
473
- const callback = jest.fn()
474
- let zone = 'America/Chicago'
475
- // New Orleans time
476
- let t = DateTime.local().setZone(zone)
477
- // Current time
478
- const d = DateTime.local()
479
-
480
- // If current time is New Orleans time, switch to Los Angeles..
481
- if (t.hour === d.hour) {
482
- zone = 'America/Los_Angeles'
483
- t = t.setZone(zone)
484
- }
485
- expect(d.hour).not.toBe(t.hour)
486
-
487
- // If t = 59s12m then t.setSeconds(60)
488
- // becomes 00s13m so we're fine just doing
489
- // this and no testRun callback.
490
- t = t.plus({ seconds: 1 })
491
- // Run a job designed to be executed at a given
492
- // time in `zone`, making sure that it is a different
493
- // hour than local time.
494
- const job = new CronJob(
495
- `${t.second} ${t.minute} ${t.hour} * * *`,
496
- callback,
497
- null,
498
- true,
499
- zone,
500
- )
501
-
502
- clock.tick(1000)
503
- clock.restore()
504
- job.stop()
505
- expect(callback).toHaveBeenCalledTimes(1)
506
- })
507
-
508
- it('should run a job using cron syntax with a "UTC+HH:mm" offset as timezone', () => {
509
- const clock = sinon.useFakeTimers()
510
- const callback = jest.fn()
511
-
512
- // Current time
513
- const d = DateTime.local()
514
-
515
- // Current time with zone offset
516
- let zone = 'UTC+5:30'
517
- let t = DateTime.local().setZone(zone)
518
-
519
- // If current offset is UTC+5:30, switch to UTC+6:30..
520
- if (t.hour === d.hour && t.minute === d.minute) {
521
- zone = 'UTC+6:30'
522
- t = t.setZone(zone)
523
- }
524
- expect(`${d.hour}:${d.minute}`).not.toBe(`${t.hour}:${t.minute}`)
525
-
526
- // If t = 59s12m then t.setSeconds(60)
527
- // becomes 00s13m so we're fine just doing
528
- // this and no testRun callback.
529
- t = t.plus({ seconds: 1 })
530
- // Run a job designed to be executed at a given
531
- // time in `zone`, making sure that it is a different
532
- // hour than local time.
533
- const job = new CronJob(
534
- `${t.second} ${t.minute} ${t.hour} * * *`,
535
- callback,
536
- null,
537
- true,
538
- zone,
539
- )
540
-
541
- clock.tick(1000)
542
- clock.restore()
543
- job.stop()
544
- expect(callback).toHaveBeenCalledTimes(1)
545
- })
546
-
547
- it('should run a job using a date', () => {
548
- let zone = 'America/Chicago'
549
- // New Orleans time
550
- let t = DateTime.local().setZone(zone)
551
- // Current time
552
- let d = DateTime.local()
553
-
554
- // If current time is New Orleans time, switch to Los Angeles..
555
- if (t.hour === d.hour) {
556
- zone = 'America/Los_Angeles'
557
- t = t.setZone(zone)
558
- }
559
-
560
- expect(d.hour).not.toBe(t.hour)
561
- d = d.plus({ seconds: 1 })
562
- const clock = sinon.useFakeTimers(d.valueOf())
563
- const callback = jest.fn()
564
- const job = new CronJob(d.toJSDate(), callback, null, true, zone)
565
- clock.tick(1000)
566
- clock.restore()
567
- job.stop()
568
- expect(callback).toHaveBeenCalledTimes(1)
569
- })
570
-
571
- it('should test if timezone is valid.', () => {
572
- expect(() => {
573
- CronJob.from({
574
- cronTime: '* * * * * *',
575
- onTick: () => { },
576
- timeZone: 'fake/timezone',
577
- })
578
- }).toThrow()
579
- })
580
- })
581
-
582
- describe('onTick scoping', () => {
583
- it('should scope onTick to running job', () => {
584
- const clock = sinon.useFakeTimers()
585
-
586
- const job = new CronJob(
587
- '* * * * * *',
588
- function () {
589
- expect(job).toBeInstanceOf(CronJob)
590
- expect(job).toEqual(this)
591
- },
592
- null,
593
- true,
594
- )
595
-
596
- clock.tick(1000)
597
-
598
- clock.restore()
599
- job.stop()
600
- })
601
-
602
- it('should scope onTick to running job using the object constructor', () => {
603
- const clock = sinon.useFakeTimers()
604
-
605
- const job = CronJob.from({
606
- cronTime: '* * * * * *',
607
- onTick() {
608
- expect(job).toBeInstanceOf(CronJob)
609
- expect(job).toEqual(this)
610
- },
611
- start: true,
612
- })
613
-
614
- clock.tick(1000)
615
-
616
- clock.restore()
617
- job.stop()
618
- })
619
-
620
- it('should scope onTick to object', () => {
621
- const clock = sinon.useFakeTimers()
622
-
623
- const job = new CronJob(
624
- '* * * * * *',
625
- function () {
626
- expect(this.hello).toBe('world')
627
- expect(job).not.toEqual(this)
628
- },
629
- null,
630
- true,
631
- null,
632
- { hello: 'world' },
633
- )
634
-
635
- clock.tick(1000)
636
-
637
- clock.restore()
638
- job.stop()
639
- })
640
-
641
- it('should scope onTick to object using the object constructor', () => {
642
- const clock = sinon.useFakeTimers()
643
-
644
- const job = CronJob.from({
645
- cronTime: '* * * * * *',
646
- onTick() {
647
- expect(this.hello).toBe('world')
648
- expect(job).not.toEqual(this)
649
- },
650
- start: true,
651
- context: { hello: 'world' },
652
- })
653
-
654
- clock.tick(1000)
655
-
656
- clock.restore()
657
- job.stop()
658
- })
659
- })
660
-
661
- it('should not get into an infinite loop on invalid times', () => {
662
- expect(() => {
663
- new CronJob(
664
- '* 60 * * * *',
665
- () => {
666
- expect(true).toBe(true)
667
- },
668
- null,
669
- true,
670
- )
671
- }).toThrow()
672
-
673
- expect(() => {
674
- new CronJob(
675
- '* * 24 * * *',
676
- () => {
677
- expect(true).toBe(true)
678
- },
679
- null,
680
- true,
681
- )
682
- }).toThrow()
683
- })
684
-
685
- it('should test start of month', () => {
686
- const callback = jest.fn()
687
- const d = new Date('12/31/2014')
688
- d.setSeconds(59)
689
- d.setMinutes(59)
690
- d.setHours(23)
691
- const clock = sinon.useFakeTimers(d.getTime())
692
-
693
- const job = new CronJob('0 0 0 1 * *', callback, null, true)
694
-
695
- clock.tick(1001)
696
- expect(callback).toHaveBeenCalledTimes(1)
697
-
698
- clock.tick(2678399001)
699
- expect(callback).toHaveBeenCalledTimes(1)
700
-
701
- clock.tick(2678400001) // jump over 2 firsts
702
- clock.restore()
703
- job.stop()
704
-
705
- expect(callback).toHaveBeenCalledTimes(3)
706
- })
707
-
708
- it('should not fire if time was adjusted back', () => {
709
- const callback = jest.fn()
710
- const clock = sinon.useFakeTimers({
711
- toFake: ['setTimeout'],
712
- })
713
-
714
- const job = new CronJob('0 * * * * *', callback, null, true)
715
-
716
- clock.tick(60000)
717
- expect(callback).toHaveBeenCalledTimes(0)
718
-
719
- clock.restore()
720
- job.stop()
721
- })
722
-
723
- it('should run every day', () => {
724
- const callback = jest.fn()
725
- const d = new Date('12/31/2014')
726
- d.setSeconds(59)
727
- d.setMinutes(59)
728
- d.setHours(23)
729
- const clock = sinon.useFakeTimers(d.getTime())
730
-
731
- const job = CronJob.from({
732
- cronTime: '59 59 3 * * *',
733
- onTick: callback,
734
- start: true,
735
- timeZone: 'America/Los_Angeles',
736
- })
737
-
738
- const twoWeeks = 14 * 24 * 60 * 60 * 1000
739
- clock.tick(twoWeeks)
740
-
741
- clock.restore()
742
- job.stop()
743
- expect(callback).toHaveBeenCalledTimes(14)
744
- })
745
-
746
- it('should run every 2 hours between hours', () => {
747
- const callback = jest.fn()
748
- const d = new Date('12/31/2014')
749
- d.setSeconds(0)
750
- d.setMinutes(0)
751
- d.setHours(0)
752
- const clock = sinon.useFakeTimers(d.getTime())
753
-
754
- const job = CronJob.from({
755
- cronTime: '0 2-6/2 * * * *',
756
- onTick: callback,
757
- start: true,
758
- })
759
-
760
- clock.tick(2 * 60 * 1000)
761
- expect(callback).toHaveBeenCalledTimes(1)
762
- clock.tick(2 * 60 * 1000)
763
- expect(callback).toHaveBeenCalledTimes(2)
764
- clock.tick(2 * 60 * 1000)
765
- expect(callback).toHaveBeenCalledTimes(3)
766
- clock.tick(2 * 60 * 1000)
767
-
768
- clock.restore()
769
- job.stop()
770
- expect(callback).toHaveBeenCalledTimes(3)
771
- })
772
-
773
- it('should run every minute', () => {
774
- const callback = jest.fn()
775
- const d = new Date('12/31/2014')
776
- d.setSeconds(0)
777
- d.setMinutes(0)
778
- d.setHours(0)
779
- const clock = sinon.useFakeTimers(d.getTime())
780
-
781
- const job = CronJob.from({
782
- cronTime: '00 * * * * *',
783
- onTick: callback,
784
- start: true,
785
- })
786
-
787
- clock.tick(60 * 1000)
788
- expect(callback).toHaveBeenCalledTimes(1)
789
- clock.tick(60 * 1000)
790
- expect(callback).toHaveBeenCalledTimes(2)
791
-
792
- clock.restore()
793
- job.stop()
794
- expect(callback).toHaveBeenCalledTimes(2)
795
- })
796
-
797
- it('should run every day at 12:30', () => {
798
- const callback = jest.fn()
799
- const d = new Date('12/31/2014')
800
- d.setSeconds(0)
801
- d.setMinutes(0)
802
- d.setHours(0)
803
- const clock = sinon.useFakeTimers(d.getTime())
804
-
805
- const job = CronJob.from({
806
- cronTime: '00 30 00 * * *',
807
- onTick: callback,
808
- start: true,
809
- })
810
-
811
- const day = 24 * 60 * 60 * 1000
812
- clock.tick(day)
813
- expect(callback).toHaveBeenCalledTimes(1)
814
- clock.tick(day)
815
- expect(callback).toHaveBeenCalledTimes(2)
816
- clock.tick(day)
817
- expect(callback).toHaveBeenCalledTimes(3)
818
- clock.tick(5 * day)
819
-
820
- clock.restore()
821
- job.stop()
822
- expect(callback).toHaveBeenCalledTimes(8)
823
- })
824
-
825
- it('should trigger onTick at midnight', () => {
826
- const callback = jest.fn()
827
- const d = new Date('12/31/2014')
828
- d.setSeconds(59)
829
- d.setMinutes(59)
830
- d.setHours(23)
831
- const clock = sinon.useFakeTimers(d.getTime())
832
-
833
- const job = CronJob.from({
834
- cronTime: '00 * * * * *',
835
- onTick: callback,
836
- start: true,
837
- timeZone: 'UTC',
838
- })
839
-
840
- clock.tick(1000) // move clock 1 second
841
- expect(callback).toHaveBeenCalledTimes(1)
842
-
843
- clock.restore()
844
- job.stop()
845
- expect(callback).toHaveBeenCalledTimes(1)
846
- })
847
-
848
- it('should run every day UTC', () => {
849
- const callback = jest.fn()
850
- const d = new Date('12/31/2014')
851
- d.setSeconds(0)
852
- d.setMinutes(0)
853
- d.setHours(0)
854
- const clock = sinon.useFakeTimers(d.getTime())
855
-
856
- const job = CronJob.from({
857
- cronTime: '00 30 00 * * *',
858
- onTick: callback,
859
- start: true,
860
- timeZone: 'UTC',
861
- })
862
-
863
- const day = 24 * 60 * 60 * 1000
864
- clock.tick(day)
865
- expect(callback).toHaveBeenCalledTimes(1)
866
- clock.tick(day)
867
- expect(callback).toHaveBeenCalledTimes(2)
868
- clock.tick(day)
869
- expect(callback).toHaveBeenCalledTimes(3)
870
- clock.tick(5 * day)
871
-
872
- clock.restore()
873
- job.stop()
874
- expect(callback).toHaveBeenCalledTimes(8)
875
- })
876
-
877
- // from https://github.com/kelektiv/node-cron/issues/180#issuecomment-154108131
878
- it('should run once not double', () => {
879
- const callback = jest.fn()
880
- const d = new Date(2015, 1, 1, 1, 1, 41, 0)
881
- const clock = sinon.useFakeTimers(d.getTime())
882
-
883
- const job = CronJob.from({
884
- cronTime: '* * * * *',
885
- onTick: callback,
886
- start: true,
887
- })
888
-
889
- const minute = 60 * 1000
890
- clock.tick(minute)
891
- expect(callback).toHaveBeenCalledTimes(1)
892
- clock.restore()
893
- job.stop()
894
- expect(callback).toHaveBeenCalledTimes(1)
895
- })
896
-
897
- /**
898
- * maximum match interval is 8 years:
899
- * crontab has '* * 29 2 *' and we are on 1 March 2096:
900
- * next matching time will be 29 February 2104
901
- * source: https://github.com/cronie-crond/cronie/blob/0d669551680f733a4bdd6bab082a0b3d6d7f089c/src/cronnext.c#L401-L403
902
- */
903
- it('should work correctly for max match interval', () => {
904
- const callback = jest.fn()
905
- const d = new Date(2096, 2, 1)
906
- const clock = sinon.useFakeTimers(d.getTime())
907
-
908
- const job = CronJob.from({
909
- cronTime: ' * * 29 2 *',
910
- onTick: callback,
911
- start: true,
912
- })
913
-
914
- // 7 years, 11 months and 27 days
915
- const almostEightYears = 2919 * 24 * 60 * 60 * 1000
916
- clock.tick(almostEightYears)
917
- expect(callback).toHaveBeenCalledTimes(0)
918
-
919
- // tick by 1 day
920
- clock.tick(24 * 60 * 60 * 1000)
921
- clock.restore()
922
- job.stop()
923
- expect(callback).toHaveBeenCalledTimes(1)
924
- })
925
-
926
- describe('with utcOffset', () => {
927
- it('should run a job using cron syntax with number format utcOffset', () => {
928
- const clock = sinon.useFakeTimers()
929
- const callback = jest.fn()
930
- // Current time
931
- const t = DateTime.local()
932
- // UTC Offset decreased by an hour
933
- const utcOffset = t.offset - 60
934
-
935
- const job = new CronJob(
936
- `${t.second} ${t.minute} ${t.hour} * * *`,
937
- callback,
938
- null,
939
- true,
940
- null,
941
- null,
942
- null,
943
- utcOffset,
944
- )
945
-
946
- // tick 1 sec before an hour
947
- clock.tick(1000 * 60 * 60 - 1)
948
- expect(callback).toHaveBeenCalledTimes(0)
949
-
950
- clock.tick(1)
951
- clock.restore()
952
- job.stop()
953
- expect(callback).toHaveBeenCalledTimes(1)
954
- })
955
-
956
- it('should run a job using cron syntax with numeric format utcOffset with minute support', () => {
957
- const clock = sinon.useFakeTimers()
958
- const callback = jest.fn()
959
- // Current time
960
- const t = DateTime.local()
961
-
962
- // UTC Offset decreased by 45 minutes
963
- const utcOffset = t.offset - 45
964
- const job = new CronJob(
965
- `${t.second} ${t.minute} ${t.hour} * * *`,
966
- callback,
967
- null,
968
- true,
969
- null,
970
- null,
971
- null,
972
- utcOffset,
973
- )
974
-
975
- // tick 1 sec before 45 minutes
976
- clock.tick(1000 * 45 * 60 - 1)
977
- expect(callback).toHaveBeenCalledTimes(0)
978
-
979
- clock.tick(1)
980
- clock.restore()
981
- job.stop()
982
- expect(callback).toHaveBeenCalledTimes(1)
983
- })
984
-
985
- it('should run a job using cron syntax with number format utcOffset that is 0', () => {
986
- const clock = sinon.useFakeTimers()
987
- const callback = jest.fn()
988
-
989
- const job = new CronJob(
990
- '* * * * * *',
991
- callback,
992
- null,
993
- true,
994
- null,
995
- null,
996
- null,
997
- 0,
998
- )
999
-
1000
- clock.tick(999)
1001
- expect(callback).toHaveBeenCalledTimes(0)
1002
-
1003
- clock.tick(1)
1004
- clock.restore()
1005
- job.stop()
1006
- expect(callback).toHaveBeenCalledTimes(1)
1007
- })
1008
-
1009
- it('should be able to detect out of range days of month', () => {
1010
- expect(() => {
1011
- new CronTime('* * 32 FEB *')
1012
- }).toThrow()
1013
- })
1014
- })
1015
-
1016
- describe('setTime', () => {
1017
- it('should start, change time, start again', () => {
1018
- const callback = jest.fn()
1019
- const clock = sinon.useFakeTimers()
1020
-
1021
- const job = new CronJob('* * * * * *', callback)
1022
-
1023
- job.start()
1024
- clock.tick(1000)
1025
-
1026
- const time = new CronTime('*/2 * * * * *')
1027
- job.setTime(time)
1028
-
1029
- clock.tick(4000)
1030
-
1031
- clock.restore()
1032
- job.stop()
1033
- expect(callback).toHaveBeenCalledTimes(3)
1034
- })
1035
-
1036
- it('should start, stop, change time, not start again', () => {
1037
- const callback = jest.fn()
1038
- const clock = sinon.useFakeTimers()
1039
-
1040
- const job = new CronJob('* * * * * *', callback)
1041
-
1042
- job.start()
1043
- clock.tick(1000)
1044
-
1045
- job.stop()
1046
- const time = new CronTime('*/2 * * * * *')
1047
- job.setTime(time)
1048
-
1049
- clock.tick(4000)
1050
-
1051
- clock.restore()
1052
- job.stop()
1053
- expect(callback).toHaveBeenCalledTimes(1)
1054
- })
1055
-
1056
- it('should setTime with invalid object', () => {
1057
- const callback = jest.fn()
1058
- const job = new CronJob('* * * * * *', callback)
1059
- expect(() => {
1060
- // @ts-expect-error time parameter cannot be undefined
1061
- job.setTime(undefined)
1062
- }).toThrow()
1063
- })
1064
-
1065
- it('should start, change time, exception', () => {
1066
- const callback = jest.fn()
1067
- const clock = sinon.useFakeTimers()
1068
-
1069
- const job = new CronJob('* * * * * *', callback)
1070
-
1071
- const time = new Date()
1072
- job.start()
1073
-
1074
- clock.tick(1000)
1075
-
1076
- expect(() => {
1077
- // @ts-expect-error time parameter but be an instance of CronTime
1078
- job.setTime(time)
1079
- }).toThrow()
1080
-
1081
- clock.restore()
1082
- job.stop()
1083
- expect(callback).toHaveBeenCalledTimes(1)
1084
- })
1085
-
1086
- it('should create recurring job, setTime with actual date, start and run once (#739)', () => {
1087
- const callback = jest.fn()
1088
- const clock = sinon.useFakeTimers()
1089
-
1090
- const job = new CronJob('0 0 20 * * *', callback)
1091
-
1092
- const startDate = new Date(Date.now() + 5000)
1093
- job.setTime(new CronTime(startDate))
1094
-
1095
- job.start()
1096
-
1097
- clock.tick(5000)
1098
-
1099
- expect(callback).toHaveBeenCalledTimes(1)
1100
-
1101
- clock.tick(60000)
1102
-
1103
- clock.restore()
1104
-
1105
- expect(callback).toHaveBeenCalledTimes(1)
1106
- expect(job.running).toBe(false)
1107
- })
1108
- })
1109
-
1110
- describe('nextDate(s)', () => {
1111
- it('should give the next date to run at', () => {
1112
- const callback = jest.fn()
1113
- const clock = sinon.useFakeTimers()
1114
- const job = new CronJob('* * * * * *', callback)
1115
- const d = Date.now()
1116
-
1117
- expect(job.nextDate().toMillis()).toEqual(d + 1000)
1118
-
1119
- clock.restore()
1120
- })
1121
-
1122
- it('should give the next 5 dates to run at', () => {
1123
- const callback = jest.fn()
1124
- const clock = sinon.useFakeTimers()
1125
- const job = new CronJob('* * * * * *', callback)
1126
- const d = Date.now()
1127
-
1128
- expect(job.nextDates(5).map(d => d.toMillis())).toEqual([
1129
- d + 1000,
1130
- d + 2000,
1131
- d + 3000,
1132
- d + 4000,
1133
- d + 5000,
1134
- ])
1135
-
1136
- clock.restore()
1137
- })
1138
-
1139
- it('should give an empty array when called without argument', () => {
1140
- const callback = jest.fn()
1141
- const clock = sinon.useFakeTimers()
1142
- const job = new CronJob('* * * * * *', callback)
1143
-
1144
- expect(job.nextDates()).toHaveLength(0)
1145
-
1146
- clock.restore()
1147
- })
1148
- })
1149
-
1150
- it('should automatically setup a new timeout if we roll past the max timeout delay', () => {
1151
- const callback = jest.fn()
1152
- const clock = sinon.useFakeTimers()
1153
- const d = new Date()
1154
- d.setMilliseconds(2147485647 * 2) // MAXDELAY in `job.js` + 2000.
1155
- const job = new CronJob(d, callback)
1156
- job.start()
1157
- clock.tick(2147483648)
1158
- expect(callback).toHaveBeenCalledTimes(0)
1159
- clock.tick(2147489648)
1160
- expect(callback).toHaveBeenCalledTimes(1)
1161
- job.stop()
1162
- clock.restore()
1163
- })
1164
-
1165
- it('should give the correct last execution date', () => {
1166
- const callback = jest.fn()
1167
- const clock = sinon.useFakeTimers()
1168
- const job = new CronJob('* * * * * *', callback)
1169
- job.start()
1170
- clock.tick(1000)
1171
- expect(callback).toHaveBeenCalledTimes(1)
1172
- expect(job.lastDate()?.getTime()).toBe(1000)
1173
- job.stop()
1174
- clock.restore()
1175
- })
1176
-
1177
- it('should give the correct last execution date for intervals greater than 25 days (#710)', () => {
1178
- const callback = jest.fn()
1179
- const clock = sinon.useFakeTimers()
1180
-
1181
- const job = new CronJob('0 0 0 1 * *', callback) // At 00:00 on day-of-month 1.
1182
- job.start()
1183
-
1184
- // tick one tick before nextDate()
1185
- clock.tick(job.nextDate().toMillis() - 1)
1186
-
1187
- expect(callback).toHaveBeenCalledTimes(0)
1188
- expect(job.lastDate()?.getTime()).toBeUndefined()
1189
-
1190
- job.stop()
1191
- clock.restore()
1192
- })
1193
-
1194
- it('should throw when providing both exclusive parameters timeZone and utcOffset', () => {
1195
- expect(() => {
1196
- // @ts-expect-error testing runtime exception
1197
- new CronJob(
1198
- `* * * * *`,
1199
- () => { },
1200
- null,
1201
- true,
1202
- 'America/Chicago',
1203
- null,
1204
- null,
1205
- 120,
1206
- )
1207
- }).toThrow()
1208
- })
1209
-
1210
- it('should throw when providing both exclusive parameters timeZone and utcOffset using the object constructor', () => {
1211
- expect(() => {
1212
- // @ts-expect-error testing runtime exception
1213
- CronJob.from({
1214
- cronTime: '* * * * * *',
1215
- onTick() { },
1216
- timeZone: 'America/Chicago',
1217
- utcOffset: 120,
1218
- })
1219
- }).toThrow()
1220
- })
1221
-
1222
- it('should support async callback', () => {
1223
- const clock = sinon.useFakeTimers()
1224
- const callback = jest.fn()
1225
- const job = new CronJob(
1226
- '* * * * * *',
1227
- async () => {
1228
- await new Promise<void>((resolve) => {
1229
- setTimeout(() => {
1230
- callback()
1231
- resolve()
1232
- }, 500)
1233
- })
1234
- },
1235
- null,
1236
- true,
1237
- )
1238
- clock.tick(1500)
1239
- job.stop()
1240
- clock.restore()
1241
- expect(callback).toHaveBeenCalledTimes(1)
1242
- })
1243
- })
1
+ // /* eslint-disable no-new */
2
+ // import { DateTime } from 'luxon'
3
+ //
4
+ // // @ts-expect-error types aren't there
5
+ // import sinon from 'sinon'
6
+ // import { CronJob, CronTime } from '../src'
7
+ //
8
+ // describe('cron', () => {
9
+ // afterEach(() => expect.hasAssertions())
10
+ //
11
+ // describe('with seconds', () => {
12
+ // it('should run every second (* * * * * *)', () => {
13
+ // const clock = sinon.useFakeTimers()
14
+ // const callback = jest.fn()
15
+ // const job = new CronJob('* * * * * *', callback, null, true)
16
+ //
17
+ // expect(callback).not.toHaveBeenCalled()
18
+ // clock.tick(1000)
19
+ // job.stop()
20
+ // clock.restore()
21
+ // expect(callback).toHaveBeenCalledTimes(1)
22
+ // })
23
+ //
24
+ // it('should run second with onComplete (* * * * * *)', (done: any) => {
25
+ // const clock = sinon.useFakeTimers()
26
+ // const callback = jest.fn()
27
+ //
28
+ // const job = new CronJob(
29
+ // '* * * * * *',
30
+ // callback,
31
+ // () => {
32
+ // expect(callback).toHaveBeenCalledTimes(1)
33
+ // done()
34
+ // },
35
+ // true,
36
+ // )
37
+ //
38
+ // clock.tick(1000)
39
+ // job.stop()
40
+ // clock.restore()
41
+ // })
42
+ //
43
+ // it('should use standard cron no-seconds syntax (* * * * *)', () => {
44
+ // const clock = sinon.useFakeTimers()
45
+ // const callback = jest.fn()
46
+ // const job = new CronJob('* * * * *', callback, null, true)
47
+ //
48
+ // clock.tick(1000) // tick second
49
+ //
50
+ // clock.tick(59 * 1000) // tick minute
51
+ //
52
+ // job.stop()
53
+ // clock.restore()
54
+ //
55
+ // expect(callback).toHaveBeenCalledTimes(1)
56
+ // })
57
+ //
58
+ // it('should run every second for 5 seconds (* * * * * *)', () => {
59
+ // const clock = sinon.useFakeTimers()
60
+ // const callback = jest.fn()
61
+ // const job = new CronJob('* * * * * *', callback, null, true)
62
+ // for (let i = 0; i < 5; i++) clock.tick(1000)
63
+ // job.stop()
64
+ // clock.restore()
65
+ // expect(callback).toHaveBeenCalledTimes(5)
66
+ // })
67
+ //
68
+ // it('should run every second for 5 seconds with onComplete (* * * * * *)', (done: any) => {
69
+ // const callback = jest.fn()
70
+ // const clock = sinon.useFakeTimers()
71
+ // const job = new CronJob(
72
+ // '* * * * * *',
73
+ // callback,
74
+ // () => {
75
+ // expect(callback).toHaveBeenCalledTimes(5)
76
+ // done()
77
+ // },
78
+ // true,
79
+ // )
80
+ // for (let i = 0; i < 5; i++) clock.tick(1000)
81
+ // job.stop()
82
+ // clock.restore()
83
+ // })
84
+ //
85
+ // it('should run every second for 5 seconds (*/1 * * * * *)', () => {
86
+ // const clock = sinon.useFakeTimers()
87
+ // const callback = jest.fn()
88
+ // const job = new CronJob('*/1 * * * * *', callback, null, true)
89
+ // for (let i = 0; i < 5; i++) clock.tick(1000)
90
+ // job.stop()
91
+ // clock.restore()
92
+ // expect(callback).toHaveBeenCalledTimes(5)
93
+ // })
94
+ //
95
+ // it('should run every 2 seconds for 1 seconds (*/2 * * * * *)', () => {
96
+ // const clock = sinon.useFakeTimers()
97
+ // const callback = jest.fn()
98
+ // const job = new CronJob('*/2 * * * * *', callback, null, true)
99
+ // clock.tick(1000)
100
+ // job.stop()
101
+ // clock.restore()
102
+ // expect(callback).toHaveBeenCalledTimes(0)
103
+ // })
104
+ //
105
+ // it('should run every 2 seconds for 5 seconds (*/2 * * * * *)', () => {
106
+ // const clock = sinon.useFakeTimers()
107
+ // const callback = jest.fn()
108
+ // const job = new CronJob('*/2 * * * * *', callback, null, true)
109
+ // for (let i = 0; i < 5; i++) clock.tick(1000)
110
+ // job.stop()
111
+ // clock.restore()
112
+ // expect(callback).toHaveBeenCalledTimes(2)
113
+ // })
114
+ //
115
+ // it('should run every second for 5 seconds with onComplete (*/1 * * * * *)', (done: any) => {
116
+ // const clock = sinon.useFakeTimers()
117
+ // const callback = jest.fn()
118
+ // const job = new CronJob(
119
+ // '*/1 * * * * *',
120
+ // callback,
121
+ // () => {
122
+ // expect(callback).toHaveBeenCalledTimes(5)
123
+ // done()
124
+ // },
125
+ // true,
126
+ // )
127
+ // for (let i = 0; i < 5; i++) clock.tick(1000)
128
+ // job.stop()
129
+ // clock.restore()
130
+ // })
131
+ //
132
+ // it('should run every second for a range ([start]-[end] * * * * *)', () => {
133
+ // const clock = sinon.useFakeTimers()
134
+ // const callback = jest.fn()
135
+ // const job = new CronJob('0-8 * * * * *', callback, null, true)
136
+ // clock.tick(10000)
137
+ // job.stop()
138
+ // clock.restore()
139
+ // expect(callback).toHaveBeenCalledTimes(8)
140
+ // })
141
+ //
142
+ // it('should run every second for a range ([start]-[end] * * * * *) with onComplete', (done: any) => {
143
+ // const clock = sinon.useFakeTimers()
144
+ // const callback = jest.fn()
145
+ // const job = new CronJob(
146
+ // '0-8 * * * * *',
147
+ // callback,
148
+ // () => {
149
+ // expect(callback).toHaveBeenCalledTimes(8)
150
+ // done()
151
+ // },
152
+ // true,
153
+ // )
154
+ // clock.tick(10000)
155
+ // job.stop()
156
+ // clock.restore()
157
+ // })
158
+ //
159
+ // it('should default to full range when upper range not provided (1/2 * * * * *)', (done: any) => {
160
+ // const clock = sinon.useFakeTimers()
161
+ // const callback = jest.fn()
162
+ // const job = new CronJob(
163
+ // '1/2 * * * * *',
164
+ // callback,
165
+ // () => {
166
+ // expect(callback).toHaveBeenCalledTimes(30)
167
+ // done()
168
+ // },
169
+ // true,
170
+ // )
171
+ // clock.tick(1000 * 60)
172
+ // job.stop()
173
+ // clock.restore()
174
+ // })
175
+ //
176
+ // it('should run every second (* * * * * *) using the object constructor', () => {
177
+ // const clock = sinon.useFakeTimers()
178
+ // const callback = jest.fn()
179
+ // const job = CronJob.from({
180
+ // cronTime: '* * * * * *',
181
+ // onTick: callback,
182
+ // start: true,
183
+ // })
184
+ // clock.tick(1000)
185
+ // job.stop()
186
+ // clock.restore()
187
+ // expect(callback).toHaveBeenCalledTimes(1)
188
+ // })
189
+ //
190
+ // it('should run every second with onComplete (* * * * * *) using the object constructor', (done: any) => {
191
+ // const clock = sinon.useFakeTimers()
192
+ // const callback = jest.fn()
193
+ // const job = CronJob.from({
194
+ // cronTime: '* * * * * *',
195
+ // onTick: callback,
196
+ // onComplete: () => {
197
+ // expect(callback).toHaveBeenCalledTimes(1)
198
+ // done()
199
+ // },
200
+ // start: true,
201
+ // })
202
+ // clock.tick(1000)
203
+ // job.stop()
204
+ // clock.restore()
205
+ // })
206
+ // })
207
+ //
208
+ // describe('with minutes', () => {
209
+ // it('should fire every 60 min', () => {
210
+ // const clock = sinon.useFakeTimers()
211
+ // const m60 = 60 * 60 * 1000
212
+ // const l: number[] = []
213
+ // const job = new CronJob(
214
+ // '00 30 * * * *',
215
+ // () => {
216
+ // l.push(Math.floor(Date.now() / 60000))
217
+ // },
218
+ // null,
219
+ // true,
220
+ // )
221
+ //
222
+ // clock.tick(m60 * 10)
223
+ //
224
+ // expect(l).toHaveLength(10)
225
+ // expect(l.every(i => i % 30 === 0)).toBe(true)
226
+ //
227
+ // job.stop()
228
+ // clock.restore()
229
+ // })
230
+ //
231
+ // it('should run every 45 minutes for 2 hours (0 */45 * * * *)', () => {
232
+ // const clock = sinon.useFakeTimers()
233
+ // const callback = jest.fn()
234
+ // const job = new CronJob('0 */45 * * * *', callback, null, true)
235
+ // for (let i = 0; i < 2; i++) clock.tick(60 * 60 * 1000)
236
+ // job.stop()
237
+ // clock.restore()
238
+ // expect(callback).toHaveBeenCalledTimes(4)
239
+ // })
240
+ //
241
+ // it('should run every 45 minutes for 2 hours (0 */45 * * * *) with onComplete', (done: any) => {
242
+ // const clock = sinon.useFakeTimers()
243
+ // const callback = jest.fn()
244
+ // const job = new CronJob(
245
+ // '0 */45 * * * *',
246
+ // callback,
247
+ // () => {
248
+ // expect(callback).toHaveBeenCalledTimes(4)
249
+ // done()
250
+ // },
251
+ // true,
252
+ // )
253
+ // for (let i = 0; i < 2; i++) clock.tick(60 * 60 * 1000)
254
+ // job.stop()
255
+ // clock.restore()
256
+ // })
257
+ // })
258
+ //
259
+ // it('should start and stop job from outside', (done: any) => {
260
+ // const clock = sinon.useFakeTimers()
261
+ // const callback = jest.fn()
262
+ // const job = new CronJob(
263
+ // '* * * * * *',
264
+ // () => {
265
+ // callback()
266
+ // },
267
+ // () => {
268
+ // expect(callback).toHaveBeenCalledTimes(1)
269
+ // clock.restore()
270
+ // done()
271
+ // },
272
+ // true,
273
+ // )
274
+ // clock.tick(1000)
275
+ // job.stop()
276
+ // })
277
+ //
278
+ // it('should start and stop job from inside (default context)', (done: any) => {
279
+ // const clock = sinon.useFakeTimers()
280
+ // const callback = jest.fn()
281
+ // new CronJob(
282
+ // '* * * * * *',
283
+ // function () {
284
+ // callback()
285
+ // this.stop()
286
+ // },
287
+ // () => {
288
+ // expect(callback).toHaveBeenCalledTimes(1)
289
+ // clock.restore()
290
+ // done()
291
+ // },
292
+ // true,
293
+ // )
294
+ // clock.tick(1000)
295
+ // })
296
+ //
297
+ // describe('with date', () => {
298
+ // it('should run on a specific date', () => {
299
+ // const d = new Date()
300
+ // const clock = sinon.useFakeTimers(d.getTime())
301
+ // const s = d.getSeconds() + 1
302
+ // d.setSeconds(s)
303
+ // const callback = jest.fn()
304
+ // const job = new CronJob(
305
+ // d,
306
+ // () => {
307
+ // const t = new Date()
308
+ // expect(t.getSeconds()).toBe(d.getSeconds())
309
+ // callback()
310
+ // },
311
+ // null,
312
+ // true,
313
+ // )
314
+ // clock.tick(1000)
315
+ // clock.restore()
316
+ // job.stop()
317
+ // expect(callback).toHaveBeenCalledTimes(1)
318
+ // })
319
+ //
320
+ // it('should run on a specific date and call onComplete from onTick', async () => {
321
+ // const d = new Date()
322
+ // const clock = sinon.useFakeTimers(d.getTime())
323
+ // d.setSeconds(d.getSeconds() + 1)
324
+ // const callback = jest.fn()
325
+ //
326
+ // await new Promise<void>((resolve) => {
327
+ // const job = new CronJob(
328
+ // d,
329
+ // (onComplete) => {
330
+ // const t = new Date()
331
+ // expect(t.getSeconds()).toBe(d.getSeconds())
332
+ // void onComplete()
333
+ // },
334
+ // () => {
335
+ // callback()
336
+ // resolve()
337
+ // },
338
+ // true,
339
+ // )
340
+ // clock.tick(1000)
341
+ // clock.restore()
342
+ // job.stop()
343
+ // })
344
+ //
345
+ // // onComplete is called 2 times: once in onTick() & once when calling job.stop()
346
+ // expect(callback).toHaveBeenCalledTimes(2)
347
+ // })
348
+ //
349
+ // it('should run on a specific date and call onComplete from onTick using the object constructor', async () => {
350
+ // const d = new Date()
351
+ // const clock = sinon.useFakeTimers(d.getTime())
352
+ // d.setSeconds(d.getSeconds() + 1)
353
+ // const callback = jest.fn()
354
+ //
355
+ // await new Promise<void>((resolve) => {
356
+ // const job = CronJob.from({
357
+ // cronTime: d,
358
+ // onTick: (onComplete) => {
359
+ // const t = new Date()
360
+ // expect(t.getSeconds()).toBe(d.getSeconds())
361
+ // void onComplete()
362
+ // },
363
+ // onComplete: function () {
364
+ // callback()
365
+ // resolve()
366
+ // } as () => void,
367
+ // start: true,
368
+ // })
369
+ // clock.tick(1000)
370
+ // clock.restore()
371
+ // job.stop()
372
+ // })
373
+ //
374
+ // // onComplete is called 2 times: once in onTick() & once when calling job.stop()
375
+ // expect(callback).toHaveBeenCalledTimes(2)
376
+ // })
377
+ //
378
+ // it('should not be able to call onComplete from onTick if if wasn\'t provided', () => {
379
+ // expect.assertions(4)
380
+ // const d = new Date()
381
+ // const clock = sinon.useFakeTimers(d.getTime())
382
+ // d.setSeconds(d.getSeconds() + 1)
383
+ //
384
+ // const job = new CronJob(
385
+ // d,
386
+ // (onComplete) => {
387
+ // const t = new Date()
388
+ // expect(onComplete).toBeUndefined()
389
+ // try {
390
+ // // @ts-expect-error should be a TS warning and throw
391
+ // onComplete()
392
+ // }
393
+ // catch (e) {
394
+ // // we make sure this isn't skipped with `expect.assertions()`
395
+ // // at the beginning of the test
396
+ // expect(e).toBeInstanceOf(TypeError)
397
+ // }
398
+ // expect(onComplete).toBeUndefined()
399
+ // expect(t.getSeconds()).toBe(d.getSeconds())
400
+ // },
401
+ // null,
402
+ // true,
403
+ // )
404
+ // clock.tick(1000)
405
+ // job.stop()
406
+ // clock.restore()
407
+ // })
408
+ //
409
+ // it('should wait and not fire immediately', () => {
410
+ // const clock = sinon.useFakeTimers()
411
+ // const callback = jest.fn()
412
+ //
413
+ // const d = new Date().getTime() + 31 * 86400 * 1000
414
+ //
415
+ // const job = new CronJob(new Date(d), callback)
416
+ // job.start()
417
+ //
418
+ // clock.tick(1000)
419
+ //
420
+ // clock.restore()
421
+ // job.stop()
422
+ // expect(callback).toHaveBeenCalledTimes(0)
423
+ // })
424
+ //
425
+ // it('should wait but fire on init', () => {
426
+ // const clock = sinon.useFakeTimers()
427
+ // const callback = jest.fn()
428
+ //
429
+ // const d = new Date().getTime() + 31 * 86400 * 1000
430
+ //
431
+ // const job = CronJob.from({
432
+ // cronTime: new Date(d),
433
+ // onTick: callback,
434
+ // runOnInit: true,
435
+ // })
436
+ //
437
+ // expect(callback).toHaveBeenCalledTimes(1)
438
+ //
439
+ // job.start()
440
+ //
441
+ // clock.tick(1000)
442
+ //
443
+ // clock.restore()
444
+ // job.stop()
445
+ // expect(callback).toHaveBeenCalledTimes(1)
446
+ // })
447
+ //
448
+ // it('should fire on init but not run until started', () => {
449
+ // const clock = sinon.useFakeTimers()
450
+ // const callback = jest.fn()
451
+ //
452
+ // const job = CronJob.from({
453
+ // cronTime: '* * * * * *',
454
+ // onTick: callback,
455
+ // runOnInit: true,
456
+ // })
457
+ //
458
+ // expect(callback).toHaveBeenCalledTimes(1)
459
+ //
460
+ // job.start()
461
+ //
462
+ // clock.tick(3500)
463
+ //
464
+ // clock.restore()
465
+ // job.stop()
466
+ // expect(callback).toHaveBeenCalledTimes(4)
467
+ // })
468
+ // })
469
+ //
470
+ // describe('with timezone', () => {
471
+ // it('should run a job using cron syntax with a timezone', () => {
472
+ // const clock = sinon.useFakeTimers()
473
+ // const callback = jest.fn()
474
+ // let zone = 'America/Chicago'
475
+ // // New Orleans time
476
+ // let t = DateTime.local().setZone(zone)
477
+ // // Current time
478
+ // const d = DateTime.local()
479
+ //
480
+ // // If current time is New Orleans time, switch to Los Angeles..
481
+ // if (t.hour === d.hour) {
482
+ // zone = 'America/Los_Angeles'
483
+ // t = t.setZone(zone)
484
+ // }
485
+ // expect(d.hour).not.toBe(t.hour)
486
+ //
487
+ // // If t = 59s12m then t.setSeconds(60)
488
+ // // becomes 00s13m so we're fine just doing
489
+ // // this and no testRun callback.
490
+ // t = t.plus({ seconds: 1 })
491
+ // // Run a job designed to be executed at a given
492
+ // // time in `zone`, making sure that it is a different
493
+ // // hour than local time.
494
+ // const job = new CronJob(
495
+ // `${t.second} ${t.minute} ${t.hour} * * *`,
496
+ // callback,
497
+ // null,
498
+ // true,
499
+ // zone,
500
+ // )
501
+ //
502
+ // clock.tick(1000)
503
+ // clock.restore()
504
+ // job.stop()
505
+ // expect(callback).toHaveBeenCalledTimes(1)
506
+ // })
507
+ //
508
+ // it('should run a job using cron syntax with a "UTC+HH:mm" offset as timezone', () => {
509
+ // const clock = sinon.useFakeTimers()
510
+ // const callback = jest.fn()
511
+ //
512
+ // // Current time
513
+ // const d = DateTime.local()
514
+ //
515
+ // // Current time with zone offset
516
+ // let zone = 'UTC+5:30'
517
+ // let t = DateTime.local().setZone(zone)
518
+ //
519
+ // // If current offset is UTC+5:30, switch to UTC+6:30..
520
+ // if (t.hour === d.hour && t.minute === d.minute) {
521
+ // zone = 'UTC+6:30'
522
+ // t = t.setZone(zone)
523
+ // }
524
+ // expect(`${d.hour}:${d.minute}`).not.toBe(`${t.hour}:${t.minute}`)
525
+ //
526
+ // // If t = 59s12m then t.setSeconds(60)
527
+ // // becomes 00s13m so we're fine just doing
528
+ // // this and no testRun callback.
529
+ // t = t.plus({ seconds: 1 })
530
+ // // Run a job designed to be executed at a given
531
+ // // time in `zone`, making sure that it is a different
532
+ // // hour than local time.
533
+ // const job = new CronJob(
534
+ // `${t.second} ${t.minute} ${t.hour} * * *`,
535
+ // callback,
536
+ // null,
537
+ // true,
538
+ // zone,
539
+ // )
540
+ //
541
+ // clock.tick(1000)
542
+ // clock.restore()
543
+ // job.stop()
544
+ // expect(callback).toHaveBeenCalledTimes(1)
545
+ // })
546
+ //
547
+ // it('should run a job using a date', () => {
548
+ // let zone = 'America/Chicago'
549
+ // // New Orleans time
550
+ // let t = DateTime.local().setZone(zone)
551
+ // // Current time
552
+ // let d = DateTime.local()
553
+ //
554
+ // // If current time is New Orleans time, switch to Los Angeles..
555
+ // if (t.hour === d.hour) {
556
+ // zone = 'America/Los_Angeles'
557
+ // t = t.setZone(zone)
558
+ // }
559
+ //
560
+ // expect(d.hour).not.toBe(t.hour)
561
+ // d = d.plus({ seconds: 1 })
562
+ // const clock = sinon.useFakeTimers(d.valueOf())
563
+ // const callback = jest.fn()
564
+ // const job = new CronJob(d.toJSDate(), callback, null, true, zone)
565
+ // clock.tick(1000)
566
+ // clock.restore()
567
+ // job.stop()
568
+ // expect(callback).toHaveBeenCalledTimes(1)
569
+ // })
570
+ //
571
+ // it('should test if timezone is valid.', () => {
572
+ // expect(() => {
573
+ // CronJob.from({
574
+ // cronTime: '* * * * * *',
575
+ // onTick: () => { },
576
+ // timeZone: 'fake/timezone',
577
+ // })
578
+ // }).toThrow()
579
+ // })
580
+ // })
581
+ //
582
+ // describe('onTick scoping', () => {
583
+ // it('should scope onTick to running job', () => {
584
+ // const clock = sinon.useFakeTimers()
585
+ //
586
+ // const job = new CronJob(
587
+ // '* * * * * *',
588
+ // function () {
589
+ // expect(job).toBeInstanceOf(CronJob)
590
+ // expect(job).toEqual(this)
591
+ // },
592
+ // null,
593
+ // true,
594
+ // )
595
+ //
596
+ // clock.tick(1000)
597
+ //
598
+ // clock.restore()
599
+ // job.stop()
600
+ // })
601
+ //
602
+ // it('should scope onTick to running job using the object constructor', () => {
603
+ // const clock = sinon.useFakeTimers()
604
+ //
605
+ // const job = CronJob.from({
606
+ // cronTime: '* * * * * *',
607
+ // onTick() {
608
+ // expect(job).toBeInstanceOf(CronJob)
609
+ // expect(job).toEqual(this)
610
+ // },
611
+ // start: true,
612
+ // })
613
+ //
614
+ // clock.tick(1000)
615
+ //
616
+ // clock.restore()
617
+ // job.stop()
618
+ // })
619
+ //
620
+ // it('should scope onTick to object', () => {
621
+ // const clock = sinon.useFakeTimers()
622
+ //
623
+ // const job = new CronJob(
624
+ // '* * * * * *',
625
+ // function () {
626
+ // expect(this.hello).toBe('world')
627
+ // expect(job).not.toEqual(this)
628
+ // },
629
+ // null,
630
+ // true,
631
+ // null,
632
+ // { hello: 'world' },
633
+ // )
634
+ //
635
+ // clock.tick(1000)
636
+ //
637
+ // clock.restore()
638
+ // job.stop()
639
+ // })
640
+ //
641
+ // it('should scope onTick to object using the object constructor', () => {
642
+ // const clock = sinon.useFakeTimers()
643
+ //
644
+ // const job = CronJob.from({
645
+ // cronTime: '* * * * * *',
646
+ // onTick() {
647
+ // expect(this.hello).toBe('world')
648
+ // expect(job).not.toEqual(this)
649
+ // },
650
+ // start: true,
651
+ // context: { hello: 'world' },
652
+ // })
653
+ //
654
+ // clock.tick(1000)
655
+ //
656
+ // clock.restore()
657
+ // job.stop()
658
+ // })
659
+ // })
660
+ //
661
+ // it('should not get into an infinite loop on invalid times', () => {
662
+ // expect(() => {
663
+ // new CronJob(
664
+ // '* 60 * * * *',
665
+ // () => {
666
+ // expect(true).toBe(true)
667
+ // },
668
+ // null,
669
+ // true,
670
+ // )
671
+ // }).toThrow()
672
+ //
673
+ // expect(() => {
674
+ // new CronJob(
675
+ // '* * 24 * * *',
676
+ // () => {
677
+ // expect(true).toBe(true)
678
+ // },
679
+ // null,
680
+ // true,
681
+ // )
682
+ // }).toThrow()
683
+ // })
684
+ //
685
+ // it('should test start of month', () => {
686
+ // const callback = jest.fn()
687
+ // const d = new Date('12/31/2014')
688
+ // d.setSeconds(59)
689
+ // d.setMinutes(59)
690
+ // d.setHours(23)
691
+ // const clock = sinon.useFakeTimers(d.getTime())
692
+ //
693
+ // const job = new CronJob('0 0 0 1 * *', callback, null, true)
694
+ //
695
+ // clock.tick(1001)
696
+ // expect(callback).toHaveBeenCalledTimes(1)
697
+ //
698
+ // clock.tick(2678399001)
699
+ // expect(callback).toHaveBeenCalledTimes(1)
700
+ //
701
+ // clock.tick(2678400001) // jump over 2 firsts
702
+ // clock.restore()
703
+ // job.stop()
704
+ //
705
+ // expect(callback).toHaveBeenCalledTimes(3)
706
+ // })
707
+ //
708
+ // it('should not fire if time was adjusted back', () => {
709
+ // const callback = jest.fn()
710
+ // const clock = sinon.useFakeTimers({
711
+ // toFake: ['setTimeout'],
712
+ // })
713
+ //
714
+ // const job = new CronJob('0 * * * * *', callback, null, true)
715
+ //
716
+ // clock.tick(60000)
717
+ // expect(callback).toHaveBeenCalledTimes(0)
718
+ //
719
+ // clock.restore()
720
+ // job.stop()
721
+ // })
722
+ //
723
+ // it('should run every day', () => {
724
+ // const callback = jest.fn()
725
+ // const d = new Date('12/31/2014')
726
+ // d.setSeconds(59)
727
+ // d.setMinutes(59)
728
+ // d.setHours(23)
729
+ // const clock = sinon.useFakeTimers(d.getTime())
730
+ //
731
+ // const job = CronJob.from({
732
+ // cronTime: '59 59 3 * * *',
733
+ // onTick: callback,
734
+ // start: true,
735
+ // timeZone: 'America/Los_Angeles',
736
+ // })
737
+ //
738
+ // const twoWeeks = 14 * 24 * 60 * 60 * 1000
739
+ // clock.tick(twoWeeks)
740
+ //
741
+ // clock.restore()
742
+ // job.stop()
743
+ // expect(callback).toHaveBeenCalledTimes(14)
744
+ // })
745
+ //
746
+ // it('should run every 2 hours between hours', () => {
747
+ // const callback = jest.fn()
748
+ // const d = new Date('12/31/2014')
749
+ // d.setSeconds(0)
750
+ // d.setMinutes(0)
751
+ // d.setHours(0)
752
+ // const clock = sinon.useFakeTimers(d.getTime())
753
+ //
754
+ // const job = CronJob.from({
755
+ // cronTime: '0 2-6/2 * * * *',
756
+ // onTick: callback,
757
+ // start: true,
758
+ // })
759
+ //
760
+ // clock.tick(2 * 60 * 1000)
761
+ // expect(callback).toHaveBeenCalledTimes(1)
762
+ // clock.tick(2 * 60 * 1000)
763
+ // expect(callback).toHaveBeenCalledTimes(2)
764
+ // clock.tick(2 * 60 * 1000)
765
+ // expect(callback).toHaveBeenCalledTimes(3)
766
+ // clock.tick(2 * 60 * 1000)
767
+ //
768
+ // clock.restore()
769
+ // job.stop()
770
+ // expect(callback).toHaveBeenCalledTimes(3)
771
+ // })
772
+ //
773
+ // it('should run every minute', () => {
774
+ // const callback = jest.fn()
775
+ // const d = new Date('12/31/2014')
776
+ // d.setSeconds(0)
777
+ // d.setMinutes(0)
778
+ // d.setHours(0)
779
+ // const clock = sinon.useFakeTimers(d.getTime())
780
+ //
781
+ // const job = CronJob.from({
782
+ // cronTime: '00 * * * * *',
783
+ // onTick: callback,
784
+ // start: true,
785
+ // })
786
+ //
787
+ // clock.tick(60 * 1000)
788
+ // expect(callback).toHaveBeenCalledTimes(1)
789
+ // clock.tick(60 * 1000)
790
+ // expect(callback).toHaveBeenCalledTimes(2)
791
+ //
792
+ // clock.restore()
793
+ // job.stop()
794
+ // expect(callback).toHaveBeenCalledTimes(2)
795
+ // })
796
+ //
797
+ // it('should run every day at 12:30', () => {
798
+ // const callback = jest.fn()
799
+ // const d = new Date('12/31/2014')
800
+ // d.setSeconds(0)
801
+ // d.setMinutes(0)
802
+ // d.setHours(0)
803
+ // const clock = sinon.useFakeTimers(d.getTime())
804
+ //
805
+ // const job = CronJob.from({
806
+ // cronTime: '00 30 00 * * *',
807
+ // onTick: callback,
808
+ // start: true,
809
+ // })
810
+ //
811
+ // const day = 24 * 60 * 60 * 1000
812
+ // clock.tick(day)
813
+ // expect(callback).toHaveBeenCalledTimes(1)
814
+ // clock.tick(day)
815
+ // expect(callback).toHaveBeenCalledTimes(2)
816
+ // clock.tick(day)
817
+ // expect(callback).toHaveBeenCalledTimes(3)
818
+ // clock.tick(5 * day)
819
+ //
820
+ // clock.restore()
821
+ // job.stop()
822
+ // expect(callback).toHaveBeenCalledTimes(8)
823
+ // })
824
+ //
825
+ // it('should trigger onTick at midnight', () => {
826
+ // const callback = jest.fn()
827
+ // const d = new Date('12/31/2014')
828
+ // d.setSeconds(59)
829
+ // d.setMinutes(59)
830
+ // d.setHours(23)
831
+ // const clock = sinon.useFakeTimers(d.getTime())
832
+ //
833
+ // const job = CronJob.from({
834
+ // cronTime: '00 * * * * *',
835
+ // onTick: callback,
836
+ // start: true,
837
+ // timeZone: 'UTC',
838
+ // })
839
+ //
840
+ // clock.tick(1000) // move clock 1 second
841
+ // expect(callback).toHaveBeenCalledTimes(1)
842
+ //
843
+ // clock.restore()
844
+ // job.stop()
845
+ // expect(callback).toHaveBeenCalledTimes(1)
846
+ // })
847
+ //
848
+ // it('should run every day UTC', () => {
849
+ // const callback = jest.fn()
850
+ // const d = new Date('12/31/2014')
851
+ // d.setSeconds(0)
852
+ // d.setMinutes(0)
853
+ // d.setHours(0)
854
+ // const clock = sinon.useFakeTimers(d.getTime())
855
+ //
856
+ // const job = CronJob.from({
857
+ // cronTime: '00 30 00 * * *',
858
+ // onTick: callback,
859
+ // start: true,
860
+ // timeZone: 'UTC',
861
+ // })
862
+ //
863
+ // const day = 24 * 60 * 60 * 1000
864
+ // clock.tick(day)
865
+ // expect(callback).toHaveBeenCalledTimes(1)
866
+ // clock.tick(day)
867
+ // expect(callback).toHaveBeenCalledTimes(2)
868
+ // clock.tick(day)
869
+ // expect(callback).toHaveBeenCalledTimes(3)
870
+ // clock.tick(5 * day)
871
+ //
872
+ // clock.restore()
873
+ // job.stop()
874
+ // expect(callback).toHaveBeenCalledTimes(8)
875
+ // })
876
+ //
877
+ // // from https://github.com/kelektiv/node-cron/issues/180#issuecomment-154108131
878
+ // it('should run once not double', () => {
879
+ // const callback = jest.fn()
880
+ // const d = new Date(2015, 1, 1, 1, 1, 41, 0)
881
+ // const clock = sinon.useFakeTimers(d.getTime())
882
+ //
883
+ // const job = CronJob.from({
884
+ // cronTime: '* * * * *',
885
+ // onTick: callback,
886
+ // start: true,
887
+ // })
888
+ //
889
+ // const minute = 60 * 1000
890
+ // clock.tick(minute)
891
+ // expect(callback).toHaveBeenCalledTimes(1)
892
+ // clock.restore()
893
+ // job.stop()
894
+ // expect(callback).toHaveBeenCalledTimes(1)
895
+ // })
896
+ //
897
+ // /**
898
+ // * maximum match interval is 8 years:
899
+ // * crontab has '* * 29 2 *' and we are on 1 March 2096:
900
+ // * next matching time will be 29 February 2104
901
+ // * source: https://github.com/cronie-crond/cronie/blob/0d669551680f733a4bdd6bab082a0b3d6d7f089c/src/cronnext.c#L401-L403
902
+ // */
903
+ // it('should work correctly for max match interval', () => {
904
+ // const callback = jest.fn()
905
+ // const d = new Date(2096, 2, 1)
906
+ // const clock = sinon.useFakeTimers(d.getTime())
907
+ //
908
+ // const job = CronJob.from({
909
+ // cronTime: ' * * 29 2 *',
910
+ // onTick: callback,
911
+ // start: true,
912
+ // })
913
+ //
914
+ // // 7 years, 11 months and 27 days
915
+ // const almostEightYears = 2919 * 24 * 60 * 60 * 1000
916
+ // clock.tick(almostEightYears)
917
+ // expect(callback).toHaveBeenCalledTimes(0)
918
+ //
919
+ // // tick by 1 day
920
+ // clock.tick(24 * 60 * 60 * 1000)
921
+ // clock.restore()
922
+ // job.stop()
923
+ // expect(callback).toHaveBeenCalledTimes(1)
924
+ // })
925
+ //
926
+ // describe('with utcOffset', () => {
927
+ // it('should run a job using cron syntax with number format utcOffset', () => {
928
+ // const clock = sinon.useFakeTimers()
929
+ // const callback = jest.fn()
930
+ // // Current time
931
+ // const t = DateTime.local()
932
+ // // UTC Offset decreased by an hour
933
+ // const utcOffset = t.offset - 60
934
+ //
935
+ // const job = new CronJob(
936
+ // `${t.second} ${t.minute} ${t.hour} * * *`,
937
+ // callback,
938
+ // null,
939
+ // true,
940
+ // null,
941
+ // null,
942
+ // null,
943
+ // utcOffset,
944
+ // )
945
+ //
946
+ // // tick 1 sec before an hour
947
+ // clock.tick(1000 * 60 * 60 - 1)
948
+ // expect(callback).toHaveBeenCalledTimes(0)
949
+ //
950
+ // clock.tick(1)
951
+ // clock.restore()
952
+ // job.stop()
953
+ // expect(callback).toHaveBeenCalledTimes(1)
954
+ // })
955
+ //
956
+ // it('should run a job using cron syntax with numeric format utcOffset with minute support', () => {
957
+ // const clock = sinon.useFakeTimers()
958
+ // const callback = jest.fn()
959
+ // // Current time
960
+ // const t = DateTime.local()
961
+ //
962
+ // // UTC Offset decreased by 45 minutes
963
+ // const utcOffset = t.offset - 45
964
+ // const job = new CronJob(
965
+ // `${t.second} ${t.minute} ${t.hour} * * *`,
966
+ // callback,
967
+ // null,
968
+ // true,
969
+ // null,
970
+ // null,
971
+ // null,
972
+ // utcOffset,
973
+ // )
974
+ //
975
+ // // tick 1 sec before 45 minutes
976
+ // clock.tick(1000 * 45 * 60 - 1)
977
+ // expect(callback).toHaveBeenCalledTimes(0)
978
+ //
979
+ // clock.tick(1)
980
+ // clock.restore()
981
+ // job.stop()
982
+ // expect(callback).toHaveBeenCalledTimes(1)
983
+ // })
984
+ //
985
+ // it('should run a job using cron syntax with number format utcOffset that is 0', () => {
986
+ // const clock = sinon.useFakeTimers()
987
+ // const callback = jest.fn()
988
+ //
989
+ // const job = new CronJob(
990
+ // '* * * * * *',
991
+ // callback,
992
+ // null,
993
+ // true,
994
+ // null,
995
+ // null,
996
+ // null,
997
+ // 0,
998
+ // )
999
+ //
1000
+ // clock.tick(999)
1001
+ // expect(callback).toHaveBeenCalledTimes(0)
1002
+ //
1003
+ // clock.tick(1)
1004
+ // clock.restore()
1005
+ // job.stop()
1006
+ // expect(callback).toHaveBeenCalledTimes(1)
1007
+ // })
1008
+ //
1009
+ // it('should be able to detect out of range days of month', () => {
1010
+ // expect(() => {
1011
+ // new CronTime('* * 32 FEB *')
1012
+ // }).toThrow()
1013
+ // })
1014
+ // })
1015
+ //
1016
+ // describe('setTime', () => {
1017
+ // it('should start, change time, start again', () => {
1018
+ // const callback = jest.fn()
1019
+ // const clock = sinon.useFakeTimers()
1020
+ //
1021
+ // const job = new CronJob('* * * * * *', callback)
1022
+ //
1023
+ // job.start()
1024
+ // clock.tick(1000)
1025
+ //
1026
+ // const time = new CronTime('*/2 * * * * *')
1027
+ // job.setTime(time)
1028
+ //
1029
+ // clock.tick(4000)
1030
+ //
1031
+ // clock.restore()
1032
+ // job.stop()
1033
+ // expect(callback).toHaveBeenCalledTimes(3)
1034
+ // })
1035
+ //
1036
+ // it('should start, stop, change time, not start again', () => {
1037
+ // const callback = jest.fn()
1038
+ // const clock = sinon.useFakeTimers()
1039
+ //
1040
+ // const job = new CronJob('* * * * * *', callback)
1041
+ //
1042
+ // job.start()
1043
+ // clock.tick(1000)
1044
+ //
1045
+ // job.stop()
1046
+ // const time = new CronTime('*/2 * * * * *')
1047
+ // job.setTime(time)
1048
+ //
1049
+ // clock.tick(4000)
1050
+ //
1051
+ // clock.restore()
1052
+ // job.stop()
1053
+ // expect(callback).toHaveBeenCalledTimes(1)
1054
+ // })
1055
+ //
1056
+ // it('should setTime with invalid object', () => {
1057
+ // const callback = jest.fn()
1058
+ // const job = new CronJob('* * * * * *', callback)
1059
+ // expect(() => {
1060
+ // // @ts-expect-error time parameter cannot be undefined
1061
+ // job.setTime(undefined)
1062
+ // }).toThrow()
1063
+ // })
1064
+ //
1065
+ // it('should start, change time, exception', () => {
1066
+ // const callback = jest.fn()
1067
+ // const clock = sinon.useFakeTimers()
1068
+ //
1069
+ // const job = new CronJob('* * * * * *', callback)
1070
+ //
1071
+ // const time = new Date()
1072
+ // job.start()
1073
+ //
1074
+ // clock.tick(1000)
1075
+ //
1076
+ // expect(() => {
1077
+ // // @ts-expect-error time parameter but be an instance of CronTime
1078
+ // job.setTime(time)
1079
+ // }).toThrow()
1080
+ //
1081
+ // clock.restore()
1082
+ // job.stop()
1083
+ // expect(callback).toHaveBeenCalledTimes(1)
1084
+ // })
1085
+ //
1086
+ // it('should create recurring job, setTime with actual date, start and run once (#739)', () => {
1087
+ // const callback = jest.fn()
1088
+ // const clock = sinon.useFakeTimers()
1089
+ //
1090
+ // const job = new CronJob('0 0 20 * * *', callback)
1091
+ //
1092
+ // const startDate = new Date(Date.now() + 5000)
1093
+ // job.setTime(new CronTime(startDate))
1094
+ //
1095
+ // job.start()
1096
+ //
1097
+ // clock.tick(5000)
1098
+ //
1099
+ // expect(callback).toHaveBeenCalledTimes(1)
1100
+ //
1101
+ // clock.tick(60000)
1102
+ //
1103
+ // clock.restore()
1104
+ //
1105
+ // expect(callback).toHaveBeenCalledTimes(1)
1106
+ // expect(job.running).toBe(false)
1107
+ // })
1108
+ // })
1109
+ //
1110
+ // describe('nextDate(s)', () => {
1111
+ // it('should give the next date to run at', () => {
1112
+ // const callback = jest.fn()
1113
+ // const clock = sinon.useFakeTimers()
1114
+ // const job = new CronJob('* * * * * *', callback)
1115
+ // const d = Date.now()
1116
+ //
1117
+ // expect(job.nextDate().toMillis()).toEqual(d + 1000)
1118
+ //
1119
+ // clock.restore()
1120
+ // })
1121
+ //
1122
+ // it('should give the next 5 dates to run at', () => {
1123
+ // const callback = jest.fn()
1124
+ // const clock = sinon.useFakeTimers()
1125
+ // const job = new CronJob('* * * * * *', callback)
1126
+ // const d = Date.now()
1127
+ //
1128
+ // expect(job.nextDates(5).map(d => d.toMillis())).toEqual([
1129
+ // d + 1000,
1130
+ // d + 2000,
1131
+ // d + 3000,
1132
+ // d + 4000,
1133
+ // d + 5000,
1134
+ // ])
1135
+ //
1136
+ // clock.restore()
1137
+ // })
1138
+ //
1139
+ // it('should give an empty array when called without argument', () => {
1140
+ // const callback = jest.fn()
1141
+ // const clock = sinon.useFakeTimers()
1142
+ // const job = new CronJob('* * * * * *', callback)
1143
+ //
1144
+ // expect(job.nextDates()).toHaveLength(0)
1145
+ //
1146
+ // clock.restore()
1147
+ // })
1148
+ // })
1149
+ //
1150
+ // it('should automatically setup a new timeout if we roll past the max timeout delay', () => {
1151
+ // const callback = jest.fn()
1152
+ // const clock = sinon.useFakeTimers()
1153
+ // const d = new Date()
1154
+ // d.setMilliseconds(2147485647 * 2) // MAXDELAY in `job.js` + 2000.
1155
+ // const job = new CronJob(d, callback)
1156
+ // job.start()
1157
+ // clock.tick(2147483648)
1158
+ // expect(callback).toHaveBeenCalledTimes(0)
1159
+ // clock.tick(2147489648)
1160
+ // expect(callback).toHaveBeenCalledTimes(1)
1161
+ // job.stop()
1162
+ // clock.restore()
1163
+ // })
1164
+ //
1165
+ // it('should give the correct last execution date', () => {
1166
+ // const callback = jest.fn()
1167
+ // const clock = sinon.useFakeTimers()
1168
+ // const job = new CronJob('* * * * * *', callback)
1169
+ // job.start()
1170
+ // clock.tick(1000)
1171
+ // expect(callback).toHaveBeenCalledTimes(1)
1172
+ // expect(job.lastDate()?.getTime()).toBe(1000)
1173
+ // job.stop()
1174
+ // clock.restore()
1175
+ // })
1176
+ //
1177
+ // it('should give the correct last execution date for intervals greater than 25 days (#710)', () => {
1178
+ // const callback = jest.fn()
1179
+ // const clock = sinon.useFakeTimers()
1180
+ //
1181
+ // const job = new CronJob('0 0 0 1 * *', callback) // At 00:00 on day-of-month 1.
1182
+ // job.start()
1183
+ //
1184
+ // // tick one tick before nextDate()
1185
+ // clock.tick(job.nextDate().toMillis() - 1)
1186
+ //
1187
+ // expect(callback).toHaveBeenCalledTimes(0)
1188
+ // expect(job.lastDate()?.getTime()).toBeUndefined()
1189
+ //
1190
+ // job.stop()
1191
+ // clock.restore()
1192
+ // })
1193
+ //
1194
+ // it('should throw when providing both exclusive parameters timeZone and utcOffset', () => {
1195
+ // expect(() => {
1196
+ // // @ts-expect-error testing runtime exception
1197
+ // new CronJob(
1198
+ // `* * * * *`,
1199
+ // () => { },
1200
+ // null,
1201
+ // true,
1202
+ // 'America/Chicago',
1203
+ // null,
1204
+ // null,
1205
+ // 120,
1206
+ // )
1207
+ // }).toThrow()
1208
+ // })
1209
+ //
1210
+ // it('should throw when providing both exclusive parameters timeZone and utcOffset using the object constructor', () => {
1211
+ // expect(() => {
1212
+ // // @ts-expect-error testing runtime exception
1213
+ // CronJob.from({
1214
+ // cronTime: '* * * * * *',
1215
+ // onTick() { },
1216
+ // timeZone: 'America/Chicago',
1217
+ // utcOffset: 120,
1218
+ // })
1219
+ // }).toThrow()
1220
+ // })
1221
+ //
1222
+ // it('should support async callback', () => {
1223
+ // const clock = sinon.useFakeTimers()
1224
+ // const callback = jest.fn()
1225
+ // const job = new CronJob(
1226
+ // '* * * * * *',
1227
+ // async () => {
1228
+ // await new Promise<void>((resolve) => {
1229
+ // setTimeout(() => {
1230
+ // callback()
1231
+ // resolve()
1232
+ // }, 500)
1233
+ // })
1234
+ // },
1235
+ // null,
1236
+ // true,
1237
+ // )
1238
+ // clock.tick(1500)
1239
+ // job.stop()
1240
+ // clock.restore()
1241
+ // expect(callback).toHaveBeenCalledTimes(1)
1242
+ // })
1243
+ // })