QueryBlock.utils.test.ts92 lines · main
| 1 | import { describe, expect, it } from 'vitest' |
| 2 | |
| 3 | import { computeYAxisWidth, formatYAxisTick } from './QueryBlock.utils' |
| 4 | |
| 5 | describe('formatYAxisTick', () => { |
| 6 | it('returns integers as-is when below 1000', () => { |
| 7 | expect(formatYAxisTick(0)).toBe('0') |
| 8 | expect(formatYAxisTick(1)).toBe('1') |
| 9 | expect(formatYAxisTick(999)).toBe('999') |
| 10 | }) |
| 11 | |
| 12 | it('abbreviates thousands with K', () => { |
| 13 | expect(formatYAxisTick(1_000)).toBe('1K') |
| 14 | expect(formatYAxisTick(5_000)).toBe('5K') |
| 15 | expect(formatYAxisTick(999_000)).toBe('999K') |
| 16 | }) |
| 17 | |
| 18 | it('rounds thousands to one decimal place', () => { |
| 19 | expect(formatYAxisTick(1_500)).toBe('1.5K') |
| 20 | expect(formatYAxisTick(55_300)).toBe('55.3K') |
| 21 | expect(formatYAxisTick(1_234)).toBe('1.2K') |
| 22 | }) |
| 23 | |
| 24 | it('abbreviates millions with M', () => { |
| 25 | expect(formatYAxisTick(1_000_000)).toBe('1M') |
| 26 | expect(formatYAxisTick(2_000_000)).toBe('2M') |
| 27 | }) |
| 28 | |
| 29 | it('rounds millions to one decimal place', () => { |
| 30 | expect(formatYAxisTick(1_500_000)).toBe('1.5M') |
| 31 | expect(formatYAxisTick(3_208_914)).toBe('3.2M') |
| 32 | }) |
| 33 | |
| 34 | it('handles values just below the million threshold', () => { |
| 35 | expect(formatYAxisTick(999_900)).toBe('999.9K') |
| 36 | }) |
| 37 | |
| 38 | it('handles negative values', () => { |
| 39 | expect(formatYAxisTick(-1_000)).toBe('-1K') |
| 40 | expect(formatYAxisTick(-1_500)).toBe('-1.5K') |
| 41 | expect(formatYAxisTick(-1_000_000)).toBe('-1M') |
| 42 | expect(formatYAxisTick(-999)).toBe('-999') |
| 43 | }) |
| 44 | |
| 45 | it('rounds small decimals to 2 places', () => { |
| 46 | expect(formatYAxisTick(0.456)).toBe('0.46') |
| 47 | expect(formatYAxisTick(0.1)).toBe('0.1') |
| 48 | expect(formatYAxisTick(-0.123)).toBe('-0.12') |
| 49 | }) |
| 50 | |
| 51 | it('rounds non-integer values between 1 and 1000 to 1 decimal place', () => { |
| 52 | expect(formatYAxisTick(1.25)).toBe('1.3') |
| 53 | expect(formatYAxisTick(99.9)).toBe('99.9') |
| 54 | expect(formatYAxisTick(5.0)).toBe('5') |
| 55 | }) |
| 56 | }) |
| 57 | |
| 58 | describe('computeYAxisWidth', () => { |
| 59 | const row = (v: number) => ({ val: v }) |
| 60 | |
| 61 | it('returns 52 for log scale regardless of data', () => { |
| 62 | expect(computeYAxisWidth([row(1_000_000)], 'val', { isLogScale: true })).toBe(52) |
| 63 | }) |
| 64 | |
| 65 | it('returns a fixed width for percentage data', () => { |
| 66 | const width = computeYAxisWidth([row(99)], 'val', { isPercentage: true }) |
| 67 | // "100" is the longest tick → (3+1)*8 = 32, floor at 36 |
| 68 | expect(width).toBe(36) |
| 69 | }) |
| 70 | |
| 71 | it('returns minimum 36 for small values', () => { |
| 72 | expect(computeYAxisWidth([row(5)], 'val')).toBe(36) |
| 73 | expect(computeYAxisWidth([], 'val')).toBe(36) |
| 74 | }) |
| 75 | |
| 76 | it('widens for large values', () => { |
| 77 | // formatYAxisTick(55_300) = "55.3K" (5 chars) → (5+1)*8 = 48 |
| 78 | expect(computeYAxisWidth([row(55_300)], 'val')).toBe(48) |
| 79 | }) |
| 80 | |
| 81 | it('uses absolute magnitude so negative data is handled correctly', () => { |
| 82 | const negWidth = computeYAxisWidth([row(-55_300)], 'val') |
| 83 | const posWidth = computeYAxisWidth([row(55_300)], 'val') |
| 84 | expect(negWidth).toBe(posWidth) |
| 85 | }) |
| 86 | |
| 87 | it('picks the largest magnitude across all rows', () => { |
| 88 | const data = [row(100), row(5_000), row(200)] |
| 89 | // max is 5000 → "5K" (2 chars) → (2+1)*8 = 24, floor at 36 |
| 90 | expect(computeYAxisWidth(data, 'val')).toBe(36) |
| 91 | }) |
| 92 | }) |