SpreadsheetImport.utils.test.ts 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import { describe, expect, test } from 'vitest'
  2. import {
  3. inferColumnType,
  4. parseSpreadsheetText,
  5. } from '@/components/interfaces/TableGridEditor/SidePanelEditor/SpreadsheetImport/SpreadsheetImport.utils'
  6. describe('SpreadsheetImport.utils: inferColumnType', () => {
  7. test('should default column type to text if no rows to infer from', () => {
  8. const mockData: Array<unknown> = []
  9. const type = inferColumnType('id', mockData)
  10. expect(type).toBe('text')
  11. })
  12. test('should default column type to text if the first row has no data to infer from', () => {
  13. const mockData = [{ name: 'bob', age: '42' }]
  14. const type = inferColumnType('id', mockData)
  15. expect(type).toBe('text')
  16. })
  17. test('should default column type to text if the first row data value is null', () => {
  18. const mockData = [{ id: 'null', name: 'bob', age: '42' }]
  19. const type = inferColumnType('id', mockData)
  20. expect(type).toBe('text')
  21. })
  22. test('should infer integer types correctly', () => {
  23. const mockData = [{ name: 'bob', age: '42' }]
  24. const type = inferColumnType('age', mockData)
  25. expect(type).toBe('int8')
  26. })
  27. test('should infer float types correctly', () => {
  28. const mockData = [{ name: 'bob', height: '161.72' }]
  29. const type = inferColumnType('height', mockData)
  30. expect(type).toBe('float8')
  31. })
  32. test('should infer boolean types correctly', () => {
  33. const mockData1 = [{ name: 'bob', height: '161.72', isWorking: 'true' }]
  34. const type1 = inferColumnType('isWorking', mockData1)
  35. expect(type1).toBe('bool')
  36. const mockData2 = [{ name: 'bob', height: '161.72', isRetired: 'false' }]
  37. const type2 = inferColumnType('isRetired', mockData2)
  38. expect(type2).toBe('bool')
  39. })
  40. test('should infer boolean type for a supposed boolean column if one of the rows has a null value', () => {
  41. const mockData3 = [
  42. { name: 'bob', height: '161.72', isRetired: 'false' },
  43. { name: 'bob', height: '161.72', isRetired: 'true' },
  44. { name: 'bob', height: '161.72', isRetired: null },
  45. ]
  46. const type3 = inferColumnType('isRetired', mockData3)
  47. expect(type3).toBe('bool')
  48. })
  49. test('should infer objects as jsonb types correctly', () => {
  50. const mockData = [{ name: 'bob', metadata: '{}' }]
  51. const type = inferColumnType('metadata', mockData)
  52. expect(type).toBe('jsonb')
  53. })
  54. test('should infer date type correctly', () => {
  55. const mockData4 = [
  56. { event: 'christmas', date: '2022-12-25 17:45:23 UTC' },
  57. { event: 'christmas', date: '2022-12-25' },
  58. { event: 'christmas', date: '2022-12-25T12:03:40Z' },
  59. { event: 'christmas', date: new Date() },
  60. { event: 'christmas', date: new Date().toISOString() },
  61. { event: 'christmas', date: 1410715640579 },
  62. { event: 'christmas', date: '25 Dec 2022' },
  63. { event: 'christmas', date: 'Dec 25 2022' },
  64. ]
  65. const type4 = inferColumnType('date', mockData4)
  66. expect(type4).toBe('timestamptz')
  67. })
  68. })
  69. interface SampleRow {
  70. name: string
  71. age: string | null
  72. city?: string | null
  73. }
  74. describe('SpreadsheetImport.utils: parseSpreadsheetText', () => {
  75. test('should keep empty cells as empty strings if no headers given', async () => {
  76. const csv = `name,age\nJohn,25\nJane,`
  77. const { rows } = await parseSpreadsheetText({ text: csv, emptyStringAsNullHeaders: [] })
  78. expect((rows[1] as SampleRow).age).toBe('')
  79. })
  80. test('should convert empty cells to null when treatEmptyAsNull is true', async () => {
  81. const csv = `name,age\nJohn,25\nJane,`
  82. const { rows } = await parseSpreadsheetText({ text: csv, emptyStringAsNullHeaders: undefined })
  83. expect((rows[1] as SampleRow).age).toBeNull()
  84. })
  85. test('should not affect non-empty values when treatEmptyAsNull is true', async () => {
  86. const csv = `name,age\nJohn,25\nJane,`
  87. const { rows } = await parseSpreadsheetText({ text: csv, emptyStringAsNullHeaders: undefined })
  88. expect((rows[0] as SampleRow).name).toBe('John')
  89. expect((rows[0] as SampleRow).age).toBe('25')
  90. })
  91. test('should handle multiple empty cells across columns when treatEmptyAsNull is true', async () => {
  92. const csv = `name,age,city\nJohn,,\nJane,30,`
  93. const { rows } = await parseSpreadsheetText({ text: csv, emptyStringAsNullHeaders: undefined })
  94. expect((rows[0] as SampleRow).age).toBeNull()
  95. expect((rows[0] as SampleRow).city).toBeNull()
  96. expect((rows[1] as SampleRow).age).toBe('30')
  97. expect((rows[1] as SampleRow).city).toBeNull()
  98. })
  99. test('should return correct headers regardless of treatEmptyAsNull', async () => {
  100. const csv = `name,age\nJohn,25`
  101. const { headers } = await parseSpreadsheetText({
  102. text: csv,
  103. emptyStringAsNullHeaders: undefined,
  104. })
  105. expect(headers).toEqual(['name', 'age'])
  106. })
  107. })