scheduler.spec.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. import Vue from 'vue'
  2. import {
  3. MAX_UPDATE_COUNT,
  4. queueWatcher as _queueWatcher
  5. } from 'core/observer/scheduler'
  6. function queueWatcher (watcher) {
  7. watcher.vm = {} // mock vm
  8. _queueWatcher(watcher)
  9. }
  10. describe('Scheduler', () => {
  11. let spy
  12. beforeEach(() => {
  13. spy = jasmine.createSpy('scheduler')
  14. })
  15. it('queueWatcher', done => {
  16. queueWatcher({
  17. run: spy
  18. })
  19. waitForUpdate(() => {
  20. expect(spy.calls.count()).toBe(1)
  21. }).then(done)
  22. })
  23. it('dedup', done => {
  24. queueWatcher({
  25. id: 1,
  26. run: spy
  27. })
  28. queueWatcher({
  29. id: 1,
  30. run: spy
  31. })
  32. waitForUpdate(() => {
  33. expect(spy.calls.count()).toBe(1)
  34. }).then(done)
  35. })
  36. it('allow duplicate when flushing', done => {
  37. const job = {
  38. id: 1,
  39. run: spy
  40. }
  41. queueWatcher(job)
  42. queueWatcher({
  43. id: 2,
  44. run () { queueWatcher(job) }
  45. })
  46. waitForUpdate(() => {
  47. expect(spy.calls.count()).toBe(2)
  48. }).then(done)
  49. })
  50. it('call user watchers before component re-render', done => {
  51. const calls = []
  52. const vm = new Vue({
  53. data: {
  54. a: 1
  55. },
  56. template: '<div>{{ a }}</div>',
  57. watch: {
  58. a () { calls.push(1) }
  59. },
  60. beforeUpdate () {
  61. calls.push(2)
  62. }
  63. }).$mount()
  64. vm.a = 2
  65. waitForUpdate(() => {
  66. expect(calls).toEqual([1, 2])
  67. }).then(done)
  68. })
  69. it('call user watcher triggered by component re-render immediately', done => {
  70. // this happens when a component re-render updates the props of a child
  71. const calls = []
  72. const vm = new Vue({
  73. data: {
  74. a: 1
  75. },
  76. watch: {
  77. a () {
  78. calls.push(1)
  79. }
  80. },
  81. beforeUpdate () {
  82. calls.push(2)
  83. },
  84. template: '<div><test :a="a"></test></div>',
  85. components: {
  86. test: {
  87. props: ['a'],
  88. template: '<div>{{ a }}</div>',
  89. watch: {
  90. a () {
  91. calls.push(3)
  92. }
  93. },
  94. beforeUpdate () {
  95. calls.push(4)
  96. }
  97. }
  98. }
  99. }).$mount()
  100. vm.a = 2
  101. waitForUpdate(() => {
  102. expect(calls).toEqual([1, 2, 3, 4])
  103. }).then(done)
  104. })
  105. it('warn against infinite update loops', function (done) {
  106. let count = 0
  107. const job = {
  108. id: 1,
  109. run () {
  110. count++
  111. queueWatcher(job)
  112. }
  113. }
  114. queueWatcher(job)
  115. waitForUpdate(() => {
  116. expect(count).toBe(MAX_UPDATE_COUNT + 1)
  117. expect('infinite update loop').toHaveBeenWarned()
  118. }).then(done)
  119. })
  120. it('should call newly pushed watcher after current watcher is done', done => {
  121. const callOrder = []
  122. queueWatcher({
  123. id: 1,
  124. user: true,
  125. run () {
  126. callOrder.push(1)
  127. queueWatcher({
  128. id: 2,
  129. run () {
  130. callOrder.push(3)
  131. }
  132. })
  133. callOrder.push(2)
  134. }
  135. })
  136. waitForUpdate(() => {
  137. expect(callOrder).toEqual([1, 2, 3])
  138. }).then(done)
  139. })
  140. // GitHub issue #5191
  141. it('emit should work when updated hook called', done => {
  142. const el = document.createElement('div')
  143. const vm = new Vue({
  144. template: `<div><child @change="bar" :foo="foo"></child></div>`,
  145. data: {
  146. foo: 0
  147. },
  148. methods: {
  149. bar: spy
  150. },
  151. components: {
  152. child: {
  153. template: `<div>{{foo}}</div>`,
  154. props: ['foo'],
  155. updated () {
  156. this.$emit('change')
  157. }
  158. }
  159. }
  160. }).$mount(el)
  161. vm.$nextTick(() => {
  162. vm.foo = 1
  163. vm.$nextTick(() => {
  164. expect(vm.$el.innerHTML).toBe('<div>1</div>')
  165. expect(spy).toHaveBeenCalled()
  166. done()
  167. })
  168. })
  169. })
  170. })