scheduler.spec.ts 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. import {
  2. queueJob,
  3. nextTick,
  4. queuePostFlushCb,
  5. invalidateJob
  6. } from '../src/scheduler'
  7. describe('scheduler', () => {
  8. it('nextTick', async () => {
  9. const calls: string[] = []
  10. const dummyThen = Promise.resolve().then()
  11. const job1 = () => {
  12. calls.push('job1')
  13. }
  14. const job2 = () => {
  15. calls.push('job2')
  16. }
  17. nextTick(job1)
  18. job2()
  19. expect(calls.length).toBe(1)
  20. await dummyThen
  21. // job1 will be pushed in nextTick
  22. expect(calls.length).toBe(2)
  23. expect(calls).toMatchObject(['job2', 'job1'])
  24. })
  25. describe('queueJob', () => {
  26. it('basic usage', async () => {
  27. const calls: string[] = []
  28. const job1 = () => {
  29. calls.push('job1')
  30. }
  31. const job2 = () => {
  32. calls.push('job2')
  33. }
  34. queueJob(job1)
  35. queueJob(job2)
  36. expect(calls).toEqual([])
  37. await nextTick()
  38. expect(calls).toEqual(['job1', 'job2'])
  39. })
  40. it('should dedupe queued jobs', async () => {
  41. const calls: string[] = []
  42. const job1 = () => {
  43. calls.push('job1')
  44. }
  45. const job2 = () => {
  46. calls.push('job2')
  47. }
  48. queueJob(job1)
  49. queueJob(job2)
  50. queueJob(job1)
  51. queueJob(job2)
  52. expect(calls).toEqual([])
  53. await nextTick()
  54. expect(calls).toEqual(['job1', 'job2'])
  55. })
  56. it('queueJob while flushing', async () => {
  57. const calls: string[] = []
  58. const job1 = () => {
  59. calls.push('job1')
  60. // job2 will be excuted after job1 at the same tick
  61. queueJob(job2)
  62. }
  63. const job2 = () => {
  64. calls.push('job2')
  65. }
  66. queueJob(job1)
  67. await nextTick()
  68. expect(calls).toEqual(['job1', 'job2'])
  69. })
  70. })
  71. describe('queuePostFlushCb', () => {
  72. it('basic usage', async () => {
  73. const calls: string[] = []
  74. const cb1 = () => {
  75. calls.push('cb1')
  76. }
  77. const cb2 = () => {
  78. calls.push('cb2')
  79. }
  80. const cb3 = () => {
  81. calls.push('cb3')
  82. }
  83. queuePostFlushCb([cb1, cb2])
  84. queuePostFlushCb(cb3)
  85. expect(calls).toEqual([])
  86. await nextTick()
  87. expect(calls).toEqual(['cb1', 'cb2', 'cb3'])
  88. })
  89. it('should dedupe queued postFlushCb', async () => {
  90. const calls: string[] = []
  91. const cb1 = () => {
  92. calls.push('cb1')
  93. }
  94. const cb2 = () => {
  95. calls.push('cb2')
  96. }
  97. const cb3 = () => {
  98. calls.push('cb3')
  99. }
  100. queuePostFlushCb([cb1, cb2])
  101. queuePostFlushCb(cb3)
  102. queuePostFlushCb([cb1, cb3])
  103. queuePostFlushCb(cb2)
  104. expect(calls).toEqual([])
  105. await nextTick()
  106. expect(calls).toEqual(['cb1', 'cb2', 'cb3'])
  107. })
  108. it('queuePostFlushCb while flushing', async () => {
  109. const calls: string[] = []
  110. const cb1 = () => {
  111. calls.push('cb1')
  112. // cb2 will be excuted after cb1 at the same tick
  113. queuePostFlushCb(cb2)
  114. }
  115. const cb2 = () => {
  116. calls.push('cb2')
  117. }
  118. queuePostFlushCb(cb1)
  119. await nextTick()
  120. expect(calls).toEqual(['cb1', 'cb2'])
  121. })
  122. })
  123. describe('queueJob w/ queuePostFlushCb', () => {
  124. it('queueJob inside postFlushCb', async () => {
  125. const calls: string[] = []
  126. const job1 = () => {
  127. calls.push('job1')
  128. }
  129. const cb1 = () => {
  130. // queueJob in postFlushCb
  131. calls.push('cb1')
  132. queueJob(job1)
  133. }
  134. queuePostFlushCb(cb1)
  135. await nextTick()
  136. expect(calls).toEqual(['cb1', 'job1'])
  137. })
  138. it('queueJob & postFlushCb inside postFlushCb', async () => {
  139. const calls: string[] = []
  140. const job1 = () => {
  141. calls.push('job1')
  142. }
  143. const cb1 = () => {
  144. calls.push('cb1')
  145. queuePostFlushCb(cb2)
  146. // job1 will executed before cb2
  147. // Job has higher priority than postFlushCb
  148. queueJob(job1)
  149. }
  150. const cb2 = () => {
  151. calls.push('cb2')
  152. }
  153. queuePostFlushCb(cb1)
  154. await nextTick()
  155. expect(calls).toEqual(['cb1', 'job1', 'cb2'])
  156. })
  157. it('postFlushCb inside queueJob', async () => {
  158. const calls: string[] = []
  159. const job1 = () => {
  160. calls.push('job1')
  161. // postFlushCb in queueJob
  162. queuePostFlushCb(cb1)
  163. }
  164. const cb1 = () => {
  165. calls.push('cb1')
  166. }
  167. queueJob(job1)
  168. await nextTick()
  169. expect(calls).toEqual(['job1', 'cb1'])
  170. })
  171. it('queueJob & postFlushCb inside queueJob', async () => {
  172. const calls: string[] = []
  173. const job1 = () => {
  174. calls.push('job1')
  175. // cb1 will executed after job2
  176. // Job has higher priority than postFlushCb
  177. queuePostFlushCb(cb1)
  178. queueJob(job2)
  179. }
  180. const job2 = () => {
  181. calls.push('job2')
  182. }
  183. const cb1 = () => {
  184. calls.push('cb1')
  185. }
  186. queueJob(job1)
  187. await nextTick()
  188. expect(calls).toEqual(['job1', 'job2', 'cb1'])
  189. })
  190. it('nested queueJob w/ postFlushCb', async () => {
  191. const calls: string[] = []
  192. const job1 = () => {
  193. calls.push('job1')
  194. queuePostFlushCb(cb1)
  195. queueJob(job2)
  196. }
  197. const job2 = () => {
  198. calls.push('job2')
  199. queuePostFlushCb(cb2)
  200. }
  201. const cb1 = () => {
  202. calls.push('cb1')
  203. }
  204. const cb2 = () => {
  205. calls.push('cb2')
  206. }
  207. queueJob(job1)
  208. await nextTick()
  209. expect(calls).toEqual(['job1', 'job2', 'cb1', 'cb2'])
  210. })
  211. })
  212. test('invalidateJob', async () => {
  213. const calls: string[] = []
  214. const job1 = () => {
  215. calls.push('job1')
  216. invalidateJob(job2)
  217. job2()
  218. }
  219. const job2 = () => {
  220. calls.push('job2')
  221. }
  222. const job3 = () => {
  223. calls.push('job3')
  224. }
  225. const job4 = () => {
  226. calls.push('job4')
  227. }
  228. // queue all jobs
  229. queueJob(job1)
  230. queueJob(job2)
  231. queueJob(job3)
  232. queuePostFlushCb(job4)
  233. expect(calls).toEqual([])
  234. await nextTick()
  235. // job2 should be called only once
  236. expect(calls).toEqual(['job1', 'job2', 'job3', 'job4'])
  237. })
  238. })