directive_spec.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. var Vue = require('../../../src/vue')
  2. var Directive = require('../../../src/directive')
  3. var nextTick = Vue.nextTick
  4. describe('Directive', function () {
  5. var el = {} // simply a mock to be able to run in Node
  6. var vm, def
  7. beforeEach(function () {
  8. def = {
  9. bind: jasmine.createSpy('bind'),
  10. update: jasmine.createSpy('update'),
  11. unbind: jasmine.createSpy('unbind')
  12. }
  13. vm = new Vue({
  14. data:{
  15. a:1
  16. },
  17. filters: {
  18. test: function (v) {
  19. return v * 2
  20. }
  21. },
  22. directives: {
  23. test: def
  24. }
  25. })
  26. })
  27. it('normal', function (done) {
  28. var d = new Directive('test', el, vm, {
  29. expression: 'a',
  30. arg: 'someArg',
  31. filters: [{name:'test'}]
  32. }, def)
  33. // properties
  34. expect(d.el).toBe(el)
  35. expect(d.name).toBe('test')
  36. expect(d.vm).toBe(vm)
  37. expect(d.arg).toBe('someArg')
  38. expect(d.expression).toBe('a')
  39. // init calls
  40. expect(def.bind).toHaveBeenCalled()
  41. expect(def.update).toHaveBeenCalledWith(2)
  42. expect(d._bound).toBe(true)
  43. // update
  44. vm.a = 2
  45. nextTick(function () {
  46. expect(def.update).toHaveBeenCalledWith(4, 2)
  47. // teardown
  48. d._teardown()
  49. expect(def.unbind).toHaveBeenCalled()
  50. expect(d._bound).toBe(false)
  51. expect(d._watcher).toBe(null)
  52. done()
  53. })
  54. })
  55. it('static literal', function () {
  56. def.isLiteral = true
  57. var d = new Directive('test', el, vm, {
  58. expression: 'a'
  59. }, def)
  60. expect(d._watcher).toBeUndefined()
  61. expect(d.expression).toBe('a')
  62. expect(d.bind).toHaveBeenCalled()
  63. expect(d.update).not.toHaveBeenCalled()
  64. })
  65. it('static literal, interpolate with no update', function () {
  66. def.isLiteral = true
  67. delete def.update
  68. var d = new Directive('test', el, vm, {
  69. expression: '{{a}}'
  70. }, def)
  71. expect(d._watcher).toBeUndefined()
  72. expect(d.expression).toBe(1)
  73. expect(d.bind).toHaveBeenCalled()
  74. })
  75. it('dynamic literal', function (done) {
  76. vm.a = '' // #468 dynamic literals with falsy initial
  77. // should still create the watcher.
  78. def.isLiteral = true
  79. var d = new Directive('test', el, vm, {
  80. expression: '{{a}}'
  81. }, def)
  82. expect(d._watcher).toBeDefined()
  83. expect(d.expression).toBe('')
  84. expect(def.bind).toHaveBeenCalled()
  85. expect(def.update).toHaveBeenCalledWith('')
  86. vm.a = 'aa'
  87. nextTick(function () {
  88. expect(def.update).toHaveBeenCalledWith('aa', '')
  89. done()
  90. })
  91. })
  92. it('inline statement', function () {
  93. def.acceptStatement = true
  94. var spy = jasmine.createSpy()
  95. vm.$options.filters.test = function (fn) {
  96. spy()
  97. return function () {
  98. // call it twice
  99. fn()
  100. fn()
  101. }
  102. }
  103. var d = new Directive('test', el, vm, {
  104. expression: 'a++',
  105. filters: [{name:'test'}]
  106. }, def)
  107. expect(d._watcher).toBeUndefined()
  108. expect(d.bind).toHaveBeenCalled()
  109. var wrappedFn = d.update.calls.argsFor(0)[0]
  110. expect(typeof wrappedFn).toBe('function')
  111. // test invoke the wrapped fn
  112. wrappedFn()
  113. expect(vm.a).toBe(3)
  114. })
  115. it('two-way', function (done) {
  116. def.twoWay = true
  117. vm.$options.filters.test = {
  118. write: function (v) {
  119. return v * 3
  120. }
  121. }
  122. var d = new Directive('test', el, vm, {
  123. expression: 'a',
  124. filters: [{name:'test'}]
  125. }, def)
  126. d.set(2)
  127. expect(vm.a).toBe(6)
  128. nextTick(function () {
  129. expect(def.update.calls.count()).toBe(2)
  130. expect(def.update).toHaveBeenCalledWith(6, 1)
  131. // locked set
  132. d.set(3, true)
  133. expect(vm.a).toBe(9)
  134. nextTick(function () {
  135. // should have no update calls
  136. expect(def.update.calls.count()).toBe(2)
  137. done()
  138. })
  139. })
  140. })
  141. it('function def', function () {
  142. var d = new Directive('test', el, vm, {
  143. expression: 'a'
  144. }, def.update)
  145. expect(d.update).toBe(def.update)
  146. expect(def.update).toHaveBeenCalled()
  147. })
  148. it('reuse the same watcher', function (done) {
  149. var d = new Directive('test', el, vm, {
  150. expression: 'a',
  151. }, def)
  152. var d2 = new Directive('test', el, vm, {
  153. expression: 'a',
  154. }, def)
  155. expect(vm._watcherList.length).toBe(1)
  156. expect(d._watcher).toBe(d2._watcher)
  157. d2._teardown()
  158. expect(d2._watcher).toBeNull()
  159. expect(vm._watcherList.length).toBe(1)
  160. vm.a = 2
  161. nextTick(function () {
  162. expect(def.update).toHaveBeenCalledWith(2, 1)
  163. d._teardown()
  164. expect(vm._watcherList.length).toBe(0)
  165. done()
  166. })
  167. })
  168. it('avoid update when vm is being destroyed', function (done) {
  169. var d = new Directive('test', el, vm, {
  170. expression: 'a',
  171. }, def)
  172. expect(def.update.calls.count()).toBe(1)
  173. vm._isBeingDestroyed = true
  174. vm.a = 2
  175. nextTick(function () {
  176. expect(def.update.calls.count()).toBe(1)
  177. done()
  178. })
  179. })
  180. })