compileScriptRefTransform.spec.ts 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  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/ref-transform/__tests__
  5. describe('sfc ref transform', () => {
  6. function compileWithRefTransform(src: string) {
  7. return compile(src, { refSugar: true })
  8. }
  9. test('$ unwrapping', () => {
  10. const { content, bindings } = compileWithRefTransform(`<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 } = compileWithRefTransform(`<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 } = compileWithRefTransform(`<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 with normal <script> + <script setup>', () => {
  98. const { content, bindings } = compileWithRefTransform(`<script>
  99. let a = $ref(0)
  100. let c = $ref(0)
  101. </script>
  102. <script setup>
  103. let b = $ref(0)
  104. let c = 0
  105. function change() {
  106. a++
  107. b++
  108. c++
  109. }
  110. </script>`)
  111. // should dedupe helper imports
  112. expect(content).toMatch(`import { ref as _ref } from 'vue'`)
  113. expect(content).toMatch(`let a = _ref(0)`)
  114. expect(content).toMatch(`let b = _ref(0)`)
  115. // root level ref binding declared in <script> should be inherited in <script setup>
  116. expect(content).toMatch(`a.value++`)
  117. expect(content).toMatch(`b.value++`)
  118. // c shadowed
  119. expect(content).toMatch(`c++`)
  120. assertCode(content)
  121. expect(bindings).toStrictEqual({
  122. a: BindingTypes.SETUP_REF,
  123. b: BindingTypes.SETUP_REF,
  124. c: BindingTypes.SETUP_REF,
  125. change: BindingTypes.SETUP_CONST
  126. })
  127. })
  128. describe('errors', () => {
  129. test('defineProps/Emit() referencing ref declarations', () => {
  130. expect(() =>
  131. compile(
  132. `<script setup>
  133. let bar = $ref(1)
  134. defineProps({
  135. bar
  136. })
  137. </script>`,
  138. { refSugar: true }
  139. )
  140. ).toThrow(`cannot reference locally declared variables`)
  141. expect(() =>
  142. compile(
  143. `<script setup>
  144. let bar = $ref(1)
  145. defineEmits({
  146. bar
  147. })
  148. </script>`,
  149. { refSugar: true }
  150. )
  151. ).toThrow(`cannot reference locally declared variables`)
  152. })
  153. })
  154. })