misc.js 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. describe('Misc Features', function () {
  2. var nextTick = require('vue/src/utils').nextTick
  3. describe('inline expression', function () {
  4. it('should evaluate the correct value', function (done) {
  5. var v = new Vue({
  6. template: '{{a + "123" + b}} and {{c}}'
  7. })
  8. v.a = 'A'
  9. v.b = 'B'
  10. v.c = 'C'
  11. nextTick(function () {
  12. assert.strictEqual(v.$el.textContent, 'A123B and C')
  13. done()
  14. })
  15. })
  16. })
  17. describe('expression inside attributes', function () {
  18. it('should interpolate the attribute', function (done) {
  19. var v = new Vue({
  20. attributes: {
  21. test: 'one {{msg}} three'
  22. },
  23. data: {
  24. msg: 'two'
  25. }
  26. })
  27. assert.strictEqual(v.$el.getAttribute('test'), 'one two three')
  28. v.msg = '2'
  29. nextTick(function () {
  30. assert.strictEqual(v.$el.getAttribute('test'), 'one 2 three')
  31. done()
  32. })
  33. })
  34. it('should work with filters', function (done) {
  35. var v = new Vue({
  36. attributes: {
  37. 'class': '{{msg | test}}'
  38. },
  39. data: {
  40. msg: 'hello'
  41. },
  42. filters: {
  43. test: function (v) {
  44. return v + '-bye'
  45. }
  46. }
  47. })
  48. assert.strictEqual(v.$el.className, 'hello-bye')
  49. v.msg = 'ok'
  50. nextTick(function () {
  51. assert.strictEqual(v.$el.className, 'ok-bye')
  52. done()
  53. })
  54. })
  55. })
  56. describe('triple mustache', function () {
  57. it('should set unescaped HTML', function () {
  58. var v = new Vue({
  59. template: '{{{html}}}',
  60. data: {
  61. html: '<span>a</span><a>hi</a>'
  62. }
  63. })
  64. assert.strictEqual(v.$el.innerHTML, '<span>a</span><a>hi</a><!--v-html-->')
  65. })
  66. })
  67. describe('computed properties', function () {
  68. it('should be accessible like a normal attribtue', function () {
  69. var b = 2
  70. var v = new Vue({
  71. template: '{{nested.value.a}}',
  72. data: {
  73. a: 1,
  74. },
  75. computed: {
  76. test: {
  77. $get: function () {
  78. return this.a + b
  79. },
  80. $set: function (v) {
  81. b = v - this.a
  82. }
  83. },
  84. getOnly: function () {
  85. return this.a + 1
  86. }
  87. }
  88. })
  89. assert.strictEqual(v.test, 3)
  90. assert.strictEqual(v.getOnly, 2)
  91. v.a = 2
  92. assert.strictEqual(v.test, 4)
  93. assert.strictEqual(v.getOnly, 3)
  94. b = 3
  95. assert.strictEqual(v.test, 5)
  96. v.test = 10
  97. assert.strictEqual(b, 8)
  98. })
  99. it('should be bindable in templates, even nested', function (done) {
  100. var v = new Vue({
  101. template: '{{nested.value.a}}',
  102. data: { a: 1 },
  103. computed: {
  104. nested: function () {
  105. return {
  106. value: {
  107. a: this.a + 2
  108. }
  109. }
  110. }
  111. }
  112. })
  113. assert.strictEqual(v.$el.textContent, '3')
  114. v.a = 2
  115. nextTick(function () {
  116. assert.strictEqual(v.$el.textContent, '4')
  117. done()
  118. })
  119. })
  120. })
  121. describe('setting an object to empty', function () {
  122. it('should emit undefined for paths in the old object', function (done) {
  123. var v = new Vue({
  124. data: {
  125. a: {
  126. b: { c: 1 }
  127. }
  128. }
  129. })
  130. var emitted = false
  131. v.$watch('a.b.c', function (v) {
  132. assert.strictEqual(v, undefined)
  133. emitted = true
  134. })
  135. v.a = {}
  136. nextTick(function () {
  137. assert.ok(emitted)
  138. done()
  139. })
  140. })
  141. })
  142. describe('event delegation', function () {
  143. var inCalled = 0,
  144. outCalled = 0,
  145. innerHandler = function () {}
  146. var v = new Vue({
  147. template: '<div v-on="click:out"><div class="inner" v-on="click:in"></div></div>',
  148. methods: {
  149. 'in': function (e) {
  150. inCalled++
  151. innerHandler(e)
  152. },
  153. out: function () {
  154. outCalled++
  155. }
  156. }
  157. })
  158. v.$appendTo('#test')
  159. it('should work', function () {
  160. var e = mockMouseEvent('click')
  161. v.$el.querySelector('.inner').dispatchEvent(e)
  162. assert.strictEqual(inCalled, 1)
  163. assert.strictEqual(outCalled, 1)
  164. })
  165. it('should allow stopPropagation()', function () {
  166. innerHandler = function (e) {
  167. e.stopPropagation()
  168. }
  169. var e = mockMouseEvent('click')
  170. v.$el.querySelector('.inner').dispatchEvent(e)
  171. assert.strictEqual(inCalled, 2)
  172. assert.strictEqual(outCalled, 1)
  173. })
  174. })
  175. describe('computed filter', function () {
  176. it('should process filter with `this` as computed', function (done) {
  177. var V = Vue.extend({
  178. template: '<div class="plus">{{n | plus}}</div><div class="minus">{{n | minus}}</div>',
  179. filters: {
  180. plus: function (v) {
  181. return v + this.a
  182. }
  183. }
  184. })
  185. V.filter('minus', function (v) {
  186. return v - this.a
  187. })
  188. var v = new V({
  189. data: {
  190. a: 1,
  191. n: 1
  192. }
  193. })
  194. assert.strictEqual(v.$el.querySelector('.plus').textContent, '2')
  195. assert.strictEqual(v.$el.querySelector('.minus').textContent, '0')
  196. v.a = 2
  197. nextTick(function () {
  198. assert.strictEqual(v.$el.querySelector('.plus').textContent, '3')
  199. assert.strictEqual(v.$el.querySelector('.minus').textContent, '-1')
  200. done()
  201. })
  202. })
  203. })
  204. describe('content insertion points', function () {
  205. it('should insert original content', function () {
  206. var div = document.createElement('div')
  207. div.innerHTML = '<h1>hello!</h1>'
  208. var t = new Vue({
  209. el: div,
  210. template: '<h1>before</h1><content></content><p>after</p>'
  211. })
  212. assert.strictEqual(t.$el.innerHTML, '<h1>before</h1><h1>hello!</h1><p>after</p>')
  213. })
  214. it('should respect "select" attributes', function () {
  215. var div = document.createElement('div')
  216. div.innerHTML = '<h1>hi</h1><h1>ha</h1><p>hehe</p>'
  217. var t = new Vue({
  218. el: div,
  219. template: '<h1>before</h1>' +
  220. '<content></content>' +
  221. '<content select="h1:nth-of-type(2)"></content>' +
  222. '<content select="h1:nth-of-type(1)"></content>' +
  223. '<p>after</p>'
  224. })
  225. assert.strictEqual(t.$el.innerHTML,
  226. '<h1>before</h1>' +
  227. '<p>hehe</p>' +
  228. '<h1>ha</h1><h1>hi</h1>' +
  229. '<p>after</p>'
  230. )
  231. })
  232. it('should use fallback content if no rawContent is available', function () {
  233. var t = new Vue({
  234. template: '<content>Hello!</content>'
  235. })
  236. assert.strictEqual(t.$el.innerHTML, 'Hello!')
  237. })
  238. })
  239. describe('interpolation in directive values', function () {
  240. it('should be evaled by the compiler', function () {
  241. var t = new Vue({
  242. template: '<input v-model="{{field}}">',
  243. data: {
  244. field: 'test',
  245. test: 'hello'
  246. }
  247. })
  248. assert.equal(t.$el.childNodes[0].value, 'hello')
  249. })
  250. })
  251. describe('attribute names with colons', function () {
  252. it('should be parsed properly', function () {
  253. var t = new Vue({
  254. template: '<use xlink:href="{{icon}}"></use>',
  255. data: {
  256. icon: 'test'
  257. }
  258. })
  259. assert.equal(t.$el.firstChild.getAttribute('xlink:href'), 'test')
  260. })
  261. })
  262. })