shallowReadonly.spec.ts 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. import { isReactive, isReadonly, readonly, shallowReadonly } from '../src'
  2. describe('reactivity/shallowReadonly', () => {
  3. test('should not make non-reactive properties reactive', () => {
  4. const props = shallowReadonly({ n: { foo: 1 } })
  5. expect(isReactive(props.n)).toBe(false)
  6. })
  7. test('should make root level properties readonly', () => {
  8. const props = shallowReadonly({ n: 1 })
  9. // @ts-expect-error
  10. props.n = 2
  11. expect(props.n).toBe(1)
  12. expect(
  13. `Set operation on key "n" failed: target is readonly.`,
  14. ).toHaveBeenWarned()
  15. })
  16. // to retain 2.x behavior.
  17. test('should NOT make nested properties readonly', () => {
  18. const props = shallowReadonly({ n: { foo: 1 } })
  19. props.n.foo = 2
  20. expect(props.n.foo).toBe(2)
  21. expect(
  22. `Set operation on key "foo" failed: target is readonly.`,
  23. ).not.toHaveBeenWarned()
  24. })
  25. // #2843
  26. test('should differentiate from normal readonly calls', () => {
  27. const original = { foo: {} }
  28. const shallowProxy = shallowReadonly(original)
  29. const reactiveProxy = readonly(original)
  30. expect(shallowProxy).not.toBe(reactiveProxy)
  31. expect(isReadonly(shallowProxy.foo)).toBe(false)
  32. expect(isReadonly(reactiveProxy.foo)).toBe(true)
  33. })
  34. describe('collection/Map', () => {
  35. ;[Map, WeakMap].forEach(Collection => {
  36. test('should make the map/weak-map readonly', () => {
  37. const key = {}
  38. const val = { foo: 1 }
  39. const original = new Collection([[key, val]])
  40. const sroMap = shallowReadonly(original)
  41. expect(isReadonly(sroMap)).toBe(true)
  42. expect(isReactive(sroMap)).toBe(false)
  43. expect(sroMap.get(key)).toBe(val)
  44. sroMap.set(key, {} as any)
  45. expect(
  46. `Set operation on key "[object Object]" failed: target is readonly.`,
  47. ).toHaveBeenWarned()
  48. })
  49. test('should not make nested values readonly', () => {
  50. const key = {}
  51. const val = { foo: 1 }
  52. const original = new Collection([[key, val]])
  53. const sroMap = shallowReadonly(original)
  54. expect(isReadonly(sroMap.get(key))).toBe(false)
  55. expect(isReactive(sroMap.get(key))).toBe(false)
  56. sroMap.get(key)!.foo = 2
  57. expect(
  58. `Set operation on key "foo" failed: target is readonly.`,
  59. ).not.toHaveBeenWarned()
  60. })
  61. })
  62. test('should not make the value generated by the iterable method readonly', () => {
  63. const key = {}
  64. const val = { foo: 1 }
  65. const original = new Map([[key, val]])
  66. const sroMap = shallowReadonly(original)
  67. const values1 = [...sroMap.values()]
  68. const values2 = [...sroMap.entries()]
  69. expect(isReadonly(values1[0])).toBe(false)
  70. expect(isReactive(values1[0])).toBe(false)
  71. expect(values1[0]).toBe(val)
  72. values1[0].foo = 2
  73. expect(
  74. `Set operation on key "foo" failed: target is readonly.`,
  75. ).not.toHaveBeenWarned()
  76. expect(isReadonly(values2[0][1])).toBe(false)
  77. expect(isReactive(values2[0][1])).toBe(false)
  78. expect(values2[0][1]).toBe(val)
  79. values2[0][1].foo = 2
  80. expect(
  81. `Set operation on key "foo" failed: target is readonly.`,
  82. ).not.toHaveBeenWarned()
  83. })
  84. test('should not make the value generated by the forEach method readonly', () => {
  85. const val = { foo: 1 }
  86. const original = new Map([['key', val]])
  87. const sroMap = shallowReadonly(original)
  88. sroMap.forEach(val => {
  89. expect(isReadonly(val)).toBe(false)
  90. expect(isReactive(val)).toBe(false)
  91. expect(val).toBe(val)
  92. val.foo = 2
  93. expect(
  94. `Set operation on key "foo" failed: target is readonly.`,
  95. ).not.toHaveBeenWarned()
  96. })
  97. })
  98. test('should return undefined from Map.clear() call', () => {
  99. const sroMap = shallowReadonly(new Map())
  100. expect(sroMap.clear()).toBeUndefined()
  101. expect(`Clear operation failed: target is readonly.`).toHaveBeenWarned()
  102. })
  103. })
  104. describe('collection/Set', () => {
  105. test('should make the set/weak-set readonly', () => {
  106. ;[Set, WeakSet].forEach(Collection => {
  107. const obj = { foo: 1 }
  108. const original = new Collection([obj])
  109. const sroSet = shallowReadonly(original)
  110. expect(isReadonly(sroSet)).toBe(true)
  111. expect(isReactive(sroSet)).toBe(false)
  112. expect(sroSet.has(obj)).toBe(true)
  113. sroSet.add({} as any)
  114. expect(
  115. `Add operation on key "[object Object]" failed: target is readonly.`,
  116. ).toHaveBeenWarned()
  117. })
  118. })
  119. test('should not make nested values readonly', () => {
  120. const obj = { foo: 1 }
  121. const original = new Set([obj])
  122. const sroSet = shallowReadonly(original)
  123. const values = [...sroSet.values()]
  124. expect(values[0]).toBe(obj)
  125. expect(isReadonly(values[0])).toBe(false)
  126. expect(isReactive(values[0])).toBe(false)
  127. sroSet.add({} as any)
  128. expect(
  129. `Add operation on key "[object Object]" failed: target is readonly.`,
  130. ).toHaveBeenWarned()
  131. values[0].foo = 2
  132. expect(
  133. `Set operation on key "foo" failed: target is readonly.`,
  134. ).not.toHaveBeenWarned()
  135. })
  136. test('should not make the value generated by the iterable method readonly', () => {
  137. const val = { foo: 1 }
  138. const original = new Set([val])
  139. const sroSet = shallowReadonly(original)
  140. const values1 = [...sroSet.values()]
  141. const values2 = [...sroSet.entries()]
  142. expect(isReadonly(values1[0])).toBe(false)
  143. expect(isReactive(values1[0])).toBe(false)
  144. expect(values1[0]).toBe(val)
  145. values1[0].foo = 2
  146. expect(
  147. `Set operation on key "foo" failed: target is readonly.`,
  148. ).not.toHaveBeenWarned()
  149. expect(isReadonly(values2[0][1])).toBe(false)
  150. expect(isReactive(values2[0][1])).toBe(false)
  151. expect(values2[0][1]).toBe(val)
  152. values2[0][1].foo = 2
  153. expect(
  154. `Set operation on key "foo" failed: target is readonly.`,
  155. ).not.toHaveBeenWarned()
  156. })
  157. test('should not make the value generated by the forEach method readonly', () => {
  158. const val = { foo: 1 }
  159. const original = new Set([val])
  160. const sroSet = shallowReadonly(original)
  161. sroSet.forEach(val => {
  162. expect(isReadonly(val)).toBe(false)
  163. expect(isReactive(val)).toBe(false)
  164. expect(val).toBe(val)
  165. val.foo = 2
  166. expect(
  167. `Set operation on key "foo" failed: target is readonly.`,
  168. ).not.toHaveBeenWarned()
  169. })
  170. })
  171. test('should return undefined from Set.clear() call', () => {
  172. const sroSet = shallowReadonly(new Set())
  173. expect(sroSet.clear()).toBeUndefined()
  174. expect(`Clear operation failed: target is readonly.`).toHaveBeenWarned()
  175. })
  176. })
  177. })