class.spec.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. import Vue from 'vue'
  2. function assertClass (assertions, done) {
  3. const vm = new Vue({
  4. template: '<div class="foo" :class="value"></div>',
  5. data: { value: '' }
  6. }).$mount()
  7. const chain = waitForUpdate()
  8. assertions.forEach(([value, expected], i) => {
  9. chain.then(() => {
  10. if (typeof value === 'function') {
  11. value(vm.value)
  12. } else {
  13. vm.value = value
  14. }
  15. }).then(() => {
  16. expect(vm.$el.className).toBe(expected)
  17. if (i >= assertions.length - 1) {
  18. done()
  19. }
  20. })
  21. })
  22. chain.then(done)
  23. }
  24. describe('Directive v-bind:class', () => {
  25. it('plain string', done => {
  26. assertClass([
  27. ['bar', 'foo bar'],
  28. ['baz qux', 'foo baz qux'],
  29. ['qux', 'foo qux'],
  30. [undefined, 'foo']
  31. ], done)
  32. })
  33. it('object value', done => {
  34. assertClass([
  35. [{ bar: true, baz: false }, 'foo bar'],
  36. [{ baz: true }, 'foo baz'],
  37. [null, 'foo'],
  38. [{ 'bar baz': true, qux: false }, 'foo bar baz'],
  39. [{ qux: true }, 'foo qux']
  40. ], done)
  41. })
  42. it('array value', done => {
  43. assertClass([
  44. [['bar', 'baz'], 'foo bar baz'],
  45. [['qux', 'baz'], 'foo qux baz'],
  46. [['w', 'x y z'], 'foo w x y z'],
  47. [undefined, 'foo'],
  48. [['bar'], 'foo bar'],
  49. [val => val.push('baz'), 'foo bar baz']
  50. ], done)
  51. })
  52. it('array of mixed values', done => {
  53. assertClass([
  54. [['x', { y: true, z: true }], 'foo x y z'],
  55. [['x', { y: true, z: false }], 'foo x y'],
  56. [['f', { z: true }], 'foo f z'],
  57. [['l', 'f', { n: true, z: true }], 'foo l f n z'],
  58. [['x', {}], 'foo x'],
  59. [undefined, 'foo']
  60. ], done)
  61. })
  62. it('class merge between parent and child', done => {
  63. const vm = new Vue({
  64. template: '<child class="a" :class="value"></child>',
  65. data: { value: 'b' },
  66. components: {
  67. child: {
  68. template: '<div class="c" :class="value"></div>',
  69. data: () => ({ value: 'd' })
  70. }
  71. }
  72. }).$mount()
  73. const child = vm.$children[0]
  74. expect(vm.$el.className).toBe('c a d b')
  75. vm.value = 'e'
  76. waitForUpdate(() => {
  77. expect(vm.$el.className).toBe('c a d e')
  78. }).then(() => {
  79. child.value = 'f'
  80. }).then(() => {
  81. expect(vm.$el.className).toBe('c a f e')
  82. }).then(() => {
  83. vm.value = { foo: true }
  84. child.value = ['bar', 'baz']
  85. }).then(() => {
  86. expect(vm.$el.className).toBe('c a bar baz foo')
  87. }).then(done)
  88. })
  89. it('class merge between multiple nested components sharing same element', done => {
  90. const vm = new Vue({
  91. template: `
  92. <component1 :class="componentClass1">
  93. <component2 :class="componentClass2">
  94. <component3 :class="componentClass3">
  95. some text
  96. </component3>
  97. </component2>
  98. </component1>
  99. `,
  100. data: {
  101. componentClass1: 'componentClass1',
  102. componentClass2: 'componentClass2',
  103. componentClass3: 'componentClass3'
  104. },
  105. components: {
  106. component1: {
  107. render () {
  108. return this.$slots.default[0]
  109. }
  110. },
  111. component2: {
  112. render () {
  113. return this.$slots.default[0]
  114. }
  115. },
  116. component3: {
  117. template: '<div class="staticClass"><slot></slot></div>'
  118. }
  119. }
  120. }).$mount()
  121. expect(vm.$el.className).toBe('staticClass componentClass3 componentClass2 componentClass1')
  122. vm.componentClass1 = 'c1'
  123. waitForUpdate(() => {
  124. expect(vm.$el.className).toBe('staticClass componentClass3 componentClass2 c1')
  125. vm.componentClass2 = 'c2'
  126. }).then(() => {
  127. expect(vm.$el.className).toBe('staticClass componentClass3 c2 c1')
  128. vm.componentClass3 = 'c3'
  129. }).then(() => {
  130. expect(vm.$el.className).toBe('staticClass c3 c2 c1')
  131. }).then(done)
  132. })
  133. it('deep update', done => {
  134. const vm = new Vue({
  135. template: '<div :class="test"></div>',
  136. data: {
  137. test: { a: true, b: false }
  138. }
  139. }).$mount()
  140. expect(vm.$el.className).toBe('a')
  141. vm.test.b = true
  142. waitForUpdate(() => {
  143. expect(vm.$el.className).toBe('a b')
  144. }).then(done)
  145. })
  146. // a vdom patch edge case where the user has several un-keyed elements of the
  147. // same tag next to each other, and toggling them.
  148. it('properly remove staticClass for toggling un-keyed children', done => {
  149. const vm = new Vue({
  150. template: `
  151. <div>
  152. <div v-if="ok" class="a"></div>
  153. <div v-if="!ok"></div>
  154. </div>
  155. `,
  156. data: {
  157. ok: true
  158. }
  159. }).$mount()
  160. expect(vm.$el.children[0].className).toBe('a')
  161. vm.ok = false
  162. waitForUpdate(() => {
  163. expect(vm.$el.children[0].className).toBe('')
  164. }).then(done)
  165. })
  166. })