const request = require("supertest"); const app = require("../src/app"); const prisma = require("../src/config/prisma"); const jwt = require("jsonwebtoken"); const bcrypt = require("bcrypt"); const mailer = require("../src/config/mailer"); jest.mock("../src/config/mailer", () => ({ sendMail: jest.fn() })); const DAY = 86400000; const PREFIX = "gain-"; const CODES = ["GAINTICK01", "GAINTICK02", "GAINTICK03"]; let ctx = {}; async function cleanup() { const us = await prisma.user.findMany({ where: { email: { contains: PREFIX } } }); const ids = us.map((u) => u.id); const ps = await prisma.participation.findMany({ where: { userId: { in: ids } } }); await prisma.claim.deleteMany({ where: { participationId: { in: ps.map((p) => p.id) } } }); await prisma.participation.deleteMany({ where: { userId: { in: ids } } }); await prisma.grandPrizeWinner.deleteMany({ where: { userId: { in: ids } } }); await prisma.ticket.deleteMany({ where: { code: { in: CODES } } }); await prisma.user.deleteMany({ where: { id: { in: ids } } }); } const tk = (u) => jwt.sign({ id: u.id, role: u.role }, process.env.JWT_SECRET, { expiresIn: "1h" }); const jourJ = (d) => prisma.gameSettings.update({ where: { id: ctx.settingsId }, data: { startDate: new Date(Date.now() - d * DAY) }, }); beforeAll(async () => { await cleanup(); const row = await prisma.gameSettings.findFirst({ orderBy: { id: "asc" } }); ctx.settingsId = row.id; ctx.startDateOriginale = row.startDate; ctx.lot = await prisma.lot.findFirst({ orderBy: { id: "asc" } }); for (const c of CODES) await prisma.ticket.create({ data: { code: c, lotId: ctx.lot.id } }); const h = await bcrypt.hash("Password123", 10); ctx.client = await prisma.user.create({ data: { firstname: "Chloe", lastname: "Martin", email: PREFIX + "chloe@test.local", password: h, role: "CLIENT", isEmailVerified: true } }); ctx.tClient = tk(ctx.client); await jourJ(1); }); afterAll(async () => { await prisma.gameSettings.update({ where: { id: ctx.settingsId }, data: { startDate: ctx.startDateOriginale } }); await cleanup(); await prisma.$disconnect(); }); describe("Notification du gain a chaque participation", () => { beforeEach(() => jest.clearAllMocks()); test("le joueur recoit un email decrivant son lot", async () => { mailer.sendMail.mockResolvedValue(true); const res = await request(app) .post("/api/game/participate") .set("Authorization", "Bearer " + ctx.tClient) .send({ code: CODES[0] }) .expect(201); expect(res.body.emailSent).toBe(true); expect(mailer.sendMail).toHaveBeenCalledTimes(1); const envoi = mailer.sendMail.mock.calls[0][0]; expect(envoi.to).toBe(ctx.client.email); expect(envoi.subject).toContain(ctx.lot.name); expect(envoi.html).toContain("Chloe"); expect(envoi.html).toContain(CODES[0]); expect(envoi.html).toContain(ctx.lot.name); }); test("un SMTP en panne n annule pas la participation", async () => { mailer.sendMail.mockRejectedValue(new Error("SMTP indisponible")); const res = await request(app) .post("/api/game/participate") .set("Authorization", "Bearer " + ctx.tClient) .send({ code: CODES[1] }); expect(res.status).toBe(201); expect(res.body.emailSent).toBe(false); // Le gain reste acquis et consultable. const t = await prisma.ticket.findUnique({ where: { code: CODES[1] } }); expect(t.isUsed).toBe(true); const gains = await request(app).get("/api/game/my-gains").set("Authorization", "Bearer " + ctx.tClient).expect(200); expect(gains.body.gains.some((g) => g.ticketCode === CODES[1])).toBe(true); }); test("aucun email si le code est refuse", async () => { mailer.sendMail.mockResolvedValue(true); const rejoue = await request(app).post("/api/game/participate").set("Authorization", "Bearer " + ctx.tClient).send({ code: CODES[0] }); expect(rejoue.status).toBe(409); const inconnu = await request(app).post("/api/game/participate").set("Authorization", "Bearer " + ctx.tClient).send({ code: "INEXISTAN1" }); expect(inconnu.status).toBe(404); await jourJ(45); const horsDelai = await request(app).post("/api/game/participate").set("Authorization", "Bearer " + ctx.tClient).send({ code: CODES[2] }); expect(horsDelai.status).toBe(410); await jourJ(1); expect(mailer.sendMail).not.toHaveBeenCalled(); }); });