Files
supabase__supabase/apps/studio/components/interfaces/ProjectCreation/RegionSelector.utils.test.ts
kemal.earth 24e8333c54 feat(studio): flag for unavailable regions (#50473)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Adds feature flag for controlling region unavailability.


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

* **New Features**
* Region options now display availability badges, tooltips, and
status-specific notices.
* Restricted regions remain selectable so users can review their
availability status.
* Project creation provides a clear field-level message when a selected
region is unavailable and prompts users to choose another region.

* **Bug Fixes**
* Region availability messaging now consistently reflects platform
status and configured restrictions.
  * Availability warnings clear after selecting an eligible region.
  * Region checks now cover both dynamic and static provider regions.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-17 14:42:58 +01:00

106 lines
3.7 KiB
TypeScript

import { describe, expect, it, vi } from 'vitest'
import {
getRegionRestrictionCopy,
getRegionRestrictionMessage,
parseRestrictedRegions,
REGION_RESTRICTION_COPY,
resolveRegionRestriction,
SELECT_DIFFERENT_REGION,
} from './RegionSelector.utils'
vi.mock('@/lib/error-reporting', () => ({ captureCriticalError: vi.fn() }))
describe('parseRestrictedRegions', () => {
it.each([
['the false that useFlag returns when unresolved or errored', false],
['undefined', undefined],
['an empty string', ''],
['an empty object', '{}'],
['invalid JSON', 'not json'],
['an unknown status value', '{"sa-east-1":"bogus"}'],
['a status value the flag no longer supports', '{"sa-east-1":"paid_only"}'],
['an array instead of a record', '["sa-east-1"]'],
['a non-string value', 42],
])('fails open to no restrictions for %s', (_label, flagValue) => {
expect(parseRestrictedRegions(flagValue)).toEqual({})
})
it('returns the restrictions keyed by region code for a valid payload', () => {
expect(
parseRestrictedRegions('{"sa-east-1":"unavailable","eu-central-1":"unavailable"}')
).toEqual({ 'sa-east-1': 'unavailable', 'eu-central-1': 'unavailable' })
})
it('drops every restriction when any entry is invalid', () => {
expect(parseRestrictedRegions('{"sa-east-1":"unavailable","eu-central-1":"bogus"}')).toEqual({})
})
it('reports a present-but-invalid payload without reporting the unresolved flag value', async () => {
const { captureCriticalError } = await import('@/lib/error-reporting')
vi.mocked(captureCriticalError).mockClear()
parseRestrictedRegions(false)
parseRestrictedRegions('')
expect(captureCriticalError).not.toHaveBeenCalled()
parseRestrictedRegions('not json')
parseRestrictedRegions('{"sa-east-1":"bogus"}')
expect(captureCriticalError).toHaveBeenCalledTimes(2)
})
})
describe('resolveRegionRestriction', () => {
it('lets the platform status win over the flag', () => {
expect(
resolveRegionRestriction({ platformStatus: 'capacity', flagRestriction: 'unavailable' })
).toBe('capacity')
expect(
resolveRegionRestriction({ platformStatus: 'other', flagRestriction: 'unavailable' })
).toBe('other')
})
it('applies the flag only where the platform reports no status', () => {
expect(
resolveRegionRestriction({ platformStatus: undefined, flagRestriction: 'unavailable' })
).toBe('unavailable')
})
it('passes a platform status it does not recognise through unchanged', () => {
expect(
resolveRegionRestriction({ platformStatus: 'brand_new', flagRestriction: undefined })
).toBe('brand_new')
})
it('returns no restriction when neither source restricts the region', () => {
expect(
resolveRegionRestriction({ platformStatus: undefined, flagRestriction: undefined })
).toBeUndefined()
})
})
describe('getRegionRestrictionCopy', () => {
it('uses the capacity copy for a capacity status', () => {
expect(getRegionRestrictionCopy('capacity')).toBe(REGION_RESTRICTION_COPY.capacity)
expect(getRegionRestrictionCopy('capacity').tooltip).toBe(
'Temporarily unavailable due to this region being at capacity.'
)
})
it.each(['other', 'unavailable', 'brand_new', 'toString'])(
'falls back to the generic copy for %s',
(restriction) => {
expect(getRegionRestrictionCopy(restriction)).toBe(REGION_RESTRICTION_COPY.other)
}
)
it('builds the submit message from the title and the shared call to action', () => {
expect(getRegionRestrictionMessage('capacity')).toBe(
`Selected region is at capacity. ${SELECT_DIFFERENT_REGION}`
)
expect(getRegionRestrictionMessage('brand_new')).toBe(
`Selected region is unavailable. ${SELECT_DIFFERENT_REGION}`
)
})
})