Files
lunarfront-app/packages/backend/__tests__/routes/v1/auth.test.ts
Ryan Moon 01d6ff3fa3 Move tests to __tests__ folders, add unit tests for shared utils and services
Restructure tests into __tests__/ directories at package root so they can
be excluded from production builds. Add unit tests for dates, currency,
lookup service, payment method default logic, and tax exemption state
transitions.
2026-03-27 21:14:42 -05:00

167 lines
4.4 KiB
TypeScript

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)
})
})
})