Barazo default frontend barazo.forum
at main 101 lines 3.2 kB view raw
1/** 2 * Tests for API client auth functions. 3 * Verifies the contract between client functions and the API response shape. 4 */ 5 6import { describe, it, expect } from 'vitest' 7import { http, HttpResponse } from 'msw' 8import { server } from '@/mocks/server' 9import { initiateLogin, refreshSession, initiateCrossPostAuth } from '@/lib/api/client' 10 11const API_URL = '' 12 13describe('initiateLogin', () => { 14 it('returns the redirect URL from the API', async () => { 15 const expectedUrl = 'https://bsky.social/oauth/authorize?client_id=test&request_uri=urn:test' 16 17 server.use( 18 http.get(`${API_URL}/api/auth/login`, ({ request }) => { 19 const url = new URL(request.url) 20 expect(url.searchParams.get('handle')).toBe('jay.bsky.team') 21 return HttpResponse.json({ url: expectedUrl }) 22 }) 23 ) 24 25 const result = await initiateLogin('jay.bsky.team') 26 expect(result).toEqual({ url: expectedUrl }) 27 expect(result.url).toBe(expectedUrl) 28 }) 29 30 it('passes handle as query parameter', async () => { 31 let receivedHandle: string | null = null 32 33 server.use( 34 http.get(`${API_URL}/api/auth/login`, ({ request }) => { 35 const url = new URL(request.url) 36 receivedHandle = url.searchParams.get('handle') 37 return HttpResponse.json({ url: 'https://example.com/oauth' }) 38 }) 39 ) 40 41 await initiateLogin('gui.do') 42 expect(receivedHandle).toBe('gui.do') 43 }) 44 45 it('throws on API error', async () => { 46 server.use( 47 http.get(`${API_URL}/api/auth/login`, () => { 48 return HttpResponse.json({ error: 'Failed to initiate login' }, { status: 502 }) 49 }) 50 ) 51 52 await expect(initiateLogin('bad.handle')).rejects.toThrow('Failed to initiate login') 53 }) 54 55 it('throws on invalid handle', async () => { 56 server.use( 57 http.get(`${API_URL}/api/auth/login`, () => { 58 return HttpResponse.json({ error: 'Invalid handle' }, { status: 400 }) 59 }) 60 ) 61 62 await expect(initiateLogin('')).rejects.toThrow('Invalid handle') 63 }) 64}) 65 66describe('refreshSession', () => { 67 it('returns session data on success', async () => { 68 const result = await refreshSession() 69 expect(result).toHaveProperty('accessToken') 70 expect(result).toHaveProperty('did') 71 expect(result).toHaveProperty('handle') 72 }) 73 74 it('throws on expired session', async () => { 75 server.use( 76 http.post(`${API_URL}/api/auth/refresh`, () => { 77 return HttpResponse.json({ error: 'No refresh token' }, { status: 401 }) 78 }) 79 ) 80 81 await expect(refreshSession()).rejects.toThrow('No refresh token') 82 }) 83}) 84 85describe('initiateCrossPostAuth', () => { 86 it('returns the redirect URL with auth header', async () => { 87 const expectedUrl = 'https://bsky.social/oauth/authorize?scope=crosspost' 88 89 server.use( 90 http.get(`${API_URL}/api/auth/crosspost-authorize`, ({ request }) => { 91 const auth = request.headers.get('Authorization') 92 expect(auth).toBe('Bearer test-token-123') 93 return HttpResponse.json({ url: expectedUrl }) 94 }) 95 ) 96 97 const result = await initiateCrossPostAuth('test-token-123') 98 expect(result).toEqual({ url: expectedUrl }) 99 expect(result.url).toBe(expectedUrl) 100 }) 101})