if.spec.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. import Vue from 'vue'
  2. describe('Directive v-if', () => {
  3. it('should check if value is truthy', () => {
  4. const vm = new Vue({
  5. template: '<div><span v-if="foo">hello</span></div>',
  6. data: { foo: true }
  7. }).$mount()
  8. expect(vm.$el.innerHTML).toBe('<span>hello</span>')
  9. })
  10. it('should check if value is falsy', () => {
  11. const vm = new Vue({
  12. template: '<div><span v-if="foo">hello</span></div>',
  13. data: { foo: false }
  14. }).$mount()
  15. expect(vm.$el.innerHTML).toBe('<!---->')
  16. })
  17. it('should update if value changed', done => {
  18. const vm = new Vue({
  19. template: '<div><span v-if="foo">hello</span></div>',
  20. data: { foo: true }
  21. }).$mount()
  22. expect(vm.$el.innerHTML).toBe('<span>hello</span>')
  23. vm.foo = false
  24. waitForUpdate(() => {
  25. expect(vm.$el.innerHTML).toBe('<!---->')
  26. vm.foo = {}
  27. }).then(() => {
  28. expect(vm.$el.innerHTML).toBe('<span>hello</span>')
  29. vm.foo = 0
  30. }).then(() => {
  31. expect(vm.$el.innerHTML).toBe('<!---->')
  32. vm.foo = []
  33. }).then(() => {
  34. expect(vm.$el.innerHTML).toBe('<span>hello</span>')
  35. vm.foo = null
  36. }).then(() => {
  37. expect(vm.$el.innerHTML).toBe('<!---->')
  38. vm.foo = '0'
  39. }).then(() => {
  40. expect(vm.$el.innerHTML).toBe('<span>hello</span>')
  41. vm.foo = undefined
  42. }).then(() => {
  43. expect(vm.$el.innerHTML).toBe('<!---->')
  44. vm.foo = 1
  45. }).then(() => {
  46. expect(vm.$el.innerHTML).toBe('<span>hello</span>')
  47. }).then(done)
  48. })
  49. it('should work well with v-else', done => {
  50. const vm = new Vue({
  51. template: `
  52. <div>
  53. <span v-if="foo">hello</span>
  54. <span v-else>bye</span>
  55. </div>
  56. `,
  57. data: { foo: true }
  58. }).$mount()
  59. expect(vm.$el.innerHTML.trim()).toBe('<span>hello</span>')
  60. vm.foo = false
  61. waitForUpdate(() => {
  62. expect(vm.$el.innerHTML.trim()).toBe('<span>bye</span>')
  63. vm.foo = {}
  64. }).then(() => {
  65. expect(vm.$el.innerHTML.trim()).toBe('<span>hello</span>')
  66. vm.foo = 0
  67. }).then(() => {
  68. expect(vm.$el.innerHTML.trim()).toBe('<span>bye</span>')
  69. vm.foo = []
  70. }).then(() => {
  71. expect(vm.$el.innerHTML.trim()).toBe('<span>hello</span>')
  72. vm.foo = null
  73. }).then(() => {
  74. expect(vm.$el.innerHTML.trim()).toBe('<span>bye</span>')
  75. vm.foo = '0'
  76. }).then(() => {
  77. expect(vm.$el.innerHTML.trim()).toBe('<span>hello</span>')
  78. vm.foo = undefined
  79. }).then(() => {
  80. expect(vm.$el.innerHTML.trim()).toBe('<span>bye</span>')
  81. vm.foo = 1
  82. }).then(() => {
  83. expect(vm.$el.innerHTML.trim()).toBe('<span>hello</span>')
  84. }).then(done)
  85. })
  86. it('should work well with v-else-if', done => {
  87. const vm = new Vue({
  88. template: `
  89. <div>
  90. <span v-if="foo">hello</span>
  91. <span v-else-if="bar">elseif</span>
  92. <span v-else>bye</span>
  93. </div>
  94. `,
  95. data: { foo: true, bar: false }
  96. }).$mount()
  97. expect(vm.$el.innerHTML.trim()).toBe('<span>hello</span>')
  98. vm.foo = false
  99. waitForUpdate(() => {
  100. expect(vm.$el.innerHTML.trim()).toBe('<span>bye</span>')
  101. vm.bar = true
  102. }).then(() => {
  103. expect(vm.$el.innerHTML.trim()).toBe('<span>elseif</span>')
  104. vm.bar = false
  105. }).then(() => {
  106. expect(vm.$el.innerHTML.trim()).toBe('<span>bye</span>')
  107. vm.foo = true
  108. }).then(() => {
  109. expect(vm.$el.innerHTML.trim()).toBe('<span>hello</span>')
  110. vm.foo = false
  111. vm.bar = {}
  112. }).then(() => {
  113. expect(vm.$el.innerHTML.trim()).toBe('<span>elseif</span>')
  114. vm.bar = 0
  115. }).then(() => {
  116. expect(vm.$el.innerHTML.trim()).toBe('<span>bye</span>')
  117. vm.bar = []
  118. }).then(() => {
  119. expect(vm.$el.innerHTML.trim()).toBe('<span>elseif</span>')
  120. vm.bar = null
  121. }).then(() => {
  122. expect(vm.$el.innerHTML.trim()).toBe('<span>bye</span>')
  123. vm.bar = '0'
  124. }).then(() => {
  125. expect(vm.$el.innerHTML.trim()).toBe('<span>elseif</span>')
  126. vm.bar = undefined
  127. }).then(() => {
  128. expect(vm.$el.innerHTML.trim()).toBe('<span>bye</span>')
  129. vm.bar = 1
  130. }).then(() => {
  131. expect(vm.$el.innerHTML.trim()).toBe('<span>elseif</span>')
  132. }).then(done)
  133. })
  134. it('should work well with v-for', done => {
  135. const vm = new Vue({
  136. template: `
  137. <div>
  138. <span v-for="item,i in list" v-if="item.value">{{i}}</span>
  139. </div>
  140. `,
  141. data: {
  142. list: [
  143. { value: true },
  144. { value: false },
  145. { value: true }
  146. ]
  147. }
  148. }).$mount()
  149. expect(vm.$el.innerHTML).toBe('<span>0</span><!----><span>2</span>')
  150. vm.list[0].value = false
  151. waitForUpdate(() => {
  152. expect(vm.$el.innerHTML).toBe('<!----><!----><span>2</span>')
  153. vm.list.push({ value: true })
  154. }).then(() => {
  155. expect(vm.$el.innerHTML).toBe('<!----><!----><span>2</span><span>3</span>')
  156. vm.list.splice(1, 2)
  157. }).then(() => {
  158. expect(vm.$el.innerHTML).toBe('<!----><span>1</span>')
  159. }).then(done)
  160. })
  161. it('should work well with v-for and v-else', done => {
  162. const vm = new Vue({
  163. template: `
  164. <div>
  165. <span v-for="item,i in list" v-if="item.value">hello</span>
  166. <span v-else>bye</span>
  167. </div>
  168. `,
  169. data: {
  170. list: [
  171. { value: true },
  172. { value: false },
  173. { value: true }
  174. ]
  175. }
  176. }).$mount()
  177. expect(vm.$el.innerHTML.trim()).toBe('<span>hello</span><span>bye</span><span>hello</span>')
  178. vm.list[0].value = false
  179. waitForUpdate(() => {
  180. expect(vm.$el.innerHTML.trim()).toBe('<span>bye</span><span>bye</span><span>hello</span>')
  181. vm.list.push({ value: true })
  182. }).then(() => {
  183. expect(vm.$el.innerHTML.trim()).toBe('<span>bye</span><span>bye</span><span>hello</span><span>hello</span>')
  184. vm.list.splice(1, 2)
  185. }).then(() => {
  186. expect(vm.$el.innerHTML.trim()).toBe('<span>bye</span><span>hello</span>')
  187. }).then(done)
  188. })
  189. it('should work properly on component root', done => {
  190. const vm = new Vue({
  191. template: `
  192. <div>
  193. <test class="test"></test>
  194. </div>
  195. `,
  196. components: {
  197. test: {
  198. data () {
  199. return { ok: true }
  200. },
  201. template: '<div v-if="ok" id="ok" class="inner">test</div>'
  202. }
  203. }
  204. }).$mount()
  205. expect(vm.$el.children[0].id).toBe('ok')
  206. expect(vm.$el.children[0].className).toBe('inner test')
  207. vm.$children[0].ok = false
  208. waitForUpdate(() => {
  209. // attrs / class modules should not attempt to patch the comment node
  210. expect(vm.$el.innerHTML).toBe('<!---->')
  211. vm.$children[0].ok = true
  212. }).then(() => {
  213. expect(vm.$el.children[0].id).toBe('ok')
  214. expect(vm.$el.children[0].className).toBe('inner test')
  215. }).then(done)
  216. })
  217. it('should maintain stable list to avoid unnecessary patches', done => {
  218. const created = jasmine.createSpy()
  219. const destroyed = jasmine.createSpy()
  220. const vm = new Vue({
  221. data: {
  222. ok: true
  223. },
  224. // when the first div is toggled, the second div should be reused
  225. // instead of re-created/destroyed
  226. template: `
  227. <div>
  228. <div v-if="ok"></div>
  229. <div><test></test></div>
  230. </div>
  231. `,
  232. components: {
  233. test: {
  234. template: '<div></div>',
  235. created,
  236. destroyed
  237. }
  238. }
  239. }).$mount()
  240. expect(created.calls.count()).toBe(1)
  241. vm.ok = false
  242. waitForUpdate(() => {
  243. expect(created.calls.count()).toBe(1)
  244. expect(destroyed).not.toHaveBeenCalled()
  245. }).then(done)
  246. })
  247. })