import { describe, expect, it, beforeEach, mock } from 'bun:test' import { Elysia } from 'elysia' import { router } from '~/modules/auth/router' // Mock dependencies mock.module('~/middlewares', () => ({ basicAuthMiddleware: mock((headers: Record, set: { status?: number }) => { if (!headers.authorization || headers.authorization !== 'Basic dGVzdDp0ZXN0') { set.status = 401 throw new Error('Unauthenticated.') } }), bearerAuthMiddleware: mock(async (headers: Record, set: { status?: number }) => { if (!headers.authorization || !headers.authorization.startsWith('Bearer ')) { set.status = 401 throw new Error('Unauthenticated.') } return { id: 123, name: 'Test User', email: 'test@example.com', phone: null, image: null, googleId: null, role: 'admin', status: true, createdAt: new Date(), updatedAt: new Date(), } }), })) mock.module('@/user/queries/query', () => ({ default: { getUserByEmail: mock(async (email: string) => { if (email === 'test@example.com') { return { id: 'user-123', name: 'Test User', email: 'test@example.com', role: 'admin', image: null, googleId: null, password: '$2a$10$mockhashedpassword', } } return null }), getVolunteerById: mock(async ({ id }: { id: string }) => { if (id === 'volunteer-123') { return { id: 'vol-456', partnerId: 'partner-789', name: 'Test Volunteer', phone: '+1234567890', gender: 'male', } } return null }), }, })) mock.module('~/helpers/utils', () => ({ passwordVerify: mock((password: string, _hash: string) => { return password === 'correctpassword' }), })) mock.module('~/helpers/jwt', () => ({ sign: mock(async (_payload: unknown) => 'mock-access-token-12345'), })) describe('Auth Router', () => { let app: Elysia beforeEach(() => { app = new Elysia().use(router) }) describe('POST /auth/v1/login', () => { it('should login successfully with valid credentials', async () => { const response = await app.handle( new Request('http://localhost/auth/v1/login', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Basic dGVzdDp0ZXN0', // test:test in base64 }, body: JSON.stringify({ email: 'test@example.com', password: 'correctpassword', }), }), ) expect(response.status).toBe(200) const data = await response.json() expect(data.message).toBe('Logged in.') expect(data.data.accessToken).toBe('mock-access-token-12345') }) it('should fail login with invalid basic auth', async () => { const response = await app.handle( new Request('http://localhost/auth/v1/login', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Basic aW52YWxpZA==', // invalid:invalid in base64 }, body: JSON.stringify({ email: 'test@example.com', password: 'correctpassword', }), }), ) expect(response.status).toBe(401) }) it('should fail login without authorization header', async () => { const response = await app.handle( new Request('http://localhost/auth/v1/login', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ email: 'test@example.com', password: 'password123', }), }), ) expect(response.status).toBe(401) }) it('should validate request body schema', async () => { const response = await app.handle( new Request('http://localhost/auth/v1/login', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Basic dGVzdDp0ZXN0', }, body: JSON.stringify({ email: 'invalid-email', password: 'short', }), }), ) expect(response.status).toBe(422) }) }) describe('GET /auth/v1/info', () => { it('should get user info with valid bearer token', async () => { const response = await app.handle( new Request('http://localhost/auth/v1/info', { method: 'GET', headers: { Authorization: 'Bearer valid-token-123', }, }), ) expect(response.status).toBe(200) const data = await response.json() expect(data.message).toBe('Get user info.') expect(data.data.id).toBe(123) expect(data.data.email).toBe('test@example.com') }) it('should fail with invalid bearer token', async () => { const response = await app.handle( new Request('http://localhost/auth/v1/info', { method: 'GET', headers: { Authorization: 'Invalid token-123', }, }), ) expect(response.status).toBe(401) }) it('should fail without authorization header', async () => { const response = await app.handle( new Request('http://localhost/auth/v1/info', { method: 'GET', }), ) expect(response.status).toBe(401) }) }) })