| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- import { describe, expect, it } from 'vitest'
- import { computeYAxisDomain, normalizeStackedSeriesData } from './Charts.utils'
- const IOPS_DATA = [
- { timestamp: 1, disk_iops_write: 1200, disk_iops_read: 24203, disk_iops_max: 25000 },
- { timestamp: 2, disk_iops_write: 400, disk_iops_read: 3200, disk_iops_max: 25000 },
- { timestamp: 3, disk_iops_write: 100, disk_iops_read: 900, disk_iops_max: 25000 },
- ]
- const IOPS_VISIBLE = ['disk_iops_write', 'disk_iops_read']
- describe('computeYAxisDomain', () => {
- describe('percentage charts with max line hidden', () => {
- it('returns [0, yMaxFromVisible] to zoom in on the data', () => {
- expect(
- computeYAxisDomain({
- isPercentage: true,
- showMaxValue: false,
- yMaxFromVisible: 75,
- maxAttributeKey: 'cpu_usage_max',
- showMaxLine: false,
- data: [{ cpu_busy: 75, cpu_usage_max: 100 }],
- visibleAttributeNames: ['cpu_busy'],
- })
- ).toEqual([0, 75])
- })
- it('still zooms in even when a maxAttributeKey is present', () => {
- expect(
- computeYAxisDomain({
- isPercentage: true,
- showMaxValue: false,
- yMaxFromVisible: 60,
- maxAttributeKey: 'cpu_usage_max',
- showMaxLine: true,
- data: [{ cpu_busy: 60, cpu_usage_max: 100 }],
- visibleAttributeNames: ['cpu_busy'],
- })
- ).toEqual([0, 60])
- })
- })
- describe('no max reference line', () => {
- it('returns auto when maxAttributeKey is undefined', () => {
- expect(
- computeYAxisDomain({
- isPercentage: false,
- showMaxValue: false,
- yMaxFromVisible: 5000,
- maxAttributeKey: undefined,
- showMaxLine: false,
- data: IOPS_DATA,
- visibleAttributeNames: IOPS_VISIBLE,
- })
- ).toEqual(['auto', 'auto'])
- })
- it('returns auto when showMaxLine is false', () => {
- expect(
- computeYAxisDomain({
- isPercentage: false,
- showMaxValue: true,
- yMaxFromVisible: 5000,
- maxAttributeKey: 'disk_iops_max',
- showMaxLine: false,
- data: IOPS_DATA,
- visibleAttributeNames: IOPS_VISIBLE,
- })
- ).toEqual(['auto', 'auto'])
- })
- })
- describe('max reference line not yet loaded (value is 0)', () => {
- it('returns auto when diskConfig has not loaded and reference line value is 0', () => {
- const dataWithZeroMax = IOPS_DATA.map((p) => ({ ...p, disk_iops_max: 0 }))
- expect(
- computeYAxisDomain({
- isPercentage: false,
- showMaxValue: true,
- yMaxFromVisible: 5000,
- maxAttributeKey: 'disk_iops_max',
- showMaxLine: true,
- data: dataWithZeroMax,
- visibleAttributeNames: IOPS_VISIBLE,
- })
- ).toEqual(['auto', 'auto'])
- })
- })
- describe('explicit domain with reference line', () => {
- it('uses the reference line value when bars stay below it', () => {
- // All stacked bar totals (1000, 500) are well below maxRefValue (25000)
- expect(
- computeYAxisDomain({
- isPercentage: false,
- showMaxValue: true,
- yMaxFromVisible: 800,
- maxAttributeKey: 'disk_iops_max',
- showMaxLine: true,
- data: [
- { disk_iops_write: 400, disk_iops_read: 600, disk_iops_max: 25000 },
- { disk_iops_write: 200, disk_iops_read: 300, disk_iops_max: 25000 },
- ],
- visibleAttributeNames: IOPS_VISIBLE,
- })
- ).toEqual([0, 25000])
- })
- it('uses the stacked bar total when it exceeds the reference line', () => {
- // Stacked total at first point: 24203 + 1200 = 25403 > 25000
- expect(
- computeYAxisDomain({
- isPercentage: false,
- showMaxValue: true,
- yMaxFromVisible: 24203,
- maxAttributeKey: 'disk_iops_max',
- showMaxLine: true,
- data: IOPS_DATA,
- visibleAttributeNames: IOPS_VISIBLE,
- })
- ).toEqual([0, 25403])
- })
- it('domain min is always 0', () => {
- const [min] = computeYAxisDomain({
- isPercentage: false,
- showMaxValue: true,
- yMaxFromVisible: 100,
- maxAttributeKey: 'disk_iops_max',
- showMaxLine: true,
- data: IOPS_DATA,
- visibleAttributeNames: IOPS_VISIBLE,
- }) as [number, number]
- expect(min).toBe(0)
- })
- it('works for database connections chart (single bar series, no stacking)', () => {
- const data = [
- { pg_stat_database_num_backends: 45, max_db_connections: 60 },
- { pg_stat_database_num_backends: 52, max_db_connections: 60 },
- ]
- expect(
- computeYAxisDomain({
- isPercentage: false,
- showMaxValue: true,
- yMaxFromVisible: 52,
- maxAttributeKey: 'max_db_connections',
- showMaxLine: true,
- data,
- visibleAttributeNames: ['pg_stat_database_num_backends'],
- })
- ).toEqual([0, 60])
- })
- it('handles non-numeric values in data gracefully', () => {
- const data = [
- { disk_iops_write: 'bad', disk_iops_read: null, disk_iops_max: 25000 },
- { disk_iops_write: 500, disk_iops_read: 1000, disk_iops_max: 25000 },
- ]
- expect(
- computeYAxisDomain({
- isPercentage: false,
- showMaxValue: true,
- yMaxFromVisible: 1000,
- maxAttributeKey: 'disk_iops_max',
- showMaxLine: true,
- data: data as Record<string, unknown>[],
- visibleAttributeNames: IOPS_VISIBLE,
- })
- ).toEqual([0, 25000])
- })
- })
- })
- describe('normalizeStackedSeriesData', () => {
- it('normalizes each stacked point to 100%', () => {
- const normalized = normalizeStackedSeriesData({
- data: [{ system: 25, user: 25, idle: 100 }],
- attributeNames: ['system', 'user', 'idle'],
- })
- expect(normalized[0].system).toBeCloseTo(16.6666666667)
- expect(normalized[0].user).toBeCloseTo(16.6666666667)
- expect(normalized[0].idle).toBeCloseTo(66.6666666666)
- expect(
- Number(normalized[0].system) + Number(normalized[0].user) + Number(normalized[0].idle)
- ).toBeCloseTo(100)
- })
- it('leaves empty stacks unchanged', () => {
- const empty = [{ system: 0, user: 0, idle: 0 }]
- expect(
- normalizeStackedSeriesData({
- data: empty,
- attributeNames: ['system', 'user', 'idle'],
- })
- ).toEqual(empty)
- })
- it('leaves data unchanged when attributeNames is empty', () => {
- const data = [{ system: 50, user: 30, timestamp: 1000 }]
- expect(
- normalizeStackedSeriesData({
- data,
- attributeNames: [],
- })
- ).toEqual(data)
- })
- it('preserves non-stacked keys (timestamps, metadata) unchanged', () => {
- const data = [{ system: 60, user: 80, period_start: '2024-01-01', timestamp: 1000 }]
- const normalized = normalizeStackedSeriesData({
- data,
- attributeNames: ['system', 'user'],
- })
- expect(normalized[0].period_start).toBe('2024-01-01')
- expect(normalized[0].timestamp).toBe(1000)
- expect(Number(normalized[0].system) + Number(normalized[0].user)).toBeCloseTo(100)
- })
- })
|