Files
supabase/apps/studio/components/interfaces/ConnectSheet/ConnectionString.utils.test.ts
T
Saxon Fletcher d8fadcc1c8 makes it possible to reset password from connect dialog (#46866)
Makes it possible to reset password from the connect sheet. Once reset
the password is shown temporarily in the connection string for copy. The
copy prompt action does not copy the password.

<img width="1043" height="953" alt="image"
src="https://github.com/user-attachments/assets/fe1a33bb-839f-47e3-b07f-7a5fa1df2b8d"
/>


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

* **New Features**
  * Session Pooler notice for direct connections on IPv4 networks
* Option to show a temporary database password during direct-connection
setup

* **Improvements**
  * New password reset dialog with strength checks and generation
* Connection-copy behavior now redacts temporary passwords and produces
cleaner copy prompts

* **Tests**
* Added tests covering connection-string password insertion/replacement
and copy-prompt behavior
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-12 07:38:18 -06:00

179 lines
5.6 KiB
TypeScript

import { describe, expect, test } from 'vitest'
import {
buildConnectionParameters,
buildConnectionStringWithPassword,
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('buildConnectionStringWithPassword', () => {
test('returns the original string when input or password is empty', () => {
const uri = `postgresql://postgres:${PASSWORD_PLACEHOLDER}@localhost:5432/postgres`
expect(buildConnectionStringWithPassword('', 'password')).toBe('')
expect(buildConnectionStringWithPassword(uri, '')).toBe(uri)
})
test('replaces every password placeholder with the encoded password', () => {
const uri = `postgresql://postgres:${PASSWORD_PLACEHOLDER}@localhost:5432/postgres?password=${PASSWORD_PLACEHOLDER}`
expect(buildConnectionStringWithPassword(uri, 'p@ss/word#1')).toBe(
'postgresql://postgres:p%40ss%2Fword%231@localhost:5432/postgres?password=p%40ss%2Fword%231'
)
})
})
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' },
])
})
})