DatabaseInfrastructureSection.utils.test.ts309 lines · main
| 1 | import { describe, expect, it } from 'vitest' |
| 2 | |
| 3 | import { |
| 4 | parseConnectionsData, |
| 5 | parseInfrastructureMetrics, |
| 6 | parseNumericValue, |
| 7 | } from './DatabaseInfrastructureSection.utils' |
| 8 | import type { |
| 9 | InfraMonitoringMultiResponse, |
| 10 | InfraMonitoringSingleResponse, |
| 11 | } from '@/data/analytics/infra-monitoring-query' |
| 12 | |
| 13 | describe('parseNumericValue', () => { |
| 14 | it('returns number value as-is', () => { |
| 15 | expect(parseNumericValue(42)).toBe(42) |
| 16 | expect(parseNumericValue(0)).toBe(0) |
| 17 | expect(parseNumericValue(3.14)).toBe(3.14) |
| 18 | }) |
| 19 | |
| 20 | it('parses valid string numbers', () => { |
| 21 | expect(parseNumericValue('42')).toBe(42) |
| 22 | expect(parseNumericValue('3.14')).toBe(3.14) |
| 23 | expect(parseNumericValue('0')).toBe(0) |
| 24 | }) |
| 25 | |
| 26 | it('returns 0 for invalid string values', () => { |
| 27 | expect(parseNumericValue('invalid')).toBe(0) |
| 28 | expect(parseNumericValue('')).toBe(0) |
| 29 | expect(parseNumericValue('NaN')).toBe(0) |
| 30 | }) |
| 31 | |
| 32 | it('returns 0 for undefined', () => { |
| 33 | expect(parseNumericValue(undefined)).toBe(0) |
| 34 | }) |
| 35 | }) |
| 36 | |
| 37 | describe('parseInfrastructureMetrics', () => { |
| 38 | it('returns null for undefined data', () => { |
| 39 | expect(parseInfrastructureMetrics(undefined)).toBe(null) |
| 40 | }) |
| 41 | |
| 42 | it('parses valid metrics from response', () => { |
| 43 | const mockResponse: InfraMonitoringMultiResponse = { |
| 44 | data: [], |
| 45 | series: { |
| 46 | avg_cpu_usage: { format: 'percent', total: 150, totalAverage: 50, yAxisLimit: 100 }, |
| 47 | ram_usage: { format: 'bytes', total: 180, totalAverage: 60, yAxisLimit: 100 }, |
| 48 | disk_fs_used_system: { |
| 49 | format: 'bytes', |
| 50 | total: 20, |
| 51 | totalAverage: 20, |
| 52 | yAxisLimit: 100, |
| 53 | }, |
| 54 | disk_fs_used_wal: { |
| 55 | format: 'bytes', |
| 56 | total: 10, |
| 57 | totalAverage: 10, |
| 58 | yAxisLimit: 100, |
| 59 | }, |
| 60 | pg_database_size: { |
| 61 | format: 'bytes', |
| 62 | total: 30, |
| 63 | totalAverage: 30, |
| 64 | yAxisLimit: 100, |
| 65 | }, |
| 66 | disk_fs_size: { |
| 67 | format: 'bytes', |
| 68 | total: 200, |
| 69 | totalAverage: 200, |
| 70 | yAxisLimit: 100, |
| 71 | }, |
| 72 | disk_io_consumption: { |
| 73 | format: 'percent', |
| 74 | total: 210, |
| 75 | totalAverage: 70, |
| 76 | yAxisLimit: 100, |
| 77 | }, |
| 78 | }, |
| 79 | } |
| 80 | |
| 81 | const result = parseInfrastructureMetrics(mockResponse) |
| 82 | |
| 83 | expect(result).toEqual({ |
| 84 | cpu: { current: 50, max: 100 }, |
| 85 | ram: { current: 60, max: 100 }, |
| 86 | disk: { current: 30, max: 100 }, |
| 87 | diskIo: { current: 70, max: 100 }, |
| 88 | }) |
| 89 | }) |
| 90 | |
| 91 | it('handles string values in metrics', () => { |
| 92 | const mockResponse: InfraMonitoringMultiResponse = { |
| 93 | data: [], |
| 94 | series: { |
| 95 | avg_cpu_usage: { format: 'percent', total: 150, totalAverage: '50.5', yAxisLimit: 100 }, |
| 96 | ram_usage: { format: 'bytes', total: 180, totalAverage: '60.8', yAxisLimit: 100 }, |
| 97 | disk_fs_used_system: { |
| 98 | format: 'bytes', |
| 99 | total: 20, |
| 100 | totalAverage: '20.4', |
| 101 | yAxisLimit: 100, |
| 102 | }, |
| 103 | disk_fs_used_wal: { |
| 104 | format: 'bytes', |
| 105 | total: 10, |
| 106 | totalAverage: '10.2', |
| 107 | yAxisLimit: 100, |
| 108 | }, |
| 109 | pg_database_size: { |
| 110 | format: 'bytes', |
| 111 | total: 30, |
| 112 | totalAverage: '30.5', |
| 113 | yAxisLimit: 100, |
| 114 | }, |
| 115 | disk_fs_size: { |
| 116 | format: 'bytes', |
| 117 | total: 200, |
| 118 | totalAverage: '200.0', |
| 119 | yAxisLimit: 100, |
| 120 | }, |
| 121 | disk_io_consumption: { |
| 122 | format: 'percent', |
| 123 | total: 210, |
| 124 | totalAverage: '70.2', |
| 125 | yAxisLimit: 100, |
| 126 | }, |
| 127 | }, |
| 128 | } |
| 129 | |
| 130 | const result = parseInfrastructureMetrics(mockResponse) |
| 131 | |
| 132 | expect(result).toEqual({ |
| 133 | cpu: { current: 50.5, max: 100 }, |
| 134 | ram: { current: 60.8, max: 100 }, |
| 135 | disk: { current: 30.55, max: 100 }, |
| 136 | diskIo: { current: 70.2, max: 100 }, |
| 137 | }) |
| 138 | }) |
| 139 | |
| 140 | it('returns 0 for missing metrics', () => { |
| 141 | const mockResponse: InfraMonitoringMultiResponse = { |
| 142 | data: [], |
| 143 | series: {}, |
| 144 | } |
| 145 | |
| 146 | const result = parseInfrastructureMetrics(mockResponse) |
| 147 | |
| 148 | expect(result).toEqual({ |
| 149 | cpu: { current: 0, max: 100 }, |
| 150 | ram: { current: 0, max: 100 }, |
| 151 | disk: { current: 0, max: 100 }, |
| 152 | diskIo: { current: 0, max: 100 }, |
| 153 | }) |
| 154 | }) |
| 155 | |
| 156 | it('handles partial metrics data', () => { |
| 157 | const mockResponse: InfraMonitoringMultiResponse = { |
| 158 | data: [], |
| 159 | series: { |
| 160 | avg_cpu_usage: { format: 'percent', total: 150, totalAverage: 50, yAxisLimit: 100 }, |
| 161 | }, |
| 162 | } |
| 163 | |
| 164 | const result = parseInfrastructureMetrics(mockResponse) |
| 165 | |
| 166 | expect(result).toEqual({ |
| 167 | cpu: { current: 50, max: 100 }, |
| 168 | ram: { current: 0, max: 100 }, |
| 169 | disk: { current: 0, max: 100 }, |
| 170 | diskIo: { current: 0, max: 100 }, |
| 171 | }) |
| 172 | }) |
| 173 | |
| 174 | it('handles single-response format (legacy)', () => { |
| 175 | const mockResponse: InfraMonitoringSingleResponse = { |
| 176 | data: [], |
| 177 | format: 'percent', |
| 178 | total: 150, |
| 179 | totalAverage: 50, |
| 180 | yAxisLimit: 100, |
| 181 | } |
| 182 | |
| 183 | const result = parseInfrastructureMetrics(mockResponse) |
| 184 | |
| 185 | expect(result).toEqual({ |
| 186 | cpu: { current: 0, max: 100 }, |
| 187 | ram: { current: 0, max: 100 }, |
| 188 | disk: { current: 0, max: 100 }, |
| 189 | diskIo: { current: 0, max: 100 }, |
| 190 | }) |
| 191 | }) |
| 192 | }) |
| 193 | |
| 194 | describe('parseConnectionsData', () => { |
| 195 | it('returns zeros when data is undefined', () => { |
| 196 | expect(parseConnectionsData(undefined, undefined)).toEqual({ current: 0, max: 0 }) |
| 197 | expect(parseConnectionsData(undefined, { maxConnections: 100 })).toEqual({ |
| 198 | current: 0, |
| 199 | max: 0, |
| 200 | }) |
| 201 | }) |
| 202 | |
| 203 | it('parses connections data correctly', () => { |
| 204 | const mockInfraData: InfraMonitoringMultiResponse = { |
| 205 | data: [], |
| 206 | series: { |
| 207 | pg_stat_database_num_backends: { |
| 208 | format: 'number', |
| 209 | total: 150, |
| 210 | totalAverage: 25.5, |
| 211 | yAxisLimit: 100, |
| 212 | }, |
| 213 | }, |
| 214 | } |
| 215 | |
| 216 | const mockMaxData = { maxConnections: 100 } |
| 217 | |
| 218 | const result = parseConnectionsData(mockInfraData, mockMaxData) |
| 219 | |
| 220 | expect(result).toEqual({ current: 26, max: 100 }) // 25.5 rounded to 26 |
| 221 | }) |
| 222 | |
| 223 | it('handles string values for connections', () => { |
| 224 | const mockInfraData: InfraMonitoringMultiResponse = { |
| 225 | data: [], |
| 226 | series: { |
| 227 | pg_stat_database_num_backends: { |
| 228 | format: 'number', |
| 229 | total: 150, |
| 230 | totalAverage: '30.7', |
| 231 | yAxisLimit: 100, |
| 232 | }, |
| 233 | }, |
| 234 | } |
| 235 | |
| 236 | const mockMaxData = { maxConnections: 100 } |
| 237 | |
| 238 | const result = parseConnectionsData(mockInfraData, mockMaxData) |
| 239 | |
| 240 | expect(result).toEqual({ current: 31, max: 100 }) // 30.7 rounded to 31 |
| 241 | }) |
| 242 | |
| 243 | it('returns current connections even when maxConnectionsData is undefined', () => { |
| 244 | const mockInfraData: InfraMonitoringMultiResponse = { |
| 245 | data: [], |
| 246 | series: { |
| 247 | pg_stat_database_num_backends: { |
| 248 | format: 'number', |
| 249 | total: 150, |
| 250 | totalAverage: 25, |
| 251 | yAxisLimit: 100, |
| 252 | }, |
| 253 | }, |
| 254 | } |
| 255 | |
| 256 | const result = parseConnectionsData(mockInfraData, undefined) |
| 257 | |
| 258 | expect(result).toEqual({ current: 25, max: 0 }) |
| 259 | }) |
| 260 | |
| 261 | it('returns 0 max when maxConnections is missing from data object', () => { |
| 262 | const mockInfraData: InfraMonitoringMultiResponse = { |
| 263 | data: [], |
| 264 | series: { |
| 265 | pg_stat_database_num_backends: { |
| 266 | format: 'number', |
| 267 | total: 150, |
| 268 | totalAverage: 25, |
| 269 | yAxisLimit: 100, |
| 270 | }, |
| 271 | }, |
| 272 | } |
| 273 | |
| 274 | const mockMaxData = {} |
| 275 | |
| 276 | const result = parseConnectionsData(mockInfraData, mockMaxData) |
| 277 | |
| 278 | expect(result).toEqual({ current: 25, max: 0 }) |
| 279 | }) |
| 280 | |
| 281 | it('returns 0 current when connections metric is missing', () => { |
| 282 | const mockInfraData: InfraMonitoringMultiResponse = { |
| 283 | data: [], |
| 284 | series: {}, |
| 285 | } |
| 286 | |
| 287 | const mockMaxData = { maxConnections: 100 } |
| 288 | |
| 289 | const result = parseConnectionsData(mockInfraData, mockMaxData) |
| 290 | |
| 291 | expect(result).toEqual({ current: 0, max: 100 }) |
| 292 | }) |
| 293 | |
| 294 | it('handles single-response format (legacy)', () => { |
| 295 | const mockInfraData: InfraMonitoringSingleResponse = { |
| 296 | data: [], |
| 297 | format: 'number', |
| 298 | total: 150, |
| 299 | totalAverage: 25, |
| 300 | yAxisLimit: 100, |
| 301 | } |
| 302 | |
| 303 | const mockMaxData = { maxConnections: 100 } |
| 304 | |
| 305 | const result = parseConnectionsData(mockInfraData, mockMaxData) |
| 306 | |
| 307 | expect(result).toEqual({ current: 0, max: 100 }) |
| 308 | }) |
| 309 | }) |