import test from "ava";
import { PrismaClient } from '@prisma/client';
import { PrismaPg } from '@prisma/adapter-pg';
import request from 'supertest';
import jwt from 'jsonwebtoken';
import 'dotenv/config';
import { Express } from 'express';
import { createApp } from '../../src/createApp';
let prisma: PrismaClient;
let app: Express;
test.before(() => {
process.env.NODE_ENV = 'test';
process.env.JWT_SECRET = 'test-secret-key';
const connectionString = process.env.DATABASE_URL || 'postgres://user:password@orbit_db:5432/orbit_test';
const adapter = new PrismaPg({ connectionString });
prisma = new PrismaClient({ adapter });
// Create Express app with test Prisma client
app = createApp(prisma);
});
test.beforeEach(async () => {
// Clean database before each test
try {
await prisma.user.deleteMany({});
} catch (err) {
console.error('Error cleaning test DB:', err);
}
});
test.after.always(async () => {
await prisma?.$disconnect();
});
test("POST /users creates a new user and returns JWT token", async (t) => {
const userData = {
email: "falamansa@example.com",
firstName: "Fala",
lastName: "Mansa",
password: "IscreviSeuNomeNaAreia"
};
const response = await request(app)
.post('/users')
.send(userData)
.expect('Content-Type', /json/)
.expect(201);
// Should return a JWT token
t.truthy(response.body.token);
// Verify the token is valid
const decoded = jwt.verify(response.body.token, process.env.JWT_SECRET!) as any;
t.is(decoded.email, userData.email);
t.truthy(decoded.userId);
// Verify user was created in database
const dbUser = await prisma.user.findUnique({
where: { email: userData.email }
});
t.truthy(dbUser);
t.is(dbUser!.email, userData.email);
t.is(dbUser!.firstName, userData.firstName);
t.is(dbUser!.lastName, userData.lastName);
});
test("POST /users returns 400 for missing required fields", async (t) => {
const response = await request(app)
.post('/users')
.send({
email: "invalid@example.com"
// Missing firstName and password
})
.expect('Content-Type', /json/)
.expect(400);
t.truthy(response.body.error);
t.is(response.body.error, "Campos faltantes"); // TODO: i18n?
t.truthy(response.body.missing);
t.true(response.body.missing.includes('password'));
t.true(response.body.missing.includes('firstName'));
});
test("POST /users returns 409 for duplicate email", async (t) => {
const email = "duplicate@example.com";
// Create first user
await prisma.user.create({
data: {
email,
firstName: "First",
lastName: "User",
encryptedPassword: "$2a$10$test"
}
});
// Try to create second user with same email
const response = await request(app)
.post('/users')
.send({
email,
firstName: "Second",
lastName: "User",
password: "hunter2"
})
.expect('Content-Type', /json/)
.expect(409);
t.truthy(response.body.error);
});
test("createApp successfully integrates with Prisma and Express", async (t) => {
// Test that the app factory works correctly
const testApp = createApp(prisma);
t.truthy(testApp);
t.is(typeof testApp.use, 'function');
t.is(typeof testApp.listen, 'function');
// Verify the app has the prisma client in locals
t.is(testApp.locals.prisma, prisma);
});