lib/auth/__tests__/supabase-provider.test.ts
Rama main · réplica de lectura del repositorio original.
import { NextRequest, NextResponse } from 'next/server'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { supabaseAuthProvider } from '@/lib/auth/providers/supabase'
import { createAuthActionClient } from '@/lib/supabase/server'
vi.mock('@/lib/supabase/server', () => ({
createClient: vi.fn(),
createAuthActionClient: vi.fn()
}))
vi.mock('@/lib/supabase/middleware', () => ({
updateSession: vi.fn(),
exchangeAuthCode: vi.fn()
}))
vi.mock('@/lib/supabase/keys', () => ({
hasSupabasePublicConfig: vi.fn(() => true)
}))
vi.mock('next/headers', () => ({ headers: vi.fn() }))
import { headers } from 'next/headers'
import { exchangeAuthCode, updateSession } from '@/lib/supabase/middleware'
function request(url: string) {
return new NextRequest(url)
}
describe('supabase provider', () => {
const resetPasswordForEmail = vi.fn()
beforeEach(() => {
vi.clearAllMocks()
vi.mocked(createAuthActionClient).mockResolvedValue({
auth: { resetPasswordForEmail }
} as never)
vi.mocked(headers).mockResolvedValue(
new Headers({ origin: 'http://localhost:3000' }) as never
)
})
describe('requestPasswordReset', () => {
it('keeps the legacy allowlisted recovery destination', async () => {
resetPasswordForEmail.mockResolvedValue({ error: null })
const result =
await supabaseAuthProvider.requestPasswordReset!('user@example.com')
expect(result).toEqual({ success: true })
expect(resetPasswordForEmail).toHaveBeenCalledWith('user@example.com', {
redirectTo: 'http://localhost:3000/auth/update-password'
})
})
})
describe('handleSession', () => {
it('exchanges a recovery code arriving at update-password', async () => {
const exchanged = NextResponse.redirect(
'http://localhost:3000/auth/update-password'
)
vi.mocked(exchangeAuthCode).mockResolvedValue(exchanged)
const req = request(
'http://localhost:3000/auth/update-password?code=abc&state=xyz'
)
const response = await supabaseAuthProvider.handleSession!(req)
expect(exchangeAuthCode).toHaveBeenCalledWith(req, 'abc')
expect(updateSession).not.toHaveBeenCalled()
expect(response).toBe(exchanged)
})
it('runs normal session handling without a code', async () => {
const next = NextResponse.next()
vi.mocked(updateSession).mockResolvedValue(next)
const response = await supabaseAuthProvider.handleSession!(
request('http://localhost:3000/auth/update-password')
)
expect(updateSession).toHaveBeenCalledOnce()
expect(exchangeAuthCode).not.toHaveBeenCalled()
expect(response).toBe(next)
})
it('exchanges a sign-up confirmation code arriving at the root', async () => {
const exchanged = NextResponse.redirect('http://localhost:3000/')
vi.mocked(exchangeAuthCode).mockResolvedValue(exchanged)
const req = request('http://localhost:3000/?code=abc')
const response = await supabaseAuthProvider.handleSession!(req)
expect(exchangeAuthCode).toHaveBeenCalledWith(req, 'abc', '?confirmed=1')
expect(updateSession).not.toHaveBeenCalled()
expect(response).toBe(exchanged)
})
it('ignores code params on other paths', async () => {
const next = NextResponse.next()
vi.mocked(updateSession).mockResolvedValue(next)
await supabaseAuthProvider.handleSession!(
request('http://localhost:3000/auth/login?code=abc')
)
expect(updateSession).toHaveBeenCalledOnce()
expect(exchangeAuthCode).not.toHaveBeenCalled()
})
})
})