Results.utils.test.ts 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. import { describe, expect, it } from 'vitest'
  2. import {
  3. convertResultsToCSV,
  4. convertResultsToJSON,
  5. convertResultsToMarkdown,
  6. formatResults,
  7. getResultsHeaders,
  8. isLargeValue,
  9. } from './Results.utils'
  10. describe('Results.utils', () => {
  11. describe('formatResults', () => {
  12. it('should stringify object values', () => {
  13. const results = [{ id: 1, data: { nested: true } }]
  14. const formatted = formatResults(results)
  15. expect(formatted).toEqual([{ id: 1, data: '{"nested":true}' }])
  16. })
  17. it('should stringify array values', () => {
  18. const results = [{ id: 1, tags: ['a', 'b'] }]
  19. const formatted = formatResults(results)
  20. expect(formatted).toEqual([{ id: 1, tags: '["a","b"]' }])
  21. })
  22. it('should stringify null values', () => {
  23. const results = [{ id: 1, value: null }]
  24. const formatted = formatResults(results)
  25. expect(formatted).toEqual([{ id: 1, value: 'null' }])
  26. })
  27. it('should leave primitive values unchanged', () => {
  28. const results = [{ name: 'test', count: 42, active: true }]
  29. const formatted = formatResults(results)
  30. expect(formatted).toEqual([{ name: 'test', count: 42, active: true }])
  31. })
  32. it('should return empty array for empty input', () => {
  33. expect(formatResults([])).toEqual([])
  34. })
  35. })
  36. describe('convertResultsToMarkdown', () => {
  37. it('should return undefined for empty results', () => {
  38. expect(convertResultsToMarkdown([])).toBeUndefined()
  39. })
  40. it('should convert results to a markdown table', () => {
  41. const results = [
  42. { id: 1, name: 'Alice' },
  43. { id: 2, name: 'Bob' },
  44. ]
  45. const md = convertResultsToMarkdown(results)
  46. expect(md).toContain('| id | name |')
  47. expect(md).toContain('| 1 | Alice |')
  48. expect(md).toContain('| 2 | Bob |')
  49. })
  50. it('should stringify nested objects in markdown output', () => {
  51. const results = [{ id: 1, meta: { role: 'admin' } }]
  52. const md = convertResultsToMarkdown(results)
  53. expect(md).toContain('{"role":"admin"}')
  54. })
  55. })
  56. describe('convertResultsToJSON', () => {
  57. it('should return undefined for empty results', () => {
  58. expect(convertResultsToJSON([])).toBeUndefined()
  59. })
  60. it('should return formatted JSON string', () => {
  61. const results = [{ id: 1, name: 'Alice' }]
  62. const json = convertResultsToJSON(results)
  63. expect(json).toBe(JSON.stringify(results, null, 2))
  64. })
  65. it('should preserve nested object structure', () => {
  66. const results = [{ id: 1, meta: { role: 'admin' } }]
  67. const json = convertResultsToJSON(results)
  68. const parsed = JSON.parse(json!)
  69. expect(parsed[0].meta.role).toBe('admin')
  70. })
  71. })
  72. describe('getResultsHeaders', () => {
  73. it('should return undefined for empty results', () => {
  74. expect(getResultsHeaders([])).toBeUndefined()
  75. })
  76. it('should return keys from the first row', () => {
  77. const results = [{ id: 1, name: 'Alice' }]
  78. expect(getResultsHeaders(results)).toEqual(['id', 'name'])
  79. })
  80. it('should preserve key order from the first row', () => {
  81. const results = [{ z: 1, a: 2, m: 3 }]
  82. expect(getResultsHeaders(results)).toEqual(['z', 'a', 'm'])
  83. })
  84. it('should use only the first row for headers', () => {
  85. const results = [{ id: 1 }, { id: 2, extra: 'bonus' }]
  86. expect(getResultsHeaders(results)).toEqual(['id'])
  87. })
  88. })
  89. describe('isLargeValue', () => {
  90. it('returns false for null', () => {
  91. expect(isLargeValue(null)).toBe(false)
  92. })
  93. it('returns false for undefined', () => {
  94. expect(isLargeValue(undefined)).toBe(false)
  95. })
  96. it('returns false for an empty string', () => {
  97. expect(isLargeValue('')).toBe(false)
  98. })
  99. it('returns false for a short string under the threshold', () => {
  100. expect(isLargeValue('hello')).toBe(false)
  101. })
  102. it('returns false for a string at the 60-char boundary', () => {
  103. expect(isLargeValue('a'.repeat(60))).toBe(false)
  104. })
  105. it('returns true for a string just over the 60-char threshold', () => {
  106. expect(isLargeValue('a'.repeat(61))).toBe(true)
  107. })
  108. it('returns true for a short string containing a newline', () => {
  109. expect(isLargeValue('hello\nworld')).toBe(true)
  110. })
  111. it('returns true for an object', () => {
  112. expect(isLargeValue({ a: 1 })).toBe(true)
  113. })
  114. it('returns true for an array', () => {
  115. expect(isLargeValue([1, 2, 3])).toBe(true)
  116. })
  117. it('returns false for a number', () => {
  118. expect(isLargeValue(42)).toBe(false)
  119. })
  120. it('returns false for a boolean', () => {
  121. expect(isLargeValue(true)).toBe(false)
  122. })
  123. })
  124. describe('convertResultsToCSV', () => {
  125. it('should return undefined for empty results', () => {
  126. expect(convertResultsToCSV([])).toBeUndefined()
  127. })
  128. it('should include header row from first result keys', () => {
  129. const results = [{ id: 1, name: 'Alice' }]
  130. const csv = convertResultsToCSV(results)
  131. expect(csv).toContain('id,name')
  132. })
  133. it('should include data rows', () => {
  134. const results = [
  135. { id: 1, name: 'Alice' },
  136. { id: 2, name: 'Bob' },
  137. ]
  138. const csv = convertResultsToCSV(results)
  139. expect(csv).toContain('Alice')
  140. expect(csv).toContain('Bob')
  141. })
  142. it('should stringify object values', () => {
  143. const results = [{ id: 1, meta: { role: 'admin' } }]
  144. const csv = convertResultsToCSV(results)
  145. // CSV wraps values containing special chars in quotes and escapes inner quotes
  146. expect(csv).toContain('"{""role"":""admin""}"')
  147. })
  148. it('should stringify array values', () => {
  149. const results = [{ id: 1, tags: ['a', 'b'] }]
  150. const csv = convertResultsToCSV(results)
  151. // CSV wraps values containing special chars in quotes and escapes inner quotes
  152. expect(csv).toContain('"[""a"",""b""]"')
  153. })
  154. it('should stringify null values', () => {
  155. const results = [{ id: 1, value: null }]
  156. const csv = convertResultsToCSV(results)
  157. expect(csv).toContain('null')
  158. })
  159. it('should preserve column order from first row', () => {
  160. const results = [{ z: 1, a: 2, m: 3 }]
  161. const csv = convertResultsToCSV(results)
  162. // split on CRLF line endings produced by papaparse
  163. const headerRow = csv!.split('\r\n')[0]
  164. expect(headerRow).toBe('z,a,m')
  165. })
  166. })
  167. })