scheduler.spec.js 3.7 KB

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