import { describe, it, expect, beforeAll, beforeEach, afterAll } from 'bun:test' import type { FastifyInstance } from 'fastify' import { createTestApp, cleanDb, seedTestCompany, TEST_COMPANY_ID } from '../../../src/test/helpers.js' describe('Auth routes', () => { let app: FastifyInstance beforeAll(async () => { app = await createTestApp() }) beforeEach(async () => { await cleanDb(app) await seedTestCompany(app) }) afterAll(async () => { await app.close() }) describe('POST /v1/auth/register', () => { it('creates a user and returns token', async () => { const response = await app.inject({ method: 'POST', url: '/v1/auth/register', headers: { 'x-company-id': TEST_COMPANY_ID }, payload: { email: 'staff@musicstore.com', password: 'securepassword', firstName: 'Jane', lastName: 'Doe', role: 'staff', }, }) expect(response.statusCode).toBe(201) const body = response.json() expect(body.user.email).toBe('staff@musicstore.com') expect(body.user.firstName).toBe('Jane') expect(body.user.role).toBe('staff') expect(body.token).toBeDefined() expect(body.user.passwordHash).toBeUndefined() }) it('rejects duplicate email within same company', async () => { await app.inject({ method: 'POST', url: '/v1/auth/register', headers: { 'x-company-id': TEST_COMPANY_ID }, payload: { email: 'dupe@test.com', password: 'password123', firstName: 'First', lastName: 'User', }, }) const response = await app.inject({ method: 'POST', url: '/v1/auth/register', headers: { 'x-company-id': TEST_COMPANY_ID }, payload: { email: 'dupe@test.com', password: 'password456', firstName: 'Second', lastName: 'User', }, }) expect(response.statusCode).toBe(409) }) it('rejects invalid email', async () => { const response = await app.inject({ method: 'POST', url: '/v1/auth/register', headers: { 'x-company-id': TEST_COMPANY_ID }, payload: { email: 'not-an-email', password: 'password123', firstName: 'Bad', lastName: 'Email', }, }) expect(response.statusCode).toBe(400) }) it('rejects short password', async () => { const response = await app.inject({ method: 'POST', url: '/v1/auth/register', headers: { 'x-company-id': TEST_COMPANY_ID }, payload: { email: 'short@test.com', password: '123', firstName: 'Short', lastName: 'Pass', }, }) expect(response.statusCode).toBe(400) }) }) describe('POST /v1/auth/login', () => { beforeEach(async () => { await app.inject({ method: 'POST', url: '/v1/auth/register', headers: { 'x-company-id': TEST_COMPANY_ID }, payload: { email: 'login@test.com', password: 'correctpassword', firstName: 'Login', lastName: 'User', }, }) }) it('returns token with valid credentials', async () => { const response = await app.inject({ method: 'POST', url: '/v1/auth/login', headers: { 'x-company-id': TEST_COMPANY_ID }, payload: { email: 'login@test.com', password: 'correctpassword', }, }) expect(response.statusCode).toBe(200) const body = response.json() expect(body.token).toBeDefined() expect(body.user.email).toBe('login@test.com') }) it('rejects wrong password', async () => { const response = await app.inject({ method: 'POST', url: '/v1/auth/login', headers: { 'x-company-id': TEST_COMPANY_ID }, payload: { email: 'login@test.com', password: 'wrongpassword', }, }) expect(response.statusCode).toBe(401) }) it('rejects nonexistent email', async () => { const response = await app.inject({ method: 'POST', url: '/v1/auth/login', headers: { 'x-company-id': TEST_COMPANY_ID }, payload: { email: 'nobody@test.com', password: 'whatever', }, }) expect(response.statusCode).toBe(401) }) }) })