toDisplayString.spec.ts 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /**
  2. * @vitest-environment jsdom
  3. */
  4. import { computed, ref } from '@vue/reactivity'
  5. import { toDisplayString } from '../src'
  6. describe('toDisplayString', () => {
  7. test('nullish values', () => {
  8. expect(toDisplayString(null)).toBe('')
  9. expect(toDisplayString(undefined)).toBe('')
  10. })
  11. test('primitive values', () => {
  12. expect(toDisplayString(0)).toBe('0')
  13. expect(toDisplayString(1)).toBe('1')
  14. expect(toDisplayString(NaN)).toBe('NaN')
  15. expect(toDisplayString(true)).toBe('true')
  16. expect(toDisplayString(false)).toBe('false')
  17. expect(toDisplayString('hello')).toBe('hello')
  18. })
  19. test('primitive values in refs', () => {
  20. expect(toDisplayString(ref(0))).toBe('0')
  21. expect(toDisplayString(ref(1))).toBe('1')
  22. expect(toDisplayString(ref(NaN))).toBe('NaN')
  23. expect(toDisplayString(ref(true))).toBe('true')
  24. expect(toDisplayString(ref(false))).toBe('false')
  25. expect(toDisplayString(ref('hello'))).toBe('hello')
  26. })
  27. test('symbol values', () => {
  28. expect(toDisplayString(Symbol('hello'))).toBe('Symbol(hello)')
  29. expect(toDisplayString(ref(Symbol('hello')))).toBe('Symbol(hello)')
  30. })
  31. test('Object and Arrays', () => {
  32. const obj = { foo: 123 }
  33. expect(toDisplayString(obj)).toBe(JSON.stringify(obj, null, 2))
  34. const arr = [obj]
  35. expect(toDisplayString(arr)).toBe(JSON.stringify(arr, null, 2))
  36. const objWithToStringOverride = {
  37. foo: 555,
  38. toString() {
  39. return 'override'
  40. },
  41. }
  42. expect(toDisplayString(objWithToStringOverride)).toBe('override')
  43. const objWithNonInvokableToString = {
  44. foo: 555,
  45. toString: null,
  46. }
  47. expect(toDisplayString(objWithNonInvokableToString)).toBe(
  48. `{
  49. "foo": 555,
  50. "toString": null
  51. }`,
  52. )
  53. // object created from null does not have .toString in its prototype
  54. const nullObjectWithoutToString = Object.create(null)
  55. nullObjectWithoutToString.bar = 1
  56. expect(toDisplayString(nullObjectWithoutToString)).toBe(
  57. `{
  58. "bar": 1
  59. }`,
  60. )
  61. // array toString override is ignored
  62. const arrWithToStringOverride = [1, 2, 3]
  63. arrWithToStringOverride.toString = () =>
  64. 'override for array is not supported'
  65. expect(toDisplayString(arrWithToStringOverride)).toBe(
  66. `[
  67. 1,
  68. 2,
  69. 3
  70. ]`,
  71. )
  72. })
  73. test('refs', () => {
  74. const n = ref(1)
  75. const np = computed(() => n.value + 1)
  76. expect(
  77. toDisplayString({
  78. n,
  79. np,
  80. }),
  81. ).toBe(JSON.stringify({ n: 1, np: 2 }, null, 2))
  82. })
  83. test('objects with custom toString', () => {
  84. class TestClass {
  85. toString() {
  86. return 'foo'
  87. }
  88. }
  89. const instance = new TestClass()
  90. expect(toDisplayString(instance)).toBe('foo')
  91. const obj = { toString: () => 'bar' }
  92. expect(toDisplayString(obj)).toBe('bar')
  93. })
  94. test('native objects', () => {
  95. const div = document.createElement('div')
  96. expect(toDisplayString(div)).toMatch('[object HTMLDivElement]')
  97. expect(toDisplayString({ div })).toMatchInlineSnapshot(`
  98. "{
  99. "div": "[object HTMLDivElement]"
  100. }"
  101. `)
  102. })
  103. test('Map and Set', () => {
  104. const m = new Map<any, any>([
  105. [1, 'foo'],
  106. [{ baz: 1 }, { foo: 'bar', qux: 2 }],
  107. ])
  108. const s = new Set<any>([1, { foo: 'bar' }, m])
  109. expect(toDisplayString(m)).toMatchInlineSnapshot(`
  110. "{
  111. "Map(2)": {
  112. "1 =>": "foo",
  113. "[object Object] =>": {
  114. "foo": "bar",
  115. "qux": 2
  116. }
  117. }
  118. }"
  119. `)
  120. expect(toDisplayString(s)).toMatchInlineSnapshot(`
  121. "{
  122. "Set(3)": [
  123. 1,
  124. {
  125. "foo": "bar"
  126. },
  127. {
  128. "Map(2)": {
  129. "1 =>": "foo",
  130. "[object Object] =>": {
  131. "foo": "bar",
  132. "qux": 2
  133. }
  134. }
  135. }
  136. ]
  137. }"
  138. `)
  139. expect(
  140. toDisplayString({
  141. m,
  142. s,
  143. }),
  144. ).toMatchInlineSnapshot(`
  145. "{
  146. "m": {
  147. "Map(2)": {
  148. "1 =>": "foo",
  149. "[object Object] =>": {
  150. "foo": "bar",
  151. "qux": 2
  152. }
  153. }
  154. },
  155. "s": {
  156. "Set(3)": [
  157. 1,
  158. {
  159. "foo": "bar"
  160. },
  161. {
  162. "Map(2)": {
  163. "1 =>": "foo",
  164. "[object Object] =>": {
  165. "foo": "bar",
  166. "qux": 2
  167. }
  168. }
  169. }
  170. ]
  171. }
  172. }"
  173. `)
  174. })
  175. //#9727
  176. test('Map with Symbol keys', () => {
  177. const m = new Map<any, any>([
  178. [Symbol(), 'foo'],
  179. [Symbol(), 'bar'],
  180. [Symbol('baz'), 'baz'],
  181. ])
  182. expect(toDisplayString(m)).toMatchInlineSnapshot(`
  183. "{
  184. "Map(3)": {
  185. "Symbol(0) =>": "foo",
  186. "Symbol(1) =>": "bar",
  187. "Symbol(baz) =>": "baz"
  188. }
  189. }"
  190. `)
  191. // confirming the symbol renders Symbol(foo)
  192. expect(toDisplayString(new Map([[Symbol('foo'), 'foo']]))).toContain(
  193. String(Symbol('foo')),
  194. )
  195. })
  196. test('Set with Symbol values', () => {
  197. const s = new Set([Symbol('foo'), Symbol('bar'), Symbol()])
  198. expect(toDisplayString(s)).toMatchInlineSnapshot(`
  199. "{
  200. "Set(3)": [
  201. "Symbol(foo)",
  202. "Symbol(bar)",
  203. "Symbol()"
  204. ]
  205. }"
  206. `)
  207. })
  208. test('Object with Symbol values', () => {
  209. expect(toDisplayString({ foo: Symbol('x'), bar: Symbol() }))
  210. .toMatchInlineSnapshot(`
  211. "{
  212. "foo": "Symbol(x)",
  213. "bar": "Symbol()"
  214. }"
  215. `)
  216. })
  217. })