mirror of
https://github.com/supabase/supabase.git
synced 2026-10-06 09:55:06 +03:00
Adds a contract test that runs `createProjectSupabaseClient()` against the real `@supabase/supabase-js` for each Supabase API key format (temporary, publishable, secret, legacy JWT), asserting that client construction succeeds. Also replaces the placeholder key fixtures in the existing unit tests with realistically shaped ones. Previously the tests mocked the SDK entirely and used keys that don't resemble real formats, so an SDK version that rejects a valid key at construction (as `@supabase/supabase-js` 2.110.4 and 2.110.5 did, reverted in #47945 and fixed in supabase/supabase-js#2526) passed CI unnoticed; with this test, such a regression fails on the dependency bump PR itself. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Tests** * Added coverage confirming project clients work with temporary, publishable, secret, and legacy API key formats. * Updated test scenarios to use realistic temporary API key values. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
125 lines
4.5 KiB
TypeScript
125 lines
4.5 KiB
TypeScript
import * as supabaseJs from '@supabase/supabase-js'
|
|
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
|
|
import { createProjectSupabaseClient } from './project-supabase-client'
|
|
import * as apiKeysUtils from '@/data/api-keys/temp-api-keys-utils'
|
|
|
|
vi.mock('@supabase/supabase-js', () => ({
|
|
createClient: vi.fn(),
|
|
}))
|
|
|
|
vi.mock('@/data/api-keys/temp-api-keys-utils', () => ({
|
|
getOrRefreshTemporaryApiKey: vi.fn(),
|
|
}))
|
|
|
|
describe('project-supabase-client', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks()
|
|
})
|
|
|
|
describe('createProjectSupabaseClient', () => {
|
|
it('should create a Supabase client with temporary API key', async () => {
|
|
const mockApiKey = 'sb_temp_nonce1234567890ab_payload1'
|
|
const mockClient = { from: vi.fn() }
|
|
const projectRef = 'test-project-ref'
|
|
const clientEndpoint = 'https://test.supabase.co'
|
|
|
|
vi.mocked(apiKeysUtils.getOrRefreshTemporaryApiKey).mockResolvedValue({
|
|
apiKey: mockApiKey,
|
|
expiryTimeMs: Date.now() + 3600000,
|
|
})
|
|
vi.mocked(supabaseJs.createClient).mockReturnValue(mockClient as any)
|
|
|
|
const result = await createProjectSupabaseClient(projectRef, clientEndpoint)
|
|
|
|
expect(apiKeysUtils.getOrRefreshTemporaryApiKey).toHaveBeenCalledWith(projectRef)
|
|
expect(supabaseJs.createClient).toHaveBeenCalledWith(clientEndpoint, mockApiKey, {
|
|
auth: {
|
|
persistSession: false,
|
|
autoRefreshToken: false,
|
|
detectSessionInUrl: false,
|
|
storage: {
|
|
getItem: expect.any(Function),
|
|
setItem: expect.any(Function),
|
|
removeItem: expect.any(Function),
|
|
},
|
|
},
|
|
})
|
|
expect(result).toBe(mockClient)
|
|
})
|
|
|
|
it('should configure storage to not persist session', async () => {
|
|
const mockApiKey = 'sb_temp_nonce1234567890ab_payload2'
|
|
const mockClient = { from: vi.fn() }
|
|
|
|
vi.mocked(apiKeysUtils.getOrRefreshTemporaryApiKey).mockResolvedValue({
|
|
apiKey: mockApiKey,
|
|
expiryTimeMs: Date.now() + 3600000,
|
|
})
|
|
vi.mocked(supabaseJs.createClient).mockReturnValue(mockClient as any)
|
|
|
|
await createProjectSupabaseClient('ref', 'https://example.com')
|
|
|
|
const config = vi.mocked(supabaseJs.createClient).mock.calls[0][2]
|
|
if (!config?.auth?.storage) throw new Error('storage config is missing')
|
|
const storage = config.auth.storage
|
|
|
|
// Test storage methods return expected values
|
|
expect(storage.getItem('any-key')).toBeNull()
|
|
expect(storage.setItem('key', 'value')).toBeUndefined()
|
|
expect(storage.removeItem('key')).toBeUndefined()
|
|
})
|
|
|
|
it('should throw error if API key retrieval fails', async () => {
|
|
const error = new Error('Failed to get API key')
|
|
vi.mocked(apiKeysUtils.getOrRefreshTemporaryApiKey).mockRejectedValue(error)
|
|
|
|
await expect(createProjectSupabaseClient('ref', 'https://example.com')).rejects.toThrow(
|
|
'Failed to get API key'
|
|
)
|
|
|
|
expect(supabaseJs.createClient).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it('should pass through different project refs and endpoints', async () => {
|
|
const mockApiKey = 'sb_temp_nonce1234567890ab_payload3'
|
|
const mockClient = { from: vi.fn() }
|
|
|
|
vi.mocked(apiKeysUtils.getOrRefreshTemporaryApiKey).mockResolvedValue({
|
|
apiKey: mockApiKey,
|
|
expiryTimeMs: Date.now() + 3600000,
|
|
})
|
|
vi.mocked(supabaseJs.createClient).mockReturnValue(mockClient as any)
|
|
|
|
await createProjectSupabaseClient('project-123', 'https://project123.supabase.co')
|
|
|
|
expect(apiKeysUtils.getOrRefreshTemporaryApiKey).toHaveBeenCalledWith('project-123')
|
|
expect(supabaseJs.createClient).toHaveBeenCalledWith(
|
|
'https://project123.supabase.co',
|
|
mockApiKey,
|
|
expect.any(Object)
|
|
)
|
|
})
|
|
|
|
it('should disable session persistence options', async () => {
|
|
const mockApiKey = 'sb_temp_nonce1234567890ab_payload4'
|
|
const mockClient = { from: vi.fn() }
|
|
|
|
vi.mocked(apiKeysUtils.getOrRefreshTemporaryApiKey).mockResolvedValue({
|
|
apiKey: mockApiKey,
|
|
expiryTimeMs: Date.now() + 3600000,
|
|
})
|
|
vi.mocked(supabaseJs.createClient).mockReturnValue(mockClient as any)
|
|
|
|
await createProjectSupabaseClient('ref', 'https://example.com')
|
|
|
|
const config = vi.mocked(supabaseJs.createClient).mock.calls[0][2]
|
|
if (!config?.auth) throw new Error('auth config is missing')
|
|
|
|
expect(config.auth.persistSession).toBe(false)
|
|
expect(config.auth.autoRefreshToken).toBe(false)
|
|
expect(config.auth.detectSessionInUrl).toBe(false)
|
|
})
|
|
})
|
|
})
|