misc_spec.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. // test cases for edge cases & bug fixes
  2. var Vue = require('../../../src/vue')
  3. // spies on different objects
  4. var _ = require('../../../src/util/debug')
  5. var __ = Vue.util
  6. describe('Misc', function () {
  7. beforeEach(function () {
  8. spyOn(_, 'warn')
  9. spyOn(__, 'warn')
  10. })
  11. it('should handle directive.bind() altering its childNode structure', function () {
  12. var vm = new Vue({
  13. el: document.createElement('div'),
  14. template: '<div v-test>{{test}}</div>',
  15. data: {
  16. test: 'hi'
  17. },
  18. directives: {
  19. test: {
  20. bind: function () {
  21. this.el.insertBefore(document.createTextNode('yo '),
  22. this.el.firstChild)
  23. }
  24. }
  25. }
  26. })
  27. expect(vm.$el.textContent).toBe('yo hi')
  28. })
  29. it('attached/detached hooks for transcluded components', function () {
  30. var spy1 = jasmine.createSpy('attached')
  31. var spy2 = jasmine.createSpy('detached')
  32. var el = document.createElement('div')
  33. el.innerHTML = '<outer v-ref:outter><inner></inner></outer>'
  34. document.body.appendChild(el)
  35. var vm = new Vue({
  36. el: el,
  37. components: {
  38. outer: {
  39. template: '<slot></slot>'
  40. },
  41. inner: {
  42. template: 'hi',
  43. attached: spy1,
  44. detached: spy2
  45. }
  46. }
  47. })
  48. expect(spy1).toHaveBeenCalled()
  49. vm.$refs.outter.$remove()
  50. expect(spy2).toHaveBeenCalled()
  51. })
  52. it('v-for on component root node with replace:true', function () {
  53. var el = document.createElement('div')
  54. var vm = new Vue({
  55. el: el,
  56. template: '<test></test>',
  57. components: {
  58. test: {
  59. data: function () {
  60. return { list: [1, 2, 3] }
  61. },
  62. template: '<div v-for="n in list">{{n}}</div>',
  63. replace: true
  64. }
  65. }
  66. })
  67. expect(vm.$el.innerHTML).toBe('<div>1</div><div>2</div><div>3</div>')
  68. })
  69. // #922
  70. it('template v-for inside svg', function () {
  71. var el = document.createElement('div')
  72. new Vue({
  73. el: el,
  74. template: '<svg><template v-for="n in list"><text>{{n}}</text></template></svg>',
  75. data: {
  76. list: [1, 2, 3]
  77. }
  78. })
  79. // IE inlines svg namespace
  80. var xmlns = /\s?xmlns=".*svg"/
  81. expect(el.innerHTML.replace(xmlns, '')).toBe('<svg><text>1</text><text>2</text><text>3</text></svg>')
  82. })
  83. // #1005
  84. it('call lifecycle hooks for child components', function () {
  85. Vue.options.replace = true
  86. var el = document.createElement('div')
  87. var logs = []
  88. function log (n) {
  89. return function () {
  90. logs.push(n)
  91. }
  92. }
  93. document.body.appendChild(el)
  94. var vm = new Vue({
  95. el: el,
  96. attached: log(0),
  97. ready: log(1),
  98. detached: log(2),
  99. beforeDestroy: log(3),
  100. destroyed: log(4),
  101. template: '<div><test></test><test></test></div>',
  102. components: {
  103. test: {
  104. template: '<span>hi</span>',
  105. attached: log(5),
  106. ready: log(6),
  107. detached: log(7),
  108. beforeDestroy: log(8),
  109. destroyed: log(9)
  110. }
  111. }
  112. })
  113. expect(vm.$el.innerHTML).toBe('<span>hi</span><span>hi</span>')
  114. expect(logs.join()).toBe('0,5,6,5,6,1')
  115. logs = []
  116. vm.$destroy(true)
  117. expect(logs.join()).toBe('3,8,9,8,9,2,7,7,4')
  118. Vue.options.replace = false
  119. })
  120. // #1006
  121. it('destroyed hook for components inside v-if', function (done) {
  122. var spy = jasmine.createSpy('v-if destroyed hook')
  123. var vm = new Vue({
  124. el: document.createElement('div'),
  125. template: '<template v-if="ok"><test></test></template>',
  126. data: {
  127. ok: true
  128. },
  129. components: {
  130. test: {
  131. destroyed: spy
  132. }
  133. }
  134. })
  135. vm.ok = false
  136. Vue.nextTick(function () {
  137. expect(spy).toHaveBeenCalled()
  138. done()
  139. })
  140. })
  141. it('frozen model, root', function (done) {
  142. var vm = new Vue({
  143. el: document.createElement('div'),
  144. template: '{{msg}}',
  145. data: Object.freeze({
  146. msg: 'hi!'
  147. })
  148. })
  149. expect(vm.$el.textContent).toBe('hi!')
  150. vm.msg = 'ho!'
  151. Vue.nextTick(function () {
  152. expect(vm.$el.textContent).toBe('hi!')
  153. done()
  154. })
  155. })
  156. it('frozen model, non-root', function (done) {
  157. var vm = new Vue({
  158. el: document.createElement('div'),
  159. template: '{{msg}} {{frozen.msg}}',
  160. data: {
  161. msg: 'hi',
  162. frozen: Object.freeze({
  163. msg: 'frozen'
  164. })
  165. }
  166. })
  167. expect(vm.$el.textContent).toBe('hi frozen')
  168. vm.msg = 'ho'
  169. vm.frozen.msg = 'changed'
  170. Vue.nextTick(function () {
  171. expect(vm.$el.textContent).toBe('ho frozen')
  172. done()
  173. })
  174. })
  175. it('should not trigger deep/Array watchers when digesting', function (done) {
  176. var spy1 = jasmine.createSpy('deep')
  177. var spy2 = jasmine.createSpy('Array')
  178. var spy3 = jasmine.createSpy('test')
  179. var spy4 = jasmine.createSpy('deep-mutated')
  180. var vm = new Vue({
  181. el: document.createElement('div'),
  182. data: {
  183. obj: {},
  184. arr: [],
  185. obj2: {}
  186. },
  187. watch: {
  188. obj: {
  189. handler: spy1,
  190. deep: true
  191. },
  192. arr: spy2,
  193. // if the watcher is watching the added value,
  194. // it should still trigger properly
  195. test: {
  196. handler: spy3,
  197. deep: true
  198. },
  199. // if the object is in fact mutated, it should
  200. // still trigger.
  201. obj2: {
  202. handler: spy4,
  203. deep: true
  204. }
  205. }
  206. })
  207. var test = []
  208. var obj2 = vm.obj2
  209. vm.$set('test', test)
  210. obj2.$set('test', 123)
  211. Vue.nextTick(function () {
  212. expect(spy1).not.toHaveBeenCalled()
  213. expect(spy2).not.toHaveBeenCalled()
  214. expect(spy3).toHaveBeenCalledWith(test, undefined)
  215. expect(spy4).toHaveBeenCalledWith(obj2, obj2)
  216. done()
  217. })
  218. })
  219. it('handle interpolated textarea', function (done) {
  220. var el = document.createElement('div')
  221. el.innerHTML = '<textarea>hello {{msg}}</textarea>'
  222. var vm = new Vue({
  223. el: el,
  224. data: {
  225. msg: 'test'
  226. }
  227. })
  228. expect(el.innerHTML).toBe('<textarea>hello test</textarea>')
  229. vm.msg = 'world'
  230. Vue.nextTick(function () {
  231. expect(el.innerHTML).toBe('<textarea>hello world</textarea>')
  232. done()
  233. })
  234. })
  235. it('nested object $set should trigger parent array notify', function (done) {
  236. var vm = new Vue({
  237. el: document.createElement('div'),
  238. template: '{{items | json}}{{items[0].a}}',
  239. data: {
  240. items: [{}]
  241. }
  242. })
  243. expect(vm.$el.textContent).toBe(JSON.stringify(vm.items, null, 2))
  244. vm.items[0].$set('a', 123)
  245. Vue.nextTick(function () {
  246. expect(vm.$el.textContent).toBe(JSON.stringify(vm.items, null, 2) + '123')
  247. done()
  248. })
  249. })
  250. it('warn unkown custom element', function () {
  251. new Vue({
  252. el: document.createElement('div'),
  253. template: '<custom-stuff></custom-stuff>'
  254. })
  255. expect(hasWarned(__, 'Unknown custom element')).toBe(true)
  256. })
  257. })