compileScriptRefTransform.spec.ts 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. import { BindingTypes } from '@vue/compiler-core'
  2. import { compileSFCScript as compile, assertCode } from './utils'
  3. // this file only tests integration with SFC - main test case for the ref
  4. // transform can be found in <root>/packages/reactivity-transform/__tests__
  5. describe('sfc ref transform', () => {
  6. function compileWithReactivityTransform(src: string) {
  7. return compile(src, { reactivityTransform: true })
  8. }
  9. test('$ unwrapping', () => {
  10. const { content, bindings } = compileWithReactivityTransform(`<script setup>
  11. import { ref, shallowRef } from 'vue'
  12. let foo = $(ref())
  13. let a = $(ref(1))
  14. let b = $(shallowRef({
  15. count: 0
  16. }))
  17. let c = () => {}
  18. let d
  19. </script>`)
  20. expect(content).not.toMatch(`$(ref())`)
  21. expect(content).not.toMatch(`$(ref(1))`)
  22. expect(content).not.toMatch(`$(shallowRef({`)
  23. expect(content).toMatch(`let foo = (ref())`)
  24. expect(content).toMatch(`let a = (ref(1))`)
  25. expect(content).toMatch(`
  26. let b = (shallowRef({
  27. count: 0
  28. }))
  29. `)
  30. // normal declarations left untouched
  31. expect(content).toMatch(`let c = () => {}`)
  32. expect(content).toMatch(`let d`)
  33. expect(content).toMatch(`return { foo, a, b, c, d, ref, shallowRef }`)
  34. assertCode(content)
  35. expect(bindings).toStrictEqual({
  36. foo: BindingTypes.SETUP_REF,
  37. a: BindingTypes.SETUP_REF,
  38. b: BindingTypes.SETUP_REF,
  39. c: BindingTypes.SETUP_LET,
  40. d: BindingTypes.SETUP_LET,
  41. ref: BindingTypes.SETUP_CONST,
  42. shallowRef: BindingTypes.SETUP_CONST
  43. })
  44. })
  45. test('$ref & $shallowRef declarations', () => {
  46. const { content, bindings } = compileWithReactivityTransform(`<script setup>
  47. let foo = $ref()
  48. let a = $ref(1)
  49. let b = $shallowRef({
  50. count: 0
  51. })
  52. let c = () => {}
  53. let d
  54. </script>`)
  55. expect(content).toMatch(
  56. `import { ref as _ref, shallowRef as _shallowRef } from 'vue'`
  57. )
  58. expect(content).not.toMatch(`$ref()`)
  59. expect(content).not.toMatch(`$ref(1)`)
  60. expect(content).not.toMatch(`$shallowRef({`)
  61. expect(content).toMatch(`let foo = _ref()`)
  62. expect(content).toMatch(`let a = _ref(1)`)
  63. expect(content).toMatch(`
  64. let b = _shallowRef({
  65. count: 0
  66. })
  67. `)
  68. // normal declarations left untouched
  69. expect(content).toMatch(`let c = () => {}`)
  70. expect(content).toMatch(`let d`)
  71. assertCode(content)
  72. expect(bindings).toStrictEqual({
  73. foo: BindingTypes.SETUP_REF,
  74. a: BindingTypes.SETUP_REF,
  75. b: BindingTypes.SETUP_REF,
  76. c: BindingTypes.SETUP_LET,
  77. d: BindingTypes.SETUP_LET
  78. })
  79. })
  80. test('usage in normal <script>', () => {
  81. const { content } = compileWithReactivityTransform(`<script>
  82. export default {
  83. setup() {
  84. let count = $ref(0)
  85. const inc = () => count++
  86. return $$({ count })
  87. }
  88. }
  89. </script>`)
  90. expect(content).not.toMatch(`$ref(0)`)
  91. expect(content).toMatch(`import { ref as _ref } from 'vue'`)
  92. expect(content).toMatch(`let count = _ref(0)`)
  93. expect(content).toMatch(`count.value++`)
  94. expect(content).toMatch(`return ({ count })`)
  95. assertCode(content)
  96. })
  97. test('usage /w typescript', () => {
  98. const { content } = compileWithReactivityTransform(`
  99. <script setup lang="ts">
  100. let msg = $ref<string | number>('foo');
  101. let bar = $ref <string | number>('bar');
  102. </script>
  103. `)
  104. expect(content).toMatch(`import { ref as _ref`)
  105. expect(content).toMatch(`let msg = _ref<string | number>('foo')`)
  106. expect(content).toMatch(`let bar = _ref <string | number>('bar')`)
  107. assertCode(content)
  108. })
  109. test('usage with normal <script> + <script setup>', () => {
  110. const { content, bindings } = compileWithReactivityTransform(`<script>
  111. let a = $ref(0)
  112. let c = $ref(0)
  113. </script>
  114. <script setup>
  115. let b = $ref(0)
  116. let c = 0
  117. function change() {
  118. a++
  119. b++
  120. c++
  121. }
  122. </script>`)
  123. // should dedupe helper imports
  124. expect(content).toMatch(`import { ref as _ref } from 'vue'`)
  125. expect(content).toMatch(`let a = _ref(0)`)
  126. expect(content).toMatch(`let b = _ref(0)`)
  127. // root level ref binding declared in <script> should be inherited in <script setup>
  128. expect(content).toMatch(`a.value++`)
  129. expect(content).toMatch(`b.value++`)
  130. // c shadowed
  131. expect(content).toMatch(`c++`)
  132. assertCode(content)
  133. expect(bindings).toStrictEqual({
  134. a: BindingTypes.SETUP_REF,
  135. b: BindingTypes.SETUP_REF,
  136. c: BindingTypes.SETUP_REF,
  137. change: BindingTypes.SETUP_CONST
  138. })
  139. })
  140. describe('errors', () => {
  141. test('defineProps/Emit() referencing ref declarations', () => {
  142. expect(() =>
  143. compile(
  144. `<script setup>
  145. let bar = $ref(1)
  146. defineProps({
  147. bar
  148. })
  149. </script>`,
  150. { reactivityTransform: true }
  151. )
  152. ).toThrow(`cannot reference locally declared variables`)
  153. expect(() =>
  154. compile(
  155. `<script setup>
  156. let bar = $ref(1)
  157. defineEmits({
  158. bar
  159. })
  160. </script>`,
  161. { reactivityTransform: true }
  162. )
  163. ).toThrow(`cannot reference locally declared variables`)
  164. })
  165. })
  166. })