methods-lifecycle.spec.ts 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. import Vue from 'vue'
  2. import Dep from 'core/observer/dep'
  3. describe('Instance methods lifecycle', () => {
  4. describe('$mount', () => {
  5. it('empty mount', () => {
  6. const vm = new Vue({
  7. data: { msg: 'hi' },
  8. template: '<div>{{ msg }}</div>'
  9. }).$mount()
  10. expect(vm.$el.tagName).toBe('DIV')
  11. expect(vm.$el.textContent).toBe('hi')
  12. })
  13. it('mount to existing element', () => {
  14. const el = document.createElement('div')
  15. el.innerHTML = '{{ msg }}'
  16. const vm = new Vue({
  17. data: { msg: 'hi' }
  18. }).$mount(el)
  19. expect(vm.$el.tagName).toBe('DIV')
  20. expect(vm.$el.textContent).toBe('hi')
  21. })
  22. it('mount to id', () => {
  23. const el = document.createElement('div')
  24. el.id = 'mount-test'
  25. el.innerHTML = '{{ msg }}'
  26. document.body.appendChild(el)
  27. const vm = new Vue({
  28. data: { msg: 'hi' }
  29. }).$mount('#mount-test')
  30. expect(vm.$el.tagName).toBe('DIV')
  31. expect(vm.$el.textContent).toBe('hi')
  32. })
  33. it('Dep.target should be undefined in lifecycle', () => {
  34. new Vue({
  35. template: '<div><my-component></my-component></div>',
  36. components: {
  37. myComponent: {
  38. template: '<div>hi</div>',
  39. mounted() {
  40. this.msg
  41. expect(Dep.target).toBe(undefined)
  42. },
  43. computed: {
  44. msg() {
  45. return 1
  46. }
  47. }
  48. }
  49. }
  50. }).$mount()
  51. })
  52. it('Dep.target should be undefined during invocation of child immediate watcher', done => {
  53. let calls = 0
  54. const childData = { a: 1 }
  55. const parentUpdate = vi.fn()
  56. new Vue({
  57. template: '<div><my-component></my-component></div>',
  58. updated: parentUpdate,
  59. components: {
  60. myComponent: {
  61. template: '<div>{{ a }}</div>',
  62. data() {
  63. return childData
  64. },
  65. watch: {
  66. anything: {
  67. handler() {
  68. ++calls
  69. this.a
  70. },
  71. immediate: true
  72. }
  73. }
  74. }
  75. }
  76. }).$mount()
  77. expect(calls).toBe(1)
  78. childData.a++
  79. waitForUpdate(() => {
  80. expect(parentUpdate).not.toHaveBeenCalled()
  81. }).then(done)
  82. })
  83. })
  84. describe('$destroy', () => {
  85. it('remove self from parent', () => {
  86. const vm = new Vue({
  87. template: '<test></test>',
  88. components: {
  89. test: { template: '<div></div>' }
  90. }
  91. }).$mount()
  92. vm.$children[0].$destroy()
  93. expect(vm.$children.length).toBe(0)
  94. })
  95. it('teardown watchers', () => {
  96. const vm = new Vue({
  97. data: { a: 123 },
  98. template: '<div></div>'
  99. }).$mount()
  100. vm.$watch('a', () => {})
  101. vm.$destroy()
  102. expect(vm._watcher.active).toBe(false)
  103. expect(vm._scope.effects.every(w => !w.active)).toBe(true)
  104. })
  105. it('remove self from data observer', () => {
  106. const vm = new Vue({ data: { a: 1 } })
  107. vm.$destroy()
  108. expect(vm.$data.__ob__.vmCount).toBe(0)
  109. })
  110. it('avoid duplicate calls', () => {
  111. const spy = vi.fn()
  112. const vm = new Vue({
  113. beforeDestroy: spy
  114. })
  115. vm.$destroy()
  116. vm.$destroy()
  117. expect(spy.mock.calls.length).toBe(1)
  118. })
  119. })
  120. describe('$forceUpdate', () => {
  121. it('should force update', done => {
  122. const vm = new Vue({
  123. data: {
  124. a: {}
  125. },
  126. template: '<div>{{ a.b }}</div>'
  127. }).$mount()
  128. expect(vm.$el.textContent).toBe('')
  129. vm.a.b = 'foo'
  130. waitForUpdate(() => {
  131. // should not work because adding new property
  132. expect(vm.$el.textContent).toBe('')
  133. vm.$forceUpdate()
  134. })
  135. .then(() => {
  136. expect(vm.$el.textContent).toBe('foo')
  137. })
  138. .then(done)
  139. })
  140. })
  141. describe('$nextTick', () => {
  142. it('should be called after DOM update in correct context', done => {
  143. const vm = new Vue({
  144. template: '<div>{{ msg }}</div>',
  145. data: {
  146. msg: 'foo'
  147. }
  148. }).$mount()
  149. vm.msg = 'bar'
  150. vm.$nextTick(function () {
  151. expect(this).toBe(vm)
  152. expect(vm.$el.textContent).toBe('bar')
  153. done()
  154. })
  155. })
  156. if (typeof Promise !== 'undefined') {
  157. it('should be called after DOM update in correct context, when using Promise syntax', done => {
  158. const vm = new Vue({
  159. template: '<div>{{ msg }}</div>',
  160. data: {
  161. msg: 'foo'
  162. }
  163. }).$mount()
  164. vm.msg = 'bar'
  165. vm.$nextTick().then(ctx => {
  166. expect(ctx).toBe(vm)
  167. expect(vm.$el.textContent).toBe('bar')
  168. done()
  169. })
  170. })
  171. }
  172. })
  173. })