Files
supabase/apps/studio/components/interfaces/Settings/Integrations/AWSPrivateLink/AWSPrivateLink.utils.test.ts
Danny White 4760c1af77 feat(studio): polish PrivateLink connection UI (#49164)
## What kind of change does this PR introduce?

Polish for the AWS PrivateLink integrations UI.

## What is the current behavior?

The add/view sheet labels the optional nickname field as "Description",
delete confirmation always shows the AWS account ID, list admonitions
use generic copy, and delete uses a fire-and-forget mutation.

## What is the new behavior?

- Rename the optional nickname field to **Name**, with helper copy
explaining it appears on the connections list
- Tighten list admonition copy to reference connections below and
pluralise share wording
- Rename `showAcceptLink` to `shouldShowAcceptLink`
- Delete confirmation uses the connection name (or account ID when
unnamed) and clearer read replica fallback copy
- Delete uses `mutateAsync` so the dialog can await the mutation

| Before | After | 
| --- | --- |
| <img width="828" height="515" alt="Integrations Settings Chisel
Toolshed Supabase"
src="https://github.com/user-attachments/assets/9e255d4b-a048-459c-87ff-ee1b65f42f9a"
/> | <img width="828" height="515" alt="Integrations Settings Chisel
Toolshed Supabase"
src="https://github.com/user-attachments/assets/500e3922-912f-4e3b-a875-295ac7bd689e"
/> |

## To test

1. Open **Project settings → Integrations → AWS PrivateLink** on a
project with PrivateLink access
2. Click **Add connection** and confirm the optional field is labelled
**Name** with helper copy underneath
3. Add a connection with a name (e.g. `Production VPC`) and confirm the
list row shows that title
4. If you have a waiting or expired connection, confirm the list
admonition copy references shares below
5. Open a named connection, click **Delete**, and confirm the dialog
uses the connection name rather than always showing the raw account ID
6. Cancel delete and confirm the sheet stays open

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

* **Improvements**
* Updated AWS PrivateLink connection messages with clearer singular and
plural wording.
* Improved guidance for expired and pending connections, including
acceptance-instruction links.
* Renamed the account field to “Name,” marked it optional, and clarified
its purpose and default behavior.
* Enhanced deletion confirmations with clearer connection names and AWS
account identifiers.
  * Improved deletion handling to provide more reliable feedback.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-18 14:25:42 +10:00

85 lines
2.9 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import {
getConnectionsAttention,
getConnectionsAttentionCopy,
getConnectionStatusUi,
getConnectionTitle,
type PrivateLinkConnectionStatus,
} from './AWSPrivateLink.utils'
describe('getConnectionStatusUi', () => {
it.each([
['ASSOCIATION_ACCEPTED', { badge: 'Connected', badgeVariant: 'success' }],
['READY', { badge: 'Waiting', badgeVariant: 'warning' }],
['CREATING', { badge: 'Creating', badgeVariant: 'default' }],
['DELETING', { badge: 'Deleting', badgeVariant: 'warning' }],
['ASSOCIATION_REQUEST_EXPIRED', { badge: 'Expired', badgeVariant: 'destructive' }],
['CREATION_FAILED', { badge: 'Failed', badgeVariant: 'destructive' }],
] as const satisfies ReadonlyArray<
[PrivateLinkConnectionStatus, ReturnType<typeof getConnectionStatusUi>]
>)('maps %s', (status, expected) => {
expect(getConnectionStatusUi(status)).toEqual(expected)
})
it('returns unknown copy when status is missing', () => {
expect(getConnectionStatusUi()).toEqual({ badge: 'Unknown', badgeVariant: 'default' })
})
})
describe('getConnectionTitle', () => {
it('uses the customer nickname when present', () => {
expect(
getConnectionTitle({
account_name: 'Production VPC',
aws_account_id: '123456789012',
})
).toBe('Production VPC')
})
it('falls back to the AWS account ID for an unnamed connection', () => {
expect(getConnectionTitle({ aws_account_id: '123456789012' })).toBe('123456789012')
})
it('falls back to the AWS account ID for a blank nickname', () => {
expect(
getConnectionTitle({
account_name: ' ',
aws_account_id: '123456789012',
})
).toBe('123456789012')
})
})
describe('getConnectionsAttentionCopy', () => {
it('returns null when nothing needs attention', () => {
expect(getConnectionsAttentionCopy({ waitingCount: 0, expiredCount: 0 })).toBeNull()
})
it('warns when a connection is waiting', () => {
const copy = getConnectionsAttentionCopy({ waitingCount: 1, expiredCount: 0 })
expect(copy?.type).toBe('warning')
expect(copy?.title).toBe('Waiting for the AWS account owner')
expect(copy?.description).toBe('Accept the resource share in AWS within 12 hours.')
expect(copy?.shouldShowAcceptLink).toBe(true)
})
it('uses destructive copy when only expired', () => {
const copy = getConnectionsAttentionCopy({ waitingCount: 0, expiredCount: 2 })
expect(copy?.type).toBe('destructive')
expect(copy?.title).toBe('Connection requests expired')
expect(copy?.description).toBe('AWS can no longer accept these shares.')
expect(copy?.shouldShowAcceptLink).toBe(false)
})
it('counts statuses from a list', () => {
expect(
getConnectionsAttention([
{ status: 'READY' },
{ status: 'ASSOCIATION_ACCEPTED' },
{ status: 'ASSOCIATION_REQUEST_EXPIRED' },
])
).toEqual({ waitingCount: 1, expiredCount: 1 })
})
})