QueryBlock.utils.test.ts92 lines · main
1import { describe, expect, it } from 'vitest'
2
3import { computeYAxisWidth, formatYAxisTick } from './QueryBlock.utils'
4
5describe('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
58describe('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})