ref.spec.ts 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. import { ref, effect, reactive, isRef, toRefs } from '../src/index'
  2. import { computed } from '@vue/runtime-dom'
  3. describe('reactivity/ref', () => {
  4. it('should hold a value', () => {
  5. const a = ref(1)
  6. expect(a.value).toBe(1)
  7. a.value = 2
  8. expect(a.value).toBe(2)
  9. })
  10. it('should be reactive', () => {
  11. const a = ref(1)
  12. let dummy
  13. effect(() => {
  14. dummy = a.value
  15. })
  16. expect(dummy).toBe(1)
  17. a.value = 2
  18. expect(dummy).toBe(2)
  19. })
  20. it('should make nested properties reactive', () => {
  21. const a = ref({
  22. count: 1
  23. })
  24. let dummy
  25. effect(() => {
  26. dummy = a.value.count
  27. })
  28. expect(dummy).toBe(1)
  29. a.value.count = 2
  30. expect(dummy).toBe(2)
  31. })
  32. it('should work like a normal property when nested in a reactive object', () => {
  33. const a = ref(1)
  34. const obj = reactive({
  35. a,
  36. b: {
  37. c: a,
  38. d: [a]
  39. }
  40. })
  41. let dummy1
  42. let dummy2
  43. let dummy3
  44. effect(() => {
  45. dummy1 = obj.a
  46. dummy2 = obj.b.c
  47. dummy3 = obj.b.d[0]
  48. })
  49. expect(dummy1).toBe(1)
  50. expect(dummy2).toBe(1)
  51. expect(dummy3).toBe(1)
  52. a.value++
  53. expect(dummy1).toBe(2)
  54. expect(dummy2).toBe(2)
  55. expect(dummy3).toBe(2)
  56. obj.a++
  57. expect(dummy1).toBe(3)
  58. expect(dummy2).toBe(3)
  59. expect(dummy3).toBe(3)
  60. })
  61. it('should unwrap nested ref in types', () => {
  62. const a = ref(0)
  63. const b = ref(a)
  64. expect(typeof (b.value + 1)).toBe('number')
  65. })
  66. it('should unwrap nested values in types', () => {
  67. const a = {
  68. b: ref(0)
  69. }
  70. const c = ref(a)
  71. expect(typeof (c.value.b + 1)).toBe('number')
  72. })
  73. it('should properly unwrap ref types nested inside arrays', () => {
  74. const arr = ref([1, ref(1)]).value
  75. // should unwrap to number[]
  76. arr[0]++
  77. arr[1]++
  78. const arr2 = ref([1, new Map<string, any>(), ref('1')]).value
  79. const value = arr2[0]
  80. if (typeof value === 'string') {
  81. value + 'foo'
  82. } else if (typeof value === 'number') {
  83. value + 1
  84. } else {
  85. // should narrow down to Map type
  86. // and not contain any Ref type
  87. value.has('foo')
  88. }
  89. })
  90. test('isRef', () => {
  91. expect(isRef(ref(1))).toBe(true)
  92. expect(isRef(computed(() => 1))).toBe(true)
  93. expect(isRef(0)).toBe(false)
  94. expect(isRef(1)).toBe(false)
  95. // an object that looks like a ref isn't necessarily a ref
  96. expect(isRef({ value: 0 })).toBe(false)
  97. })
  98. test('toRefs', () => {
  99. const a = reactive({
  100. x: 1,
  101. y: 2
  102. })
  103. const { x, y } = toRefs(a)
  104. expect(isRef(x)).toBe(true)
  105. expect(isRef(y)).toBe(true)
  106. expect(x.value).toBe(1)
  107. expect(y.value).toBe(2)
  108. // source -> proxy
  109. a.x = 2
  110. a.y = 3
  111. expect(x.value).toBe(2)
  112. expect(y.value).toBe(3)
  113. // proxy -> source
  114. x.value = 3
  115. y.value = 4
  116. expect(a.x).toBe(3)
  117. expect(a.y).toBe(4)
  118. // reactivity
  119. let dummyX, dummyY
  120. effect(() => {
  121. dummyX = x.value
  122. dummyY = y.value
  123. })
  124. expect(dummyX).toBe(x.value)
  125. expect(dummyY).toBe(y.value)
  126. // mutating source should trigger effect using the proxy refs
  127. a.x = 4
  128. a.y = 5
  129. expect(dummyX).toBe(4)
  130. expect(dummyY).toBe(5)
  131. })
  132. })