computed.spec.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. import { computed, observable, autorun, stop } from '../src'
  2. describe('observer/computed', () => {
  3. it('should return updated value', () => {
  4. const value: any = observable({})
  5. const cValue = computed(() => value.foo)
  6. expect(cValue()).toBe(undefined)
  7. value.foo = 1
  8. expect(cValue()).toBe(1)
  9. })
  10. it('should compute lazily', () => {
  11. const value: any = observable({})
  12. const getter = jest.fn(() => value.foo)
  13. const cValue = computed(getter)
  14. // lazy
  15. expect(getter).not.toHaveBeenCalled()
  16. expect(cValue()).toBe(undefined)
  17. expect(getter).toHaveBeenCalledTimes(1)
  18. // should not compute again
  19. cValue()
  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()).toBe(1)
  26. expect(getter).toHaveBeenCalledTimes(2)
  27. // should not compute again
  28. cValue()
  29. expect(getter).toHaveBeenCalledTimes(2)
  30. })
  31. it('should accept context', () => {
  32. const value: any = observable({})
  33. let callCtx, callArg
  34. const getter = function(arg: any) {
  35. callCtx = this
  36. callArg = arg
  37. return value.foo
  38. }
  39. const ctx = {}
  40. const cValue = computed(getter, ctx)
  41. cValue()
  42. expect(callCtx).toBe(ctx)
  43. expect(callArg).toBe(ctx)
  44. })
  45. it('should trigger autorun', () => {
  46. const value: any = observable({})
  47. const cValue = computed(() => value.foo)
  48. let dummy
  49. autorun(() => {
  50. dummy = cValue()
  51. })
  52. expect(dummy).toBe(undefined)
  53. value.foo = 1
  54. expect(dummy).toBe(1)
  55. })
  56. it('should work when chained', () => {
  57. const value: any = observable({ foo: 0 })
  58. const c1 = computed(() => value.foo)
  59. const c2 = computed(() => c1() + 1)
  60. expect(c2()).toBe(1)
  61. expect(c1()).toBe(0)
  62. value.foo++
  63. expect(c2()).toBe(2)
  64. expect(c1()).toBe(1)
  65. })
  66. it('should trigger autorun when chained', () => {
  67. const value: any = observable({ foo: 0 })
  68. const getter1 = jest.fn(() => value.foo)
  69. const getter2 = jest.fn(() => {
  70. return c1() + 1
  71. })
  72. const c1 = computed(getter1)
  73. const c2 = computed(getter2)
  74. let dummy
  75. autorun(() => {
  76. dummy = c2()
  77. })
  78. expect(dummy).toBe(1)
  79. expect(getter1).toHaveBeenCalledTimes(1)
  80. expect(getter2).toHaveBeenCalledTimes(1)
  81. value.foo++
  82. expect(dummy).toBe(2)
  83. // should not result in duplicate calls
  84. expect(getter1).toHaveBeenCalledTimes(2)
  85. expect(getter2).toHaveBeenCalledTimes(2)
  86. })
  87. it('should trigger autorun when chained (mixed invocations)', () => {
  88. const value: any = observable({ foo: 0 })
  89. const getter1 = jest.fn(() => value.foo)
  90. const getter2 = jest.fn(() => {
  91. return c1() + 1
  92. })
  93. const c1 = computed(getter1)
  94. const c2 = computed(getter2)
  95. let dummy
  96. autorun(() => {
  97. dummy = c1() + c2()
  98. })
  99. expect(dummy).toBe(1)
  100. expect(getter1).toHaveBeenCalledTimes(1)
  101. expect(getter2).toHaveBeenCalledTimes(1)
  102. value.foo++
  103. expect(dummy).toBe(3)
  104. // should not result in duplicate calls
  105. expect(getter1).toHaveBeenCalledTimes(2)
  106. expect(getter2).toHaveBeenCalledTimes(2)
  107. })
  108. it('should no longer update when stopped', () => {
  109. const value: any = observable({})
  110. const cValue = computed(() => value.foo)
  111. let dummy
  112. autorun(() => {
  113. dummy = cValue()
  114. })
  115. expect(dummy).toBe(undefined)
  116. value.foo = 1
  117. expect(dummy).toBe(1)
  118. stop(cValue.runner)
  119. value.foo = 2
  120. expect(dummy).toBe(1)
  121. })
  122. })