compileScriptRefTransform.spec.ts 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  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(
  34. `return { foo, a, b, get c() { return c }, set c(v) { c = v }, ` +
  35. `get d() { return d }, set d(v) { d = v }, ref, shallowRef }`
  36. )
  37. assertCode(content)
  38. expect(bindings).toStrictEqual({
  39. foo: BindingTypes.SETUP_REF,
  40. a: BindingTypes.SETUP_REF,
  41. b: BindingTypes.SETUP_REF,
  42. c: BindingTypes.SETUP_LET,
  43. d: BindingTypes.SETUP_LET,
  44. ref: BindingTypes.SETUP_CONST,
  45. shallowRef: BindingTypes.SETUP_CONST
  46. })
  47. })
  48. test('$ref & $shallowRef declarations', () => {
  49. const { content, bindings } = compileWithReactivityTransform(`<script setup>
  50. let foo = $ref()
  51. let a = $ref(1)
  52. let b = $shallowRef({
  53. count: 0
  54. })
  55. let c = () => {}
  56. let d
  57. </script>`)
  58. expect(content).toMatch(
  59. `import { ref as _ref, shallowRef as _shallowRef } from 'vue'`
  60. )
  61. expect(content).not.toMatch(`$ref()`)
  62. expect(content).not.toMatch(`$ref(1)`)
  63. expect(content).not.toMatch(`$shallowRef({`)
  64. expect(content).toMatch(`let foo = _ref()`)
  65. expect(content).toMatch(`let a = _ref(1)`)
  66. expect(content).toMatch(`
  67. let b = _shallowRef({
  68. count: 0
  69. })
  70. `)
  71. // normal declarations left untouched
  72. expect(content).toMatch(`let c = () => {}`)
  73. expect(content).toMatch(`let d`)
  74. assertCode(content)
  75. expect(bindings).toStrictEqual({
  76. foo: BindingTypes.SETUP_REF,
  77. a: BindingTypes.SETUP_REF,
  78. b: BindingTypes.SETUP_REF,
  79. c: BindingTypes.SETUP_LET,
  80. d: BindingTypes.SETUP_LET
  81. })
  82. })
  83. test('usage in normal <script>', () => {
  84. const { content } = compileWithReactivityTransform(`<script>
  85. export default {
  86. setup() {
  87. let count = $ref(0)
  88. const inc = () => count++
  89. return $$({ count })
  90. }
  91. }
  92. </script>`)
  93. expect(content).not.toMatch(`$ref(0)`)
  94. expect(content).toMatch(`import { ref as _ref } from 'vue'`)
  95. expect(content).toMatch(`let count = _ref(0)`)
  96. expect(content).toMatch(`count.value++`)
  97. expect(content).toMatch(`return ({ count })`)
  98. assertCode(content)
  99. })
  100. test('usage /w typescript', () => {
  101. const { content } = compileWithReactivityTransform(`
  102. <script setup lang="ts">
  103. let msg = $ref<string | number>('foo');
  104. let bar = $ref <string | number>('bar');
  105. </script>
  106. `)
  107. expect(content).toMatch(`import { ref as _ref`)
  108. expect(content).toMatch(`let msg = _ref<string | number>('foo')`)
  109. expect(content).toMatch(`let bar = _ref <string | number>('bar')`)
  110. assertCode(content)
  111. })
  112. test('usage with normal <script> + <script setup>', () => {
  113. const { content, bindings } = compileWithReactivityTransform(`<script>
  114. let a = $ref(0)
  115. let c = $ref(0)
  116. </script>
  117. <script setup>
  118. let b = $ref(0)
  119. let c = 0
  120. function change() {
  121. a++
  122. b++
  123. c++
  124. }
  125. </script>`)
  126. // should dedupe helper imports
  127. expect(content).toMatch(`import { ref as _ref } from 'vue'`)
  128. expect(content).toMatch(`let a = _ref(0)`)
  129. expect(content).toMatch(`let b = _ref(0)`)
  130. // root level ref binding declared in <script> should be inherited in <script setup>
  131. expect(content).toMatch(`a.value++`)
  132. expect(content).toMatch(`b.value++`)
  133. // c shadowed
  134. expect(content).toMatch(`c++`)
  135. assertCode(content)
  136. expect(bindings).toStrictEqual({
  137. a: BindingTypes.SETUP_REF,
  138. b: BindingTypes.SETUP_REF,
  139. c: BindingTypes.SETUP_REF,
  140. change: BindingTypes.SETUP_CONST
  141. })
  142. })
  143. test('usage with normal <script> (has macro usage) + <script setup> (no macro usage)', () => {
  144. const { content } = compileWithReactivityTransform(`
  145. <script>
  146. let data = $ref()
  147. </script>
  148. <script setup>
  149. console.log(data)
  150. </script>
  151. `)
  152. expect(content).toMatch(`console.log(data.value)`)
  153. assertCode(content)
  154. })
  155. describe('errors', () => {
  156. test('defineProps/Emit() referencing ref declarations', () => {
  157. expect(() =>
  158. compile(
  159. `<script setup>
  160. let bar = $ref(1)
  161. defineProps({
  162. bar
  163. })
  164. </script>`,
  165. { reactivityTransform: true }
  166. )
  167. ).toThrow(`cannot reference locally declared variables`)
  168. expect(() =>
  169. compile(
  170. `<script setup>
  171. let bar = $ref(1)
  172. defineEmits({
  173. bar
  174. })
  175. </script>`,
  176. { reactivityTransform: true }
  177. )
  178. ).toThrow(`cannot reference locally declared variables`)
  179. })
  180. })
  181. })