if.spec.js 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  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 with v-for on v-else branch', done => {
  190. const vm = new Vue({
  191. template: `
  192. <div>
  193. <span v-if="false">hello</span>
  194. <span v-else v-for="item in list">{{ item }}</span>
  195. </div>
  196. `,
  197. data: {
  198. list: [1, 2, 3]
  199. }
  200. }).$mount()
  201. expect(vm.$el.textContent.trim()).toBe('123')
  202. vm.list.reverse()
  203. waitForUpdate(() => {
  204. expect(vm.$el.textContent.trim()).toBe('321')
  205. }).then(done)
  206. })
  207. it('should work properly on component root', done => {
  208. const vm = new Vue({
  209. template: `
  210. <div>
  211. <test class="test"></test>
  212. </div>
  213. `,
  214. components: {
  215. test: {
  216. data () {
  217. return { ok: true }
  218. },
  219. template: '<div v-if="ok" id="ok" class="inner">test</div>'
  220. }
  221. }
  222. }).$mount()
  223. expect(vm.$el.children[0].id).toBe('ok')
  224. expect(vm.$el.children[0].className).toBe('inner test')
  225. vm.$children[0].ok = false
  226. waitForUpdate(() => {
  227. // attrs / class modules should not attempt to patch the comment node
  228. expect(vm.$el.innerHTML).toBe('<!---->')
  229. vm.$children[0].ok = true
  230. }).then(() => {
  231. expect(vm.$el.children[0].id).toBe('ok')
  232. expect(vm.$el.children[0].className).toBe('inner test')
  233. }).then(done)
  234. })
  235. it('should maintain stable list to avoid unnecessary patches', done => {
  236. const created = jasmine.createSpy()
  237. const destroyed = jasmine.createSpy()
  238. const vm = new Vue({
  239. data: {
  240. ok: true
  241. },
  242. // when the first div is toggled, the second div should be reused
  243. // instead of re-created/destroyed
  244. template: `
  245. <div>
  246. <div v-if="ok"></div>
  247. <div><test></test></div>
  248. </div>
  249. `,
  250. components: {
  251. test: {
  252. template: '<div></div>',
  253. created,
  254. destroyed
  255. }
  256. }
  257. }).$mount()
  258. expect(created.calls.count()).toBe(1)
  259. vm.ok = false
  260. waitForUpdate(() => {
  261. expect(created.calls.count()).toBe(1)
  262. expect(destroyed).not.toHaveBeenCalled()
  263. }).then(done)
  264. })
  265. })