Charts.utils.test.ts 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. import { renderHook } from '@testing-library/react'
  2. import { describe, expect, it, test } from 'vitest'
  3. import {
  4. compactNumberFormatter,
  5. formatPercentage,
  6. isFloat,
  7. numberFormatter,
  8. precisionFormatter,
  9. useStacked,
  10. } from '@/components/ui/Charts/Charts.utils'
  11. test('isFloat', () => {
  12. expect(isFloat(123)).toBe(false)
  13. expect(isFloat(123.123)).toBe(true)
  14. })
  15. describe('numberFormatter', () => {
  16. it('should format integers without decimals', () => {
  17. expect(numberFormatter(123)).toBe('123')
  18. expect(numberFormatter(1000)).toBe('1,000')
  19. })
  20. it('should format floats with default precision', () => {
  21. expect(numberFormatter(123.123)).toBe('123.12')
  22. expect(numberFormatter(123.456)).toBe('123.45')
  23. expect(numberFormatter(123.999)).toBe('123.99')
  24. expect(numberFormatter(123456.78)).toBe('123,456.78')
  25. })
  26. it('should show "<0.01" for small positive floats', () => {
  27. expect(numberFormatter(0.00123)).toBe('<0.01')
  28. expect(numberFormatter(0.005)).toBe('<0.01')
  29. })
  30. it('should show ">-0.01" for small negative floats', () => {
  31. expect(numberFormatter(-0.00123)).toBe('>-0.01')
  32. expect(numberFormatter(-0.005)).toBe('>-0.01')
  33. })
  34. it('should respect custom precision', () => {
  35. expect(numberFormatter(0.0001, 3)).toBe('<0.001')
  36. expect(numberFormatter(123.456789, 4)).toBe('123.4567')
  37. })
  38. })
  39. describe('precisionFormatter', () => {
  40. it('should format regular numbers with precision', () => {
  41. expect(precisionFormatter(123, 1)).toBe('123.0')
  42. expect(precisionFormatter(123, 2)).toBe('123.00')
  43. expect(precisionFormatter(123.123, 2)).toBe('123.12')
  44. expect(precisionFormatter(123.999, 2)).toBe('123.99')
  45. expect(precisionFormatter(123.12345, 4)).toBe('123.1234')
  46. expect(precisionFormatter(123456, 2)).toBe('123,456.00')
  47. expect(precisionFormatter(123456.78, 2)).toBe('123,456.78')
  48. })
  49. it('should show "<0.01" for small positive numbers below threshold', () => {
  50. expect(precisionFormatter(0.00123, 2)).toBe('<0.01')
  51. expect(precisionFormatter(0.005, 2)).toBe('<0.01')
  52. expect(precisionFormatter(0.009, 2)).toBe('<0.01')
  53. })
  54. it('should show ">-0.01" for small negative numbers below threshold', () => {
  55. expect(precisionFormatter(-0.00123, 2)).toBe('>-0.01')
  56. expect(precisionFormatter(-0.005, 2)).toBe('>-0.01')
  57. expect(precisionFormatter(-0.009, 2)).toBe('>-0.01')
  58. })
  59. it('should format numbers at or above threshold normally', () => {
  60. expect(precisionFormatter(0.01, 2)).toBe('0.01')
  61. expect(precisionFormatter(0.02, 2)).toBe('0.02')
  62. expect(precisionFormatter(-0.01, 2)).toBe('-0.01')
  63. expect(precisionFormatter(-0.02, 2)).toBe('-0.02')
  64. })
  65. it('should handle different precision values', () => {
  66. expect(precisionFormatter(0.0001, 3)).toBe('<0.001')
  67. expect(precisionFormatter(0.001, 3)).toBe('0.001')
  68. expect(precisionFormatter(-0.0001, 3)).toBe('>-0.001')
  69. })
  70. it('should handle precision 0', () => {
  71. expect(precisionFormatter(123.456, 0)).toBe('123')
  72. expect(precisionFormatter(0.5, 0)).toBe('1')
  73. })
  74. it('should format exactly zero normally', () => {
  75. expect(precisionFormatter(0, 2)).toBe('0.00')
  76. })
  77. })
  78. describe('formatPercentage', () => {
  79. it('should format 100 without decimals', () => {
  80. expect(formatPercentage(100, 2)).toBe('100%')
  81. expect(formatPercentage(100, 0)).toBe('100%')
  82. })
  83. it('should keep decimals for non-100 values', () => {
  84. expect(formatPercentage(99.99, 2)).toBe('99.99%')
  85. expect(formatPercentage(0.5, 2)).toBe('0.50%')
  86. })
  87. it('should use numberFormatter for integers below 100', () => {
  88. expect(formatPercentage(50, 2)).toBe('50%')
  89. expect(formatPercentage(1, 2)).toBe('1%')
  90. })
  91. })
  92. describe('compactNumberFormatter', () => {
  93. it('returns the number as-is below 1000', () => {
  94. expect(compactNumberFormatter(0)).toBe('0')
  95. expect(compactNumberFormatter(1)).toBe('1')
  96. expect(compactNumberFormatter(999)).toBe('999')
  97. })
  98. it('formats thousands with K suffix', () => {
  99. expect(compactNumberFormatter(1000)).toBe('1K')
  100. expect(compactNumberFormatter(1500)).toBe('1.5K')
  101. expect(compactNumberFormatter(64000)).toBe('64K')
  102. expect(compactNumberFormatter(999999)).toBe('1M') // rounds up
  103. })
  104. it('formats millions with M suffix', () => {
  105. expect(compactNumberFormatter(1_000_000)).toBe('1M')
  106. expect(compactNumberFormatter(1_500_000)).toBe('1.5M')
  107. expect(compactNumberFormatter(2_500_000)).toBe('2.5M')
  108. })
  109. it('formats billions with B suffix', () => {
  110. expect(compactNumberFormatter(1_000_000_000)).toBe('1B')
  111. expect(compactNumberFormatter(2_500_000_000)).toBe('2.5B')
  112. })
  113. it('handles negative numbers', () => {
  114. expect(compactNumberFormatter(-1000)).toBe('-1K')
  115. expect(compactNumberFormatter(-1_500_000)).toBe('-1.5M')
  116. })
  117. })
  118. test('useStacked', () => {
  119. const { result } = renderHook(() =>
  120. useStacked({
  121. data: [
  122. { label: 'a', x: 1, y: 2 },
  123. { label: 'b', x: 1, y: 3 },
  124. ] as unknown as Array<Record<string, number>>,
  125. xAxisKey: 'x',
  126. yAxisKey: 'y',
  127. stackKey: 'label',
  128. variant: 'percentages',
  129. })
  130. )
  131. expect(result.current).toMatchObject({
  132. stackedData: [
  133. {
  134. a: 2,
  135. b: 3,
  136. x: 1,
  137. },
  138. ],
  139. percentagesStackedData: [
  140. {
  141. a: 2 / 5,
  142. b: 3 / 5,
  143. x: 1,
  144. },
  145. ],
  146. })
  147. })