vShow.spec.ts 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. import {
  2. type VNode,
  3. defineComponent,
  4. h,
  5. nextTick,
  6. ref,
  7. watch,
  8. withDirectives,
  9. } from '@vue/runtime-core'
  10. import { Transition, render, vShow } from '@vue/runtime-dom'
  11. const withVShow = (node: VNode, exp: any) =>
  12. withDirectives(node, [[vShow, exp]])
  13. let root: any
  14. beforeEach(() => {
  15. root = document.createElement('div')
  16. })
  17. describe('runtime-dom: v-show directive', () => {
  18. test('should check show value is truthy', async () => {
  19. const component = defineComponent({
  20. data() {
  21. return { value: true }
  22. },
  23. render() {
  24. return [withVShow(h('div'), this.value)]
  25. },
  26. })
  27. render(h(component), root)
  28. const $div = root.children[0]
  29. expect($div.style.display).toEqual('')
  30. })
  31. test('should check show value is falsy', async () => {
  32. const component = defineComponent({
  33. data() {
  34. return { value: false }
  35. },
  36. render() {
  37. return [withVShow(h('div'), this.value)]
  38. },
  39. })
  40. render(h(component), root)
  41. const $div = root.children[0]
  42. expect($div.style.display).toEqual('none')
  43. })
  44. it('should update show value changed', async () => {
  45. const component = defineComponent({
  46. data() {
  47. return { value: true }
  48. },
  49. render() {
  50. return [withVShow(h('div'), this.value)]
  51. },
  52. })
  53. render(h(component), root)
  54. const $div = root.children[0]
  55. const data = root._vnode.component.data
  56. expect($div.style.display).toEqual('')
  57. data.value = false
  58. await nextTick()
  59. expect($div.style.display).toEqual('none')
  60. data.value = {}
  61. await nextTick()
  62. expect($div.style.display).toEqual('')
  63. data.value = 0
  64. await nextTick()
  65. expect($div.style.display).toEqual('none')
  66. data.value = []
  67. await nextTick()
  68. expect($div.style.display).toEqual('')
  69. data.value = null
  70. await nextTick()
  71. expect($div.style.display).toEqual('none')
  72. data.value = '0'
  73. await nextTick()
  74. expect($div.style.display).toEqual('')
  75. data.value = undefined
  76. await nextTick()
  77. expect($div.style.display).toEqual('none')
  78. data.value = 1
  79. await nextTick()
  80. expect($div.style.display).toEqual('')
  81. })
  82. test('should respect display value in style attribute', async () => {
  83. const component = defineComponent({
  84. data() {
  85. return { value: true }
  86. },
  87. render() {
  88. return [
  89. withVShow(h('div', { style: { display: 'block' } }), this.value),
  90. ]
  91. },
  92. })
  93. render(h(component), root)
  94. const $div = root.children[0]
  95. const data = root._vnode.component.data
  96. expect($div.style.display).toEqual('block')
  97. data.value = false
  98. await nextTick()
  99. expect($div.style.display).toEqual('none')
  100. data.value = true
  101. await nextTick()
  102. expect($div.style.display).toEqual('block')
  103. })
  104. // #2583
  105. test('the value of `display` set by v-show should not be overwritten by the style attribute when updated', async () => {
  106. const style = ref('width: 100px')
  107. const display = ref(false)
  108. const component = defineComponent({
  109. render() {
  110. return withVShow(h('div', { style: style.value }), display.value)
  111. },
  112. })
  113. render(h(component), root)
  114. const $div = root.children[0]
  115. expect($div.style.display).toEqual('none')
  116. style.value = 'width: 50px'
  117. await nextTick()
  118. expect($div.style.display).toEqual('none')
  119. display.value = true
  120. await nextTick()
  121. expect($div.style.display).toEqual('')
  122. })
  123. test('the value of `display` set by v-show should not be overwritten by the style attribute when updated (object value)', async () => {
  124. const style = ref({
  125. display: 'block',
  126. width: '100px',
  127. })
  128. const display = ref(false)
  129. const component = defineComponent({
  130. render() {
  131. return withVShow(h('div', { style: style.value }), display.value)
  132. },
  133. })
  134. render(h(component), root)
  135. const $div = root.children[0]
  136. expect($div.style.display).toEqual('none')
  137. style.value.width = '50px'
  138. await nextTick()
  139. expect($div.style.display).toEqual('none')
  140. display.value = true
  141. await nextTick()
  142. expect($div.style.display).toEqual('block')
  143. })
  144. // #2583, #2757
  145. test('the value of `display` set by v-show should not be overwritten by the style attribute when updated (with Transition)', async () => {
  146. const style = ref('width: 100px')
  147. const display = ref(false)
  148. const component = defineComponent({
  149. setup() {
  150. const innerValue = ref(false)
  151. watch(display, val => {
  152. innerValue.value = val
  153. })
  154. return () => {
  155. return h(Transition, () =>
  156. withVShow(
  157. h('div', { style: style.value }, innerValue.value),
  158. display.value,
  159. ),
  160. )
  161. }
  162. },
  163. })
  164. render(h(component), root)
  165. const $div = root.children[0]
  166. expect($div.style.display).toEqual('none')
  167. style.value = 'width: 50px'
  168. await nextTick()
  169. expect($div.style.display).toEqual('none')
  170. display.value = true
  171. await nextTick()
  172. expect($div.style.display).toEqual('')
  173. })
  174. // #10151
  175. test('should respect the display value when v-show value is true', async () => {
  176. const isVisible = ref(false)
  177. const useDisplayStyle = ref(true)
  178. const compStyle = ref({
  179. display: 'none',
  180. })
  181. const withoutDisplayStyle = {
  182. margin: '10px',
  183. }
  184. const Component = {
  185. setup() {
  186. return () => {
  187. return withVShow(
  188. h('div', {
  189. style: useDisplayStyle.value
  190. ? compStyle.value
  191. : withoutDisplayStyle,
  192. }),
  193. isVisible.value,
  194. )
  195. }
  196. },
  197. }
  198. render(h(Component), root)
  199. const $div = root.children[0]
  200. expect($div.style.display).toEqual('none')
  201. isVisible.value = true
  202. await nextTick()
  203. expect($div.style.display).toEqual('none')
  204. compStyle.value.display = 'block'
  205. await nextTick()
  206. expect($div.style.display).toEqual('block')
  207. compStyle.value.display = 'inline-block'
  208. await nextTick()
  209. expect($div.style.display).toEqual('inline-block')
  210. isVisible.value = false
  211. await nextTick()
  212. expect($div.style.display).toEqual('none')
  213. isVisible.value = true
  214. await nextTick()
  215. expect($div.style.display).toEqual('inline-block')
  216. useDisplayStyle.value = false
  217. await nextTick()
  218. expect($div.style.display).toEqual('')
  219. expect(getComputedStyle($div).display).toEqual('block')
  220. isVisible.value = false
  221. await nextTick()
  222. expect($div.style.display).toEqual('none')
  223. isVisible.value = true
  224. await nextTick()
  225. expect($div.style.display).toEqual('')
  226. })
  227. })