Files
supabase/apps/studio/components/interfaces/DiskManagement/DiskManagement.test.ts
Jordi Enric 022b510269 fix: centralize compute disk limits data and update documentation (#41242)
https://linear.app/supabase/issue/FE-2226/fix-incorrect-baseline-and-max-iopsthroughput-values

- Centralized compute/disk limits in
packages/shared-data/compute-disk-limits.ts (MB/s, baseline+max
IOPS/throughput) and re-exported from shared-data.
- Hooked Docs compute/disk table into shared data, converted docs
text/table to MB/s baseline/max.
- Removed duplicated compute IOPS/throughput constants from Studio,
Studio now imports shared data.
- Updated Studio disk schema: compute-aware MAX IOPS/throughput
validation (MB/s), defaults computeSize to ci_micro, and gp3/io2 checks
use compute caps.
- Clarified disk update mutation to send throughput as MB/s despite
backend throughput_mbps field name.
- Added tests for compute-size mappings and IOPS helper logic.
- Added Infra ownership for shared compute/disk data in CODEOWNERS.
- Locked zod version via catalog and added zod dep to shared-data.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added a reusable Compute Disk Limits table and centralized compute
disk limits dataset for dynamic display.

* **Documentation**
* Replaced static per-size tables with a component-driven MB/s view;
clarified baseline vs. burst behavior and updated guides and
troubleshooting.

* **Bug Fixes**
* Validation and UI guidance now honor compute-size limits for IOPS and
throughput.

* **Tests**
  * Expanded unit tests for sizing, mappings, and edge cases.

* **Chores**
* Published shared-data exports, added a validation schema, pinned a
dependency, and added ownership entries.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-02-03 10:52:42 +00:00

159 lines
5.1 KiB
TypeScript

import { describe, expect, test } from 'vitest'
import {
calculateBaselineIopsForComputeSize,
calculateComputeSizeRequiredForIops,
calculateDiskSizePrice,
calculateIOPSPrice,
calculateMaxIopsForComputeSize,
calculateThroughputPrice,
mapAddOnVariantIdToComputeSize,
mapComputeSizeNameToAddonVariantId,
} from './DiskManagement.utils'
import { DiskType } from './ui/DiskManagement.constants'
describe('DiskManagement utils', () => {
describe('mapComputeSizeNameToAddonVariantId', () => {
test('maps known infra sizes to addon variant ids', () => {
expect(mapComputeSizeNameToAddonVariantId('4xlarge')).toBe('ci_4xlarge')
})
test('falls back to nano for unknown infra sizes', () => {
// @ts-expect-error intentional invalid value for runtime guard
expect(mapComputeSizeNameToAddonVariantId('unknown-size')).toBe('ci_nano')
})
})
describe('mapAddOnVariantIdToComputeSize', () => {
test('maps known addon ids to display names', () => {
expect(mapAddOnVariantIdToComputeSize('ci_4xlarge')).toBe('4XL')
})
test('falls back to Nano on invalid addon id', () => {
// @ts-expect-error intentional invalid value for runtime guard
expect(mapAddOnVariantIdToComputeSize('ci_invalid')).toBe('Nano')
})
})
describe('calculateBaselineIopsForComputeSize / calculateMaxIopsForComputeSize', () => {
test('returns 0 for invalid compute ids', () => {
expect(calculateBaselineIopsForComputeSize('invalid')).toBe(0)
expect(calculateMaxIopsForComputeSize('invalid')).toBe(0)
})
test('returns baseline and max for valid compute ids', () => {
expect(calculateBaselineIopsForComputeSize('ci_2xlarge')).toBe(12000)
expect(calculateMaxIopsForComputeSize('ci_2xlarge')).toBe(20000)
})
})
describe('calculateComputeSizeRequiredForIops', () => {
test('returns smallest size that satisfies requested IOPS', () => {
expect(calculateComputeSizeRequiredForIops(500)).toBe('ci_nano')
expect(calculateComputeSizeRequiredForIops(19000)).toBe('ci_large')
expect(calculateComputeSizeRequiredForIops(45000)).toBe('ci_12xlarge')
})
test('falls back to largest size when exceeding known max', () => {
const fallback = calculateComputeSizeRequiredForIops(500000)
expect([
'ci_48xlarge',
'ci_48xlarge_optimized_cpu',
'ci_48xlarge_optimized_memory',
'ci_48xlarge_high_memory',
]).toContain(fallback)
})
})
})
describe('DiskManagement.utils.ts:calculateDiskSizePrice', () => {
test('GP3 with 8GB to GP3 with 10GB for pro plan', () => {
const result = calculateDiskSizePrice({
planId: 'pro',
oldSize: 8,
oldStorageType: DiskType.GP3,
newSize: 10,
newStorageType: DiskType.GP3,
})
expect(result.oldPrice).toBe('0.00')
expect(result.newPrice).toBe('0.25')
})
test('IO2 with 8GB to IO2 with 10GB for pro plan', () => {
const result = calculateDiskSizePrice({
planId: 'pro',
oldSize: 8,
oldStorageType: DiskType.IO2,
newSize: 10,
newStorageType: DiskType.IO2,
})
expect(result.oldPrice).toBe('1.56')
expect(result.newPrice).toBe('1.95')
})
test('GP3 with 8GB to GP3 with 10GB, with 2 replicas', () => {
const result = calculateDiskSizePrice({
planId: 'pro',
oldSize: 8,
oldStorageType: DiskType.GP3,
newSize: 10,
newStorageType: DiskType.GP3,
numReplicas: 2,
})
expect(result.oldPrice).toBe('2.50')
expect(result.newPrice).toBe('3.38')
})
})
describe('DiskManagement.utils.ts:calculateIOPSPrice', () => {
test('GP3 with 3000 to IO2 with 3000', () => {
const result = calculateIOPSPrice({
oldStorageType: DiskType.GP3,
oldProvisionedIOPS: 3000,
newStorageType: DiskType.IO2,
newProvisionedIOPS: 3000,
})
expect(result.oldPrice).toBe('0.00')
expect(result.newPrice).toBe('357.00')
})
test('GP3 with 3000 to GP3 with 5000', () => {
const result = calculateIOPSPrice({
oldStorageType: DiskType.GP3,
oldProvisionedIOPS: 3000,
newStorageType: DiskType.GP3,
newProvisionedIOPS: 5000,
})
expect(result.oldPrice).toBe('0.00')
expect(result.newPrice).toBe('48.00')
})
test('IO2 with 3000 to IO2 with 5000', () => {
const result = calculateIOPSPrice({
oldStorageType: DiskType.IO2,
oldProvisionedIOPS: 3000,
newStorageType: DiskType.IO2,
newProvisionedIOPS: 5000,
})
expect(result.oldPrice).toBe('357.00')
expect(result.newPrice).toBe('595.00')
})
})
describe('DiskManagement.utils.ts:calculateThroughputPrice', () => {
test('GP3 with 125 MB/s 150 MB/s', () => {
const result = calculateThroughputPrice({
storageType: DiskType.GP3,
oldThroughput: 125,
newThroughput: 150,
})
expect(result.oldPrice).toBe('0.00')
expect(result.newPrice).toBe('2.38')
})
test('IO1 with 125 MB/s 150 MB/s', () => {
const result = calculateThroughputPrice({
storageType: DiskType.IO2,
oldThroughput: 125,
newThroughput: 150,
})
expect(result.oldPrice).toBe('0.00')
expect(result.newPrice).toBe('0.00')
})
})