2
0

useCssVars.spec.ts 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. import {
  2. ref,
  3. render,
  4. useCssVars,
  5. createStaticVNode,
  6. h,
  7. reactive,
  8. nextTick,
  9. ComponentOptions,
  10. Suspense,
  11. FunctionalComponent
  12. } from '@vue/runtime-dom'
  13. describe('useCssVars', () => {
  14. async function assertCssVars(getApp: (state: any) => ComponentOptions) {
  15. const state = reactive({ color: 'red' })
  16. const App = getApp(state)
  17. const root = document.createElement('div')
  18. render(h(App), root)
  19. await nextTick()
  20. for (const c of [].slice.call(root.children as any)) {
  21. expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe(`red`)
  22. }
  23. state.color = 'green'
  24. await nextTick()
  25. for (const c of [].slice.call(root.children as any)) {
  26. expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe('green')
  27. }
  28. }
  29. test('basic', async () => {
  30. await assertCssVars(state => ({
  31. setup() {
  32. // test receiving render context
  33. useCssVars((ctx: any) => ({
  34. color: ctx.color
  35. }))
  36. return state
  37. },
  38. render() {
  39. return h('div')
  40. }
  41. }))
  42. })
  43. test('on fragment root', async () => {
  44. await assertCssVars(state => ({
  45. setup() {
  46. useCssVars(() => state)
  47. return () => [h('div'), h('div')]
  48. }
  49. }))
  50. })
  51. test('on HOCs', async () => {
  52. const Child = () => [h('div'), h('div')]
  53. await assertCssVars(state => ({
  54. setup() {
  55. useCssVars(() => state)
  56. return () => h(Child)
  57. }
  58. }))
  59. })
  60. test('on suspense root', async () => {
  61. const state = reactive({ color: 'red' })
  62. const root = document.createElement('div')
  63. let resolveAsync: any
  64. let asyncPromise: any
  65. const AsyncComp = {
  66. setup() {
  67. asyncPromise = new Promise(r => {
  68. resolveAsync = () => {
  69. r(() => h('p', 'default'))
  70. }
  71. })
  72. return asyncPromise
  73. }
  74. }
  75. const App = {
  76. setup() {
  77. useCssVars(() => state)
  78. return () =>
  79. h(Suspense, null, {
  80. default: h(AsyncComp),
  81. fallback: h('div', 'fallback')
  82. })
  83. }
  84. }
  85. render(h(App), root)
  86. await nextTick()
  87. // css vars use with fallback tree
  88. for (const c of [].slice.call(root.children as any)) {
  89. expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe(`red`)
  90. }
  91. // AsyncComp resolve
  92. resolveAsync()
  93. await asyncPromise.then(() => {})
  94. // Suspense effects flush
  95. await nextTick()
  96. // css vars use with default tree
  97. for (const c of [].slice.call(root.children as any)) {
  98. expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe(`red`)
  99. }
  100. state.color = 'green'
  101. await nextTick()
  102. for (const c of [].slice.call(root.children as any)) {
  103. expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe('green')
  104. }
  105. })
  106. test('with subTree changed', async () => {
  107. const state = reactive({ color: 'red' })
  108. const value = ref(true)
  109. const root = document.createElement('div')
  110. const App = {
  111. setup() {
  112. useCssVars(() => state)
  113. return () => (value.value ? [h('div')] : [h('div'), h('div')])
  114. }
  115. }
  116. render(h(App), root)
  117. await nextTick()
  118. // css vars use with fallback tree
  119. for (const c of [].slice.call(root.children as any)) {
  120. expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe(`red`)
  121. }
  122. value.value = false
  123. await nextTick()
  124. for (const c of [].slice.call(root.children as any)) {
  125. expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe('red')
  126. }
  127. })
  128. // #3894
  129. test('with subTree change inside HOC', async () => {
  130. const state = reactive({ color: 'red' })
  131. const value = ref(true)
  132. const root = document.createElement('div')
  133. const Child: FunctionalComponent = (_, { slots }) => slots.default!()
  134. const App = {
  135. setup() {
  136. useCssVars(() => state)
  137. return () =>
  138. h(
  139. Child,
  140. null,
  141. () => (value.value ? [h('div')] : [h('div'), h('div')])
  142. )
  143. }
  144. }
  145. render(h(App), root)
  146. await nextTick()
  147. // css vars use with fallback tree
  148. for (const c of [].slice.call(root.children as any)) {
  149. expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe(`red`)
  150. }
  151. value.value = false
  152. await nextTick()
  153. for (const c of [].slice.call(root.children as any)) {
  154. expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe('red')
  155. }
  156. })
  157. test('with createStaticVNode', async () => {
  158. const state = reactive({ color: 'red' })
  159. const root = document.createElement('div')
  160. const App = {
  161. setup() {
  162. useCssVars(() => state)
  163. return () => [
  164. h('div'),
  165. createStaticVNode('<div>1</div><div><span>2</span></div>', 2),
  166. h('div')
  167. ]
  168. }
  169. }
  170. render(h(App), root)
  171. await nextTick()
  172. for (const c of [].slice.call(root.children as any)) {
  173. expect((c as HTMLElement).style.getPropertyValue(`--color`)).toBe('red')
  174. }
  175. })
  176. })