mirror of
https://github.com/supabase/supabase.git
synced 2026-10-10 11:55:05 +03:00
161 lines
4.8 KiB
TypeScript
161 lines
4.8 KiB
TypeScript
import { describe, expect, test } from 'vitest'
|
|
|
|
import {
|
|
buildConnectionParameters,
|
|
buildSafeConnectionString,
|
|
DEFAULT_PORT,
|
|
parseConnectionParams,
|
|
PASSWORD_PLACEHOLDER,
|
|
resolveConnectionString,
|
|
} from './ConnectionString.utils'
|
|
|
|
describe('parseConnectionParams', () => {
|
|
test('returns hidden defaults for an empty string', () => {
|
|
expect(parseConnectionParams('')).toEqual({
|
|
host: 'hidden',
|
|
port: DEFAULT_PORT,
|
|
user: 'hidden',
|
|
database: 'hidden',
|
|
})
|
|
})
|
|
|
|
test('returns hidden defaults for an unparseable URL', () => {
|
|
expect(parseConnectionParams('not a url')).toEqual({
|
|
host: 'hidden',
|
|
port: DEFAULT_PORT,
|
|
user: 'hidden',
|
|
database: 'hidden',
|
|
})
|
|
})
|
|
|
|
test('parses a platform-shaped connection string', () => {
|
|
const uri =
|
|
'postgresql://postgres.projref:[YOUR-PASSWORD]@aws-0-eu-west-1.pooler.supabase.com:6543/postgres'
|
|
expect(parseConnectionParams(uri)).toEqual({
|
|
host: 'aws-0-eu-west-1.pooler.supabase.com',
|
|
port: '6543',
|
|
user: 'postgres.projref',
|
|
database: 'postgres',
|
|
})
|
|
})
|
|
|
|
test('decodes percent-encoded bracket placeholders in the user info', () => {
|
|
// The URL parser percent-encodes the `[`/`]` in self-hosted's POOLER_TENANT_ID placeholder.
|
|
// parseConnectionParams must decode so the displayed user matches what we wrote.
|
|
const uri =
|
|
'postgresql://postgres.[POOLER_TENANT_ID]:[YOUR-PASSWORD]@supabase.example.com:6543/postgres'
|
|
expect(parseConnectionParams(uri).user).toBe('postgres.[POOLER_TENANT_ID]')
|
|
})
|
|
})
|
|
|
|
describe('buildSafeConnectionString', () => {
|
|
test('returns empty string when input is empty', () => {
|
|
expect(buildSafeConnectionString('', parseConnectionParams(''))).toBe('')
|
|
})
|
|
|
|
test('rebuilds the URL with PASSWORD_PLACEHOLDER and the parsed params (round-trips brackets)', () => {
|
|
const uri =
|
|
'postgresql://postgres.[POOLER_TENANT_ID]:[YOUR-PASSWORD]@supabase.example.com:6543/postgres'
|
|
const params = parseConnectionParams(uri)
|
|
const safe = buildSafeConnectionString(uri, params)
|
|
expect(safe).toBe(
|
|
`postgresql://postgres.[POOLER_TENANT_ID]:${PASSWORD_PLACEHOLDER}@supabase.example.com:6543/postgres`
|
|
)
|
|
})
|
|
|
|
test('preserves search params from the original URL', () => {
|
|
const uri = 'postgresql://postgres.proj:[YOUR-PASSWORD]@host:5432/postgres?sslmode=require'
|
|
const params = parseConnectionParams(uri)
|
|
expect(buildSafeConnectionString(uri, params)).toContain('?sslmode=require')
|
|
})
|
|
})
|
|
|
|
describe('resolveConnectionString', () => {
|
|
const pooler = {
|
|
transactionShared: 'tx-shared',
|
|
sessionShared: 'session-shared',
|
|
transactionDedicated: 'tx-dedicated',
|
|
sessionDedicated: 'session-dedicated',
|
|
ipv4SupportedForDedicatedPooler: true,
|
|
direct: 'direct-uri',
|
|
}
|
|
|
|
test('returns empty string when pooler bag is undefined', () => {
|
|
expect(
|
|
resolveConnectionString({
|
|
connectionMethod: 'direct',
|
|
useSharedPooler: false,
|
|
connectionStringPooler: undefined,
|
|
})
|
|
).toBe('')
|
|
})
|
|
|
|
test('direct method returns the direct URI', () => {
|
|
expect(
|
|
resolveConnectionString({
|
|
connectionMethod: 'direct',
|
|
useSharedPooler: false,
|
|
connectionStringPooler: pooler,
|
|
})
|
|
).toBe('direct-uri')
|
|
})
|
|
|
|
test('session method returns sessionShared', () => {
|
|
expect(
|
|
resolveConnectionString({
|
|
connectionMethod: 'session',
|
|
useSharedPooler: false,
|
|
connectionStringPooler: pooler,
|
|
})
|
|
).toBe('session-shared')
|
|
})
|
|
|
|
test('transaction prefers dedicated when available and useSharedPooler is false', () => {
|
|
expect(
|
|
resolveConnectionString({
|
|
connectionMethod: 'transaction',
|
|
useSharedPooler: false,
|
|
connectionStringPooler: pooler,
|
|
})
|
|
).toBe('tx-dedicated')
|
|
})
|
|
|
|
test('transaction falls back to shared when useSharedPooler is true', () => {
|
|
expect(
|
|
resolveConnectionString({
|
|
connectionMethod: 'transaction',
|
|
useSharedPooler: true,
|
|
connectionStringPooler: pooler,
|
|
})
|
|
).toBe('tx-shared')
|
|
})
|
|
|
|
test('transaction falls back to shared when no dedicated pooler exists', () => {
|
|
expect(
|
|
resolveConnectionString({
|
|
connectionMethod: 'transaction',
|
|
useSharedPooler: false,
|
|
connectionStringPooler: { ...pooler, transactionDedicated: undefined },
|
|
})
|
|
).toBe('tx-shared')
|
|
})
|
|
})
|
|
|
|
describe('buildConnectionParameters', () => {
|
|
test('produces host/port/database/user rows in display order', () => {
|
|
expect(
|
|
buildConnectionParameters({
|
|
host: 'h',
|
|
port: '5432',
|
|
user: 'u',
|
|
database: 'd',
|
|
})
|
|
).toEqual([
|
|
{ key: 'host', value: 'h' },
|
|
{ key: 'port', value: '5432' },
|
|
{ key: 'database', value: 'd' },
|
|
{ key: 'user', value: 'u' },
|
|
])
|
|
})
|
|
})
|