if_spec.js 9.1 KB

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