computed.spec.ts 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. import { computed, reactive, effect, stop, ref } from '../src'
  2. describe('reactivity/computed', () => {
  3. it('should return updated value', () => {
  4. const value: any = reactive({})
  5. const cValue = computed(() => value.foo)
  6. expect(cValue.value).toBe(undefined)
  7. value.foo = 1
  8. expect(cValue.value).toBe(1)
  9. })
  10. it('should compute lazily', () => {
  11. const value: any = reactive({})
  12. const getter = jest.fn(() => value.foo)
  13. const cValue = computed(getter)
  14. // lazy
  15. expect(getter).not.toHaveBeenCalled()
  16. expect(cValue.value).toBe(undefined)
  17. expect(getter).toHaveBeenCalledTimes(1)
  18. // should not compute again
  19. cValue.value
  20. expect(getter).toHaveBeenCalledTimes(1)
  21. // should not compute until needed
  22. value.foo = 1
  23. expect(getter).toHaveBeenCalledTimes(1)
  24. // now it should compute
  25. expect(cValue.value).toBe(1)
  26. expect(getter).toHaveBeenCalledTimes(2)
  27. // should not compute again
  28. cValue.value
  29. expect(getter).toHaveBeenCalledTimes(2)
  30. })
  31. it('should trigger effect', () => {
  32. const value: any = reactive({})
  33. const cValue = computed(() => value.foo)
  34. let dummy
  35. effect(() => {
  36. dummy = cValue.value
  37. })
  38. expect(dummy).toBe(undefined)
  39. value.foo = 1
  40. expect(dummy).toBe(1)
  41. })
  42. it('should work when chained', () => {
  43. const value: any = reactive({ foo: 0 })
  44. const c1 = computed(() => value.foo)
  45. const c2 = computed(() => c1.value + 1)
  46. expect(c2.value).toBe(1)
  47. expect(c1.value).toBe(0)
  48. value.foo++
  49. expect(c2.value).toBe(2)
  50. expect(c1.value).toBe(1)
  51. })
  52. it('should trigger effect when chained', () => {
  53. const value: any = reactive({ foo: 0 })
  54. const getter1 = jest.fn(() => value.foo)
  55. const getter2 = jest.fn(() => {
  56. return c1.value + 1
  57. })
  58. const c1 = computed(getter1)
  59. const c2 = computed(getter2)
  60. let dummy
  61. effect(() => {
  62. dummy = c2.value
  63. })
  64. expect(dummy).toBe(1)
  65. expect(getter1).toHaveBeenCalledTimes(1)
  66. expect(getter2).toHaveBeenCalledTimes(1)
  67. value.foo++
  68. expect(dummy).toBe(2)
  69. // should not result in duplicate calls
  70. expect(getter1).toHaveBeenCalledTimes(2)
  71. expect(getter2).toHaveBeenCalledTimes(2)
  72. })
  73. it('should trigger effect when chained (mixed invocations)', () => {
  74. const value: any = reactive({ foo: 0 })
  75. const getter1 = jest.fn(() => value.foo)
  76. const getter2 = jest.fn(() => {
  77. return c1.value + 1
  78. })
  79. const c1 = computed(getter1)
  80. const c2 = computed(getter2)
  81. let dummy
  82. effect(() => {
  83. dummy = c1.value + c2.value
  84. })
  85. expect(dummy).toBe(1)
  86. expect(getter1).toHaveBeenCalledTimes(1)
  87. expect(getter2).toHaveBeenCalledTimes(1)
  88. value.foo++
  89. expect(dummy).toBe(3)
  90. // should not result in duplicate calls
  91. expect(getter1).toHaveBeenCalledTimes(2)
  92. expect(getter2).toHaveBeenCalledTimes(2)
  93. })
  94. it('should no longer update when stopped', () => {
  95. const value: any = reactive({})
  96. const cValue = computed(() => value.foo)
  97. let dummy
  98. effect(() => {
  99. dummy = cValue.value
  100. })
  101. expect(dummy).toBe(undefined)
  102. value.foo = 1
  103. expect(dummy).toBe(1)
  104. stop(cValue.effect)
  105. value.foo = 2
  106. expect(dummy).toBe(1)
  107. })
  108. it('should support setter', () => {
  109. const n = ref(1)
  110. const plusOne = computed({
  111. get: () => n.value + 1,
  112. set: val => {
  113. n.value = val - 1
  114. }
  115. })
  116. expect(plusOne.value).toBe(2)
  117. n.value++
  118. expect(plusOne.value).toBe(3)
  119. plusOne.value = 0
  120. expect(n.value).toBe(-1)
  121. })
  122. it('should trigger effect w/ setter', () => {
  123. const n = ref(1)
  124. const plusOne = computed({
  125. get: () => n.value + 1,
  126. set: val => {
  127. n.value = val - 1
  128. }
  129. })
  130. let dummy
  131. effect(() => {
  132. dummy = n.value
  133. })
  134. expect(dummy).toBe(1)
  135. plusOne.value = 0
  136. expect(dummy).toBe(-1)
  137. })
  138. })