mirror of
https://github.com/supabase/supabase.git
synced 2026-10-12 12:55:06 +03:00
## 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? This is a follow up to #38170 adding unit tests for the functions and e2e tests for the feature. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Tests** * Added comprehensive test suites covering access token schemas, token utilities (sorting, filtering, mapping, formatting, and expiration logic), and permission utilities (action sorting and resource toggle behavior). These tests exercise validation rules, edge cases, deterministic date handling, immutability, and multiple branch scenarios to improve reliability and coverage. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
193 lines
6.3 KiB
TypeScript
193 lines
6.3 KiB
TypeScript
import { describe, it, expect } from 'vitest'
|
|
import { PermissionRowSchema, TokenSchema } from './AccessToken.schemas'
|
|
|
|
const validTokenData = {
|
|
tokenName: 'My Token',
|
|
expiresAt: 'day',
|
|
resourceAccess: 'all-orgs' as const,
|
|
permissionRows: [{ resource: 'organization:billing', actions: ['read'] }],
|
|
}
|
|
|
|
// --- PermissionRowSchema ---
|
|
|
|
describe('PermissionRowSchema', () => {
|
|
it('should pass for a valid permission row', () => {
|
|
const result = PermissionRowSchema.safeParse({
|
|
resource: 'organization:billing',
|
|
actions: ['read'],
|
|
})
|
|
expect(result.success).toBe(true)
|
|
})
|
|
|
|
it('should fail when resource is empty', () => {
|
|
const result = PermissionRowSchema.safeParse({
|
|
resource: '',
|
|
actions: ['read'],
|
|
})
|
|
expect(result.success).toBe(false)
|
|
if (!result.success) {
|
|
expect(result.error.issues[0].message).toBe('Please select a resource')
|
|
}
|
|
})
|
|
|
|
it('should fail when actions is empty', () => {
|
|
const result = PermissionRowSchema.safeParse({
|
|
resource: 'organization:billing',
|
|
actions: [],
|
|
})
|
|
expect(result.success).toBe(false)
|
|
if (!result.success) {
|
|
expect(result.error.issues[0].message).toBe('Please select at least one action')
|
|
}
|
|
})
|
|
|
|
it('should fail when resource is missing', () => {
|
|
const result = PermissionRowSchema.safeParse({ actions: ['read'] })
|
|
expect(result.success).toBe(false)
|
|
})
|
|
|
|
it('should fail when actions is missing', () => {
|
|
const result = PermissionRowSchema.safeParse({ resource: 'organization:billing' })
|
|
expect(result.success).toBe(false)
|
|
})
|
|
})
|
|
|
|
// --- TokenSchema ---
|
|
|
|
describe('TokenSchema', () => {
|
|
it('should pass for valid token data', () => {
|
|
const result = TokenSchema.safeParse(validTokenData)
|
|
expect(result.success).toBe(true)
|
|
})
|
|
|
|
it('should fail when tokenName is empty', () => {
|
|
const result = TokenSchema.safeParse({ ...validTokenData, tokenName: '' })
|
|
expect(result.success).toBe(false)
|
|
if (!result.success) {
|
|
const nameError = result.error.issues.find((i) => i.path.includes('tokenName'))
|
|
expect(nameError?.message).toBe('Please enter a name for the token')
|
|
}
|
|
})
|
|
|
|
it('should fail when tokenName is missing', () => {
|
|
const { tokenName, ...rest } = validTokenData
|
|
const result = TokenSchema.safeParse(rest)
|
|
expect(result.success).toBe(false)
|
|
})
|
|
|
|
it('should fail when permissionRows is empty', () => {
|
|
const result = TokenSchema.safeParse({ ...validTokenData, permissionRows: [] })
|
|
expect(result.success).toBe(false)
|
|
if (!result.success) {
|
|
const permError = result.error.issues.find((i) => i.path.includes('permissionRows'))
|
|
expect(permError?.message).toBe('Please configure at least one permission')
|
|
}
|
|
})
|
|
|
|
it('should fail when resourceAccess is not a valid enum value', () => {
|
|
const result = TokenSchema.safeParse({ ...validTokenData, resourceAccess: 'invalid' })
|
|
expect(result.success).toBe(false)
|
|
})
|
|
|
|
it('should accept all valid resourceAccess enum values', () => {
|
|
for (const value of ['all-orgs', 'selected-orgs', 'selected-projects'] as const) {
|
|
const result = TokenSchema.safeParse({ ...validTokenData, resourceAccess: value })
|
|
expect(result.success).toBe(true)
|
|
}
|
|
})
|
|
|
|
describe('expiresAt preprocessing', () => {
|
|
it('should convert "never" to undefined', () => {
|
|
const result = TokenSchema.safeParse({ ...validTokenData, expiresAt: 'never' })
|
|
expect(result.success).toBe(true)
|
|
if (result.success) {
|
|
expect(result.data.expiresAt).toBeUndefined()
|
|
}
|
|
})
|
|
|
|
it('should pass through other string values', () => {
|
|
const result = TokenSchema.safeParse({ ...validTokenData, expiresAt: 'day' })
|
|
expect(result.success).toBe(true)
|
|
if (result.success) {
|
|
expect(result.data.expiresAt).toBe('day')
|
|
}
|
|
})
|
|
|
|
it('should allow expiresAt to be omitted', () => {
|
|
const { expiresAt, ...rest } = validTokenData
|
|
const result = TokenSchema.safeParse(rest)
|
|
expect(result.success).toBe(true)
|
|
})
|
|
})
|
|
|
|
describe('custom expiry refinement', () => {
|
|
it('should fail when expiresAt is "custom" and customExpiryDate is not provided', () => {
|
|
const result = TokenSchema.safeParse({
|
|
...validTokenData,
|
|
expiresAt: 'custom',
|
|
customExpiryDate: undefined,
|
|
})
|
|
expect(result.success).toBe(false)
|
|
if (!result.success) {
|
|
const customError = result.error.issues.find((i) => i.path.includes('expiresAt'))
|
|
expect(customError?.message).toBe('Please select a custom expiry date')
|
|
}
|
|
})
|
|
|
|
it('should fail when expiresAt is "custom" and customExpiryDate is empty string', () => {
|
|
const result = TokenSchema.safeParse({
|
|
...validTokenData,
|
|
expiresAt: 'custom',
|
|
customExpiryDate: '',
|
|
})
|
|
expect(result.success).toBe(false)
|
|
})
|
|
|
|
it('should pass when expiresAt is "custom" and customExpiryDate is provided', () => {
|
|
const result = TokenSchema.safeParse({
|
|
...validTokenData,
|
|
expiresAt: 'custom',
|
|
customExpiryDate: '2026-12-31T00:00:00Z',
|
|
})
|
|
expect(result.success).toBe(true)
|
|
})
|
|
|
|
it('should pass when expiresAt is not "custom" even without customExpiryDate', () => {
|
|
const result = TokenSchema.safeParse({
|
|
...validTokenData,
|
|
expiresAt: 'day',
|
|
})
|
|
expect(result.success).toBe(true)
|
|
})
|
|
})
|
|
|
|
describe('nested permissionRows validation', () => {
|
|
it('should fail when a permission row has an empty resource', () => {
|
|
const result = TokenSchema.safeParse({
|
|
...validTokenData,
|
|
permissionRows: [{ resource: '', actions: ['read'] }],
|
|
})
|
|
expect(result.success).toBe(false)
|
|
})
|
|
|
|
it('should fail when a permission row has empty actions', () => {
|
|
const result = TokenSchema.safeParse({
|
|
...validTokenData,
|
|
permissionRows: [{ resource: 'organization:billing', actions: [] }],
|
|
})
|
|
expect(result.success).toBe(false)
|
|
})
|
|
|
|
it('should pass with multiple valid permission rows', () => {
|
|
const result = TokenSchema.safeParse({
|
|
...validTokenData,
|
|
permissionRows: [
|
|
{ resource: 'organization:billing', actions: ['read'] },
|
|
{ resource: 'organization:members', actions: ['read', 'write'] },
|
|
],
|
|
})
|
|
expect(result.success).toBe(true)
|
|
})
|
|
})
|
|
})
|