const request = require("supertest"); const app = require("../src/app"); const prisma = require("../src/config/prisma"); // ------------------------ // Mock du mailer pour éviter envoi réel // ------------------------ jest.mock("../src/config/mailer", () => ({ sendMail: jest.fn().mockResolvedValue(true), })); // ------------------------ // Ce test tourne sur la même base que le reste du dev (500 000 tickets // réels du jeu-concours). On ne touche donc JAMAIS les tables globales // (pas de deleteMany sur claim/participation/ticket/user/lot) : tout ce // que ce fichier crée est identifiable de façon unique et nettoyé dans // afterAll, rien d'autre. // ------------------------ const testEmail = "e2e-flow-test@test.com"; const ticketCode = "ZZE2ETEST1"; let token; let createdTicketId; let settingsBackup; beforeAll(async () => { await prisma.user.deleteMany({ where: { email: testEmail } }); await prisma.ticket.deleteMany({ where: { code: ticketCode } }); // Le parcours a besoin d'un jeu ouvert, quelle que soit la date de début // enregistrée en base (par défaut le 2 octobre 2026) : on la place à hier // le temps du test, puis on la restaure. settingsBackup = await prisma.gameSettings.findFirst({ orderBy: { id: "asc" } }); const hier = new Date(Date.now() - 24 * 60 * 60 * 1000); if (settingsBackup) { await prisma.gameSettings.update({ where: { id: settingsBackup.id }, data: { startDate: hier } }); } else { await prisma.gameSettings.create({ data: { startDate: hier } }); } }); afterAll(async () => { if (settingsBackup) { await prisma.gameSettings.update({ where: { id: settingsBackup.id }, data: { startDate: settingsBackup.startDate } }); } else { await prisma.gameSettings.deleteMany({}); } const user = await prisma.user.findUnique({ where: { email: testEmail } }); if (user) { await prisma.claim.deleteMany({ where: { participation: { userId: user.id } } }); await prisma.participation.deleteMany({ where: { userId: user.id } }); } if (createdTicketId) { await prisma.ticket.delete({ where: { id: createdTicketId } }).catch(() => {}); } if (user) { await prisma.user.delete({ where: { id: user.id } }); } await prisma.$disconnect(); }); describe("THE TIP TOP - FULL E2E FLOW", () => { test("Register user", async () => { const res = await request(app).post("/api/auth/register").send({ firstname: "E2E", lastname: "Test", email: testEmail, password: "Password123!", confirmPassword: "Password123!", }); expect(res.statusCode).toBe(201); }); test("Login user", async () => { await prisma.user.update({ where: { email: testEmail }, data: { isEmailVerified: true }, }); const res = await request(app).post("/api/auth/login").send({ email: testEmail, password: "Password123!", }); expect(res.statusCode).toBe(200); expect(res.body.token).toBeDefined(); token = res.body.token; }); test("Create a dedicated ticket for this test", async () => { const lot = await prisma.lot.findFirst(); expect(lot).not.toBeNull(); const ticket = await prisma.ticket.create({ data: { code: ticketCode, lotId: lot.id }, }); createdTicketId = ticket.id; expect(ticket.code).toBe(ticketCode); }); test("Participate to game", async () => { const res = await request(app) .post("/api/game/participate") .set("Authorization", `Bearer ${token}`) .send({ code: ticketCode }); expect(res.statusCode).toBe(201); expect(res.body.gain).toBeDefined(); }); test("Get my gains", async () => { const res = await request(app) .get("/api/game/my-gains") .set("Authorization", `Bearer ${token}`); expect(res.statusCode).toBe(200); expect(res.body.gains).toBeDefined(); expect(res.body.gains.some((g) => g.ticketCode === ticketCode)).toBe(true); }); test("Admin stats - CLIENT access denied", async () => { const res = await request(app) .get("/api/admin/stats") .set("Authorization", `Bearer ${token}`); expect(res.statusCode).toBe(403); expect(res.body.message || res.body).toBeDefined(); }); });