Files
supabase/apps/studio/components/interfaces/Storage/FilesBuckets/EditBucketModal.utils.test.ts
T
6ef729cb5c feat(storage): versioning bucket modals (FE-4161) (#49205)
| # | Branch | Base |
| - | ------ | ---- |
| 1 | `feat/storage-versioning-private-alpha` — merged | `master` |
| 2 | `feat/storage-versioning/002-bucket-form-fields` | `master` |
| 3 | `feat/storage-versioning/003-bucket-modals` ◀ | 2 |
| 4 | `feat/storage-versioning/004-object-versions-data` | 3 |
| 5 | `feat/storage-versioning/005-file-preview-versions` | 4 |
| 6 | `feat/storage-versioning/006-billing-storage-retention` | 5 |
| 7 | `feat/storage-versioning/007-archived-objects-data` | 6 |
| 8 | `feat/storage-versioning/008-archived-rows` | 7 |
| 9 | `feat/storage-versioning/009-archived-preview-pane` | 8 |
| 10 | `feat/storage-versioning/010-replace-file` | 9 |

## [3/10] Storage object versioning: wire into the bucket modals

**Base:** `feat/storage-versioning/002-bucket-form-fields` (PR 2)

### This PR

Mounts the object-versioning form section in the create and edit bucket
modals behind the feature preview, and saves it.

- create and edit bucket modals spread `bucketVersioningFormFields` into
their existing form schema
- lifecycle defaults  to 30 days / 10 versions
- edit adds a confirmation before suspending an actively versioned
bucket

## Enabling object versioning on a new bucket and setting lifecycle
policies


https://github.com/user-attachments/assets/194f8319-4929-432e-8a50-206f180a77a8

## Edit and suspend object-versioning


https://github.com/user-attachments/assets/f31e1d34-9840-4f5a-a269-6a911214742d

## To reproduce

1. Make sure storage versioning is enabled under feature previews >
Storage Versioning
2. Open Storage Bucket File explorer
3. create new bucket and enable Object Versioning
4. set lifecycle policy
- Noncurrent version expiration: can be either empty or >1
- Retained noncurrent versions: can be either empty or between 1 and 100
and can't exist without "Noncurrent version expiration"
5. Open new bucket with object versioning and test changing lifecycle
policies
6. Disabling object-versioning shows proper warning and updates
`versioning_status` to SUSPENDED (it can never go back to DISABLED once
it has been enabled on a bucket)

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com>
2026-10-07 16:38:35 +02:00

148 lines
5.1 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import {
getNextVersioningState,
getVersioningFormDefaults,
isEnablingVersioning,
isSuspendingVersioning,
toVersioningStatusUpdate,
type BucketVersioningSettings,
} from './EditBucketModal.utils'
import { PROJECT_VERSIONING_DEFAULTS } from '@/components/interfaces/Storage/StorageVersioning.constants'
const settings = (overrides: Partial<BucketVersioningSettings> = {}): BucketVersioningSettings => ({
versioning: 'disabled',
versionExpiryDays: null,
maxNoncurrentVersions: null,
expirationMode: 'and',
...overrides,
})
describe('getVersioningFormDefaults', () => {
it('prefills the project defaults for a bucket that has never been versioned', () => {
expect(getVersioningFormDefaults(settings())).toEqual({
enable_versioning: false,
version_expiry_days: PROJECT_VERSIONING_DEFAULTS.versionExpiryDays,
max_noncurrent_versions: PROJECT_VERSIONING_DEFAULTS.maxNoncurrentVersions,
expiration_mode: 'and',
})
})
it('ignores any stray stored policy on a never-versioned bucket', () => {
const defaults = getVersioningFormDefaults(
settings({ versionExpiryDays: 1, maxNoncurrentVersions: 1 })
)
expect(defaults.version_expiry_days).toBe(PROJECT_VERSIONING_DEFAULTS.versionExpiryDays)
expect(defaults.max_noncurrent_versions).toBe(PROJECT_VERSIONING_DEFAULTS.maxNoncurrentVersions)
})
it('shows the stored policy for an actively versioned bucket', () => {
expect(
getVersioningFormDefaults(
settings({
versioning: 'enabled',
versionExpiryDays: 60,
maxNoncurrentVersions: 5,
expirationMode: 'or',
})
)
).toEqual({
enable_versioning: true,
version_expiry_days: 60,
max_noncurrent_versions: 5,
expiration_mode: 'or',
})
})
it('leaves an unset condition unset rather than filling in a default', () => {
// Prefilling here would silently add a bound the user never chose.
const defaults = getVersioningFormDefaults(
settings({ versioning: 'enabled', versionExpiryDays: 60, maxNoncurrentVersions: null })
)
expect(defaults.version_expiry_days).toBe(60)
expect(defaults.max_noncurrent_versions).toBe('')
})
it('shows a suspended bucket with the switch off but its policy intact', () => {
const defaults = getVersioningFormDefaults(
settings({ versioning: 'suspended', versionExpiryDays: 14, maxNoncurrentVersions: 3 })
)
expect(defaults.enable_versioning).toBe(false)
expect(defaults.version_expiry_days).toBe(14)
expect(defaults.max_noncurrent_versions).toBe(3)
})
})
describe('getNextVersioningState', () => {
it('enables versioning from any starting state', () => {
expect(getNextVersioningState('disabled', true)).toBe('enabled')
expect(getNextVersioningState('suspended', true)).toBe('enabled')
expect(getNextVersioningState('enabled', true)).toBe('enabled')
})
it('suspends rather than disables a bucket that has been versioned', () => {
expect(getNextVersioningState('enabled', false)).toBe('suspended')
})
it('keeps an already-suspended bucket suspended', () => {
expect(getNextVersioningState('suspended', false)).toBe('suspended')
})
it('leaves a never-versioned bucket disabled', () => {
expect(getNextVersioningState('disabled', false)).toBe('disabled')
})
})
describe('isSuspendingVersioning', () => {
it('is true only when an actively versioning bucket is being turned off', () => {
expect(isSuspendingVersioning('enabled', false)).toBe(true)
})
it('is false when versioning stays on', () => {
expect(isSuspendingVersioning('enabled', true)).toBe(false)
})
it('is false for an already-suspended bucket, which has nothing left to stop', () => {
expect(isSuspendingVersioning('suspended', false)).toBe(false)
})
it('is false for a bucket that was never versioned', () => {
expect(isSuspendingVersioning('disabled', false)).toBe(false)
})
})
describe('isEnablingVersioning', () => {
it('is true only when a never-versioned bucket is being turned on', () => {
expect(isEnablingVersioning('disabled', true)).toBe(true)
})
it('is false when re-enabling a suspended bucket', () => {
// The user already opted in once, so this is not a first-time enablement.
expect(isEnablingVersioning('suspended', true)).toBe(false)
})
it('is false when versioning is already on', () => {
expect(isEnablingVersioning('enabled', true)).toBe(false)
})
it('is false whenever the switch is off', () => {
for (const state of ['disabled', 'suspended', 'enabled'] as const) {
expect(isEnablingVersioning(state, false), state).toBe(false)
}
})
})
describe('toVersioningStatusUpdate', () => {
it('sends ENABLED when versioning is on', () => {
expect(toVersioningStatusUpdate('enabled')).toBe('ENABLED')
})
it('sends SUSPENDED when versioning is being turned off', () => {
expect(toVersioningStatusUpdate('suspended')).toBe('SUSPENDED')
})
it('sends nothing for a bucket that was never versioned', () => {
expect(toVersioningStatusUpdate('disabled')).toBeUndefined()
})
})