if_spec.js 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. var _ = require('../../../../src/util')
  2. var Vue = require('../../../../src/vue')
  3. if (_.inBrowser) {
  4. describe('v-if', function () {
  5. var el
  6. beforeEach(function () {
  7. el = document.createElement('div')
  8. spyOn(_, 'warn')
  9. })
  10. it('normal', function (done) {
  11. var vm = new Vue({
  12. el: el,
  13. data: { test: false, a: 'A' },
  14. template: '<div v-if="test"><test></test></div>',
  15. components: {
  16. test: {
  17. inherit: true,
  18. template: '{{a}}'
  19. }
  20. }
  21. })
  22. // lazy instantitation
  23. expect(el.innerHTML).toBe('')
  24. expect(vm._children.length).toBe(0)
  25. vm.test = true
  26. _.nextTick(function () {
  27. expect(el.innerHTML).toBe('<div><test>A</test></div>')
  28. expect(vm._children.length).toBe(1)
  29. vm.test = false
  30. _.nextTick(function () {
  31. expect(el.innerHTML).toBe('')
  32. expect(vm._children.length).toBe(0)
  33. vm.test = true
  34. _.nextTick(function () {
  35. expect(el.innerHTML).toBe('<div><test>A</test></div>')
  36. expect(vm._children.length).toBe(1)
  37. var child = vm._children[0]
  38. vm.$destroy()
  39. expect(child._isDestroyed).toBe(true)
  40. done()
  41. })
  42. })
  43. })
  44. })
  45. it('template block', function (done) {
  46. var vm = new Vue({
  47. el: el,
  48. data: { test: false, a: 'A', b: 'B' },
  49. template: '<template v-if="test"><p>{{a}}</p><p>{{b}}</p></template>'
  50. })
  51. // lazy instantitation
  52. expect(el.innerHTML).toBe('')
  53. vm.test = true
  54. _.nextTick(function () {
  55. expect(el.innerHTML).toBe('<p>A</p><p>B</p>')
  56. vm.test = false
  57. _.nextTick(function () {
  58. expect(el.innerHTML).toBe('')
  59. done()
  60. })
  61. })
  62. })
  63. it('v-if + v-component', function (done) {
  64. var attachSpy = jasmine.createSpy()
  65. var detachSpy = jasmine.createSpy()
  66. var readySpy = jasmine.createSpy()
  67. var vm = new Vue({
  68. el: el,
  69. data: { ok: false },
  70. template: '<test v-if="ok"></test>',
  71. components: {
  72. test: {
  73. data: function () {
  74. return { a: 123 }
  75. },
  76. template: '{{a}}',
  77. ready: readySpy,
  78. attached: attachSpy,
  79. detached: detachSpy
  80. }
  81. }
  82. })
  83. vm.$appendTo(document.body)
  84. expect(el.innerHTML).toBe('')
  85. expect(vm._children.length).toBe(0)
  86. vm.ok = true
  87. _.nextTick(function () {
  88. expect(el.innerHTML).toBe('<test>123</test>')
  89. expect(vm._children.length).toBe(1)
  90. expect(attachSpy).toHaveBeenCalled()
  91. expect(readySpy).toHaveBeenCalled()
  92. vm.ok = false
  93. _.nextTick(function () {
  94. expect(detachSpy).toHaveBeenCalled()
  95. expect(el.innerHTML).toBe('')
  96. expect(vm._children.length).toBe(0)
  97. vm.$remove()
  98. done()
  99. })
  100. })
  101. })
  102. it('v-if + dynamic component', function (done) {
  103. var vm = new Vue({
  104. el: el,
  105. data: {
  106. ok: false,
  107. view: 'a'
  108. },
  109. template: '<component is="{{view}}" v-if="ok"></component>',
  110. components: {
  111. a: {
  112. template: 'AAA'
  113. },
  114. b: {
  115. template: 'BBB'
  116. }
  117. }
  118. })
  119. expect(el.innerHTML).toBe('')
  120. expect(vm._children.length).toBe(0)
  121. // toggle if with lazy instantiation
  122. vm.ok = true
  123. _.nextTick(function () {
  124. expect(el.innerHTML).toBe('<component>AAA</component>')
  125. expect(vm._children.length).toBe(1)
  126. // switch view when if=true
  127. vm.view = 'b'
  128. _.nextTick(function () {
  129. expect(el.innerHTML).toBe('<component>BBB</component>')
  130. expect(vm._children.length).toBe(1)
  131. // toggle if when already instantiated
  132. vm.ok = false
  133. _.nextTick(function () {
  134. expect(el.innerHTML).toBe('')
  135. expect(vm._children.length).toBe(0)
  136. // toggle if and switch view at the same time
  137. vm.view = 'a'
  138. vm.ok = true
  139. _.nextTick(function () {
  140. expect(el.innerHTML).toBe('<component>AAA</component>')
  141. expect(vm._children.length).toBe(1)
  142. done()
  143. })
  144. })
  145. })
  146. })
  147. })
  148. it('v-if with different truthy values', function (done) {
  149. var vm = new Vue({
  150. el: el,
  151. data: {
  152. a: 1
  153. },
  154. template: '<div v-if="a">{{a}}</div>'
  155. })
  156. expect(el.innerHTML).toBe('<div>1</div>')
  157. vm.a = 2
  158. _.nextTick(function () {
  159. expect(el.innerHTML).toBe('<div>2</div>')
  160. done()
  161. })
  162. })
  163. it('invalid warn', function () {
  164. el.setAttribute('v-if', 'test')
  165. var vm = new Vue({
  166. el: el
  167. })
  168. expect(hasWarned(_, 'already mounted instance')).toBe(true)
  169. })
  170. it('v-if with content transclusion', function (done) {
  171. var vm = new Vue({
  172. el: el,
  173. data: {
  174. a: 1,
  175. show: true
  176. },
  177. template: '<test show="{{show}}">{{a}}</test>',
  178. components: {
  179. test: {
  180. props: ['show'],
  181. template: '<div v-if="show"><content></cotent></div>'
  182. }
  183. }
  184. })
  185. expect(el.textContent).toBe('1')
  186. vm.a = 2
  187. _.nextTick(function () {
  188. expect(el.textContent).toBe('2')
  189. vm.show = false
  190. _.nextTick(function () {
  191. expect(el.textContent).toBe('')
  192. vm.show = true
  193. vm.a = 3
  194. _.nextTick(function () {
  195. expect(el.textContent).toBe('3')
  196. done()
  197. })
  198. })
  199. })
  200. })
  201. it('call attach/detach for transcluded components', function (done) {
  202. document.body.appendChild(el)
  203. var attachSpy = jasmine.createSpy('attached')
  204. var detachSpy = jasmine.createSpy('detached')
  205. var vm = new Vue({
  206. el: el,
  207. data: { show: true },
  208. template: '<outer><transcluded></transcluded></outer>',
  209. components: {
  210. outer: {
  211. template: '<div v-if="$parent.show"><content></content></div>'
  212. },
  213. transcluded: {
  214. template: 'transcluded',
  215. attached: attachSpy,
  216. detached: detachSpy
  217. }
  218. }
  219. })
  220. expect(attachSpy).toHaveBeenCalled()
  221. vm.show = false
  222. _.nextTick(function () {
  223. expect(detachSpy).toHaveBeenCalled()
  224. document.body.removeChild(el)
  225. done()
  226. })
  227. })
  228. it('call attach/detach for dynamicly created components inside if block', function (done) {
  229. document.body.appendChild(el)
  230. var attachSpy = jasmine.createSpy('attached')
  231. var detachSpy = jasmine.createSpy('detached')
  232. var vm = new Vue({
  233. el: el,
  234. data: {
  235. show: true,
  236. list: [{a:0}]
  237. },
  238. template:
  239. '<outer>' +
  240. '<div>' + // an extra layer to test components deep inside the tree
  241. '<transcluded v-repeat="list"></transcluded>' +
  242. '</div>' +
  243. '</outer>',
  244. components: {
  245. outer: {
  246. template:
  247. '<div v-if="$parent.show">' +
  248. '<content></content>' +
  249. '</div>' +
  250. // this is to test that compnents that are not in the if block
  251. // should not fire attach/detach when v-if toggles
  252. '<transcluded></transcluded>'
  253. },
  254. transcluded: {
  255. template: '{{a}}',
  256. attached: attachSpy,
  257. detached: detachSpy
  258. }
  259. }
  260. })
  261. assertMarkup()
  262. expect(attachSpy.calls.count()).toBe(2)
  263. vm.show = false
  264. _.nextTick(function () {
  265. assertMarkup()
  266. expect(detachSpy.calls.count()).toBe(1)
  267. vm.list.push({a:1})
  268. vm.show = true
  269. _.nextTick(function () {
  270. assertMarkup()
  271. expect(attachSpy.calls.count()).toBe(2 + 2)
  272. vm.list.push({a:2})
  273. vm.show = false
  274. _.nextTick(function () {
  275. assertMarkup()
  276. expect(attachSpy.calls.count()).toBe(2 + 2 + 1)
  277. expect(detachSpy.calls.count()).toBe(1 + 3)
  278. document.body.removeChild(el)
  279. done()
  280. })
  281. })
  282. })
  283. function assertMarkup () {
  284. var showBlock = vm.show
  285. ? '<div><div>' +
  286. vm.list.map(function (o) {
  287. return '<transcluded>' + o.a + '</transcluded>'
  288. }).join('') +
  289. '</div></div>'
  290. : ''
  291. var markup =
  292. '<outer>' +
  293. showBlock +
  294. '<transcluded></transcluded>' +
  295. '</outer>'
  296. expect(el.innerHTML).toBe(markup)
  297. }
  298. })
  299. })
  300. }