Files
supabase/apps/studio/components/interfaces/Auth/PerformanceSettingsForm.test.tsx
Ali Waseem 652311feb5 fix(studio): guard Auth Performance allocation strategy select against invalid values (#47896)
## Summary
- The Connection management "Allocation strategy" select on the Auth >
Performance page called its `onValueChange` handler's conversion logic
with whatever value it was given, with no validation. If that handler
ever fired with a value outside the `'percent' | 'connections'` enum, it
would silently overwrite a correctly loaded config, converting it to the
wrong absolute connection count and leaving the strategy dropdown in a
blank/inconsistent state.
- Extracted the percent/connections conversion into a pure, unit-tested
`convertPoolSize()` helper (`PerformanceSettingsForm.utils.ts`) and
added a guard so `onValueChange` ignores any value that isn't a
recognized allocation unit.

## How to test
1. Under **Connection management**, switch **Allocation strategy** back
and forth between "Absolute number of connections" and "Percent of max
connections" — the value should convert correctly each time and the
dropdown should never render blank.
2. Save, then hard-reload the page — the saved strategy and value should
persist as shown.

## Test plan
- [x] `PerformanceSettingsForm.utils.test.ts` — unit tests covering both
conversion directions, clamping, and the invalid-value guard
- [x] `PerformanceSettingsForm.test.tsx` — MSW-backed component test
verifying persisted percent/absolute configs render correctly on load
- [x] `pnpm test:studio`
- [x] `pnpm typecheck`

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

## Summary by CodeRabbit

* **Improvements**
* Switching database pool allocation strategies now automatically
converts values between percentage and connection-based units.
* Values are rounded and constrained appropriately to remain within
supported limits.
  * Allocation settings now handle invalid or zero values more safely.
* **Tests**
* Added coverage verifying persisted allocation strategies and pool-size
conversion behavior.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-13 14:16:52 -06:00

71 lines
2.3 KiB
TypeScript

import { screen } from '@testing-library/react'
import { HttpResponse } from 'msw'
import { describe, expect, test, vi } from 'vitest'
import { PerformanceSettingsForm } from './PerformanceSettingsForm'
import { customRender } from '@/tests/lib/custom-render'
import { addAPIMock } from '@/tests/lib/msw'
vi.mock('@/lib/constants', async (importOriginal) => {
const actual = await importOriginal<typeof import('@/lib/constants')>()
return { ...actual, IS_PLATFORM: true }
})
vi.mock('@/hooks/misc/useSelectedProject', () => ({
useSelectedProjectQuery: () => ({ data: { ref: 'default', connectionString: null } }),
}))
vi.mock('@/hooks/misc/useCheckEntitlements', () => ({
useCheckEntitlements: () => ({ hasAccess: true, isLoading: false }),
}))
vi.mock('@/hooks/misc/useCheckPermissions', () => ({
useAsyncCheckPermissions: () => ({ can: true, isLoading: false, isSuccess: true }),
}))
function mockAuthConfig(overrides: Record<string, unknown>) {
addAPIMock({
method: 'get',
path: '/platform/auth/:ref/config',
response: () =>
HttpResponse.json<any>({
API_MAX_REQUEST_DURATION: 10,
DB_MAX_POOL_SIZE: 10,
DB_MAX_POOL_SIZE_UNIT: 'connections',
...overrides,
}),
})
}
function mockMaxConnections(maxConnections: number) {
addAPIMock({
method: 'post',
path: '/platform/pg-meta/:ref/query',
response: () => HttpResponse.json<any>([{ max_connections: maxConnections }]),
})
}
describe('PerformanceSettingsForm', () => {
test('reflects a persisted percentage allocation strategy after loading', async () => {
mockAuthConfig({ DB_MAX_POOL_SIZE: 15, DB_MAX_POOL_SIZE_UNIT: 'percent' })
mockMaxConnections(60)
customRender(<PerformanceSettingsForm />)
expect(await screen.findByText('Percentage')).toBeInTheDocument()
expect(screen.getByDisplayValue('15')).toBeInTheDocument()
expect(screen.getByText('%')).toBeInTheDocument()
})
test('reflects a persisted absolute allocation strategy after loading', async () => {
mockAuthConfig({ DB_MAX_POOL_SIZE: 12, DB_MAX_POOL_SIZE_UNIT: 'connections' })
mockMaxConnections(60)
customRender(<PerformanceSettingsForm />)
expect(await screen.findByText('Absolute')).toBeInTheDocument()
expect(screen.getByDisplayValue('12')).toBeInTheDocument()
expect(screen.getByText('connections')).toBeInTheDocument()
})
})