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.
167 lines
4.4 KiB
TypeScript
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)
|
|
})
|
|
})
|
|
})
|