portail-associations/server/emailActions.test.ts

159 lines
4.4 KiB
TypeScript

import { describe, expect, it, vi, beforeEach } from "vitest";
// Mock db module
vi.mock("./db", () => ({
getEmailActionToken: vi.fn(),
getRequestById: vi.fn(),
updateRequest: vi.fn(),
createRequestHistory: vi.fn(),
markTokenAsUsed: vi.fn(),
createEmailActionToken: vi.fn(),
}));
import * as db from "./db";
describe("Email Action Token Logic", () => {
beforeEach(() => {
vi.clearAllMocks();
});
it("should reject an invalid token", async () => {
(db.getEmailActionToken as any).mockResolvedValue(null);
const token = await db.getEmailActionToken("invalid-token");
expect(token).toBeNull();
});
it("should reject an already used token", async () => {
(db.getEmailActionToken as any).mockResolvedValue({
id: 1,
token: "test-token",
requestId: 1,
action: "validee",
used: true,
expiresAt: new Date(Date.now() + 86400000),
usedAt: new Date(),
usedBy: 1,
createdAt: new Date(),
});
const token = await db.getEmailActionToken("test-token");
expect(token).not.toBeNull();
expect(token!.used).toBe(true);
});
it("should reject an expired token", async () => {
const expiredDate = new Date(Date.now() - 86400000); // 1 day ago
(db.getEmailActionToken as any).mockResolvedValue({
id: 1,
token: "expired-token",
requestId: 1,
action: "validee",
used: false,
expiresAt: expiredDate,
usedAt: null,
usedBy: null,
createdAt: new Date(),
});
const token = await db.getEmailActionToken("expired-token");
expect(token).not.toBeNull();
expect(new Date() > token!.expiresAt).toBe(true);
});
it("should accept a valid token for validation", async () => {
const futureDate = new Date(Date.now() + 7 * 86400000); // 7 days from now
(db.getEmailActionToken as any).mockResolvedValue({
id: 1,
token: "valid-token",
requestId: 5,
action: "validee",
used: false,
expiresAt: futureDate,
usedAt: null,
usedBy: null,
createdAt: new Date(),
});
(db.getRequestById as any).mockResolvedValue({
id: 5,
titre: "Subvention test",
type: "subvention_projet",
status: "soumise",
description: "Test description",
montantDemande: 100000,
associationId: 1,
});
const token = await db.getEmailActionToken("valid-token");
expect(token).not.toBeNull();
expect(token!.used).toBe(false);
expect(new Date() < token!.expiresAt).toBe(true);
expect(token!.action).toBe("validee");
const request = await db.getRequestById(token!.requestId);
expect(request).not.toBeNull();
expect(request!.status).not.toBe("validee");
expect(request!.status).not.toBe("refusee");
});
it("should accept a valid token for refusal", async () => {
const futureDate = new Date(Date.now() + 7 * 86400000);
(db.getEmailActionToken as any).mockResolvedValue({
id: 2,
token: "refuse-token",
requestId: 5,
action: "refusee",
used: false,
expiresAt: futureDate,
usedAt: null,
usedBy: null,
createdAt: new Date(),
});
const token = await db.getEmailActionToken("refuse-token");
expect(token).not.toBeNull();
expect(token!.action).toBe("refusee");
});
it("should reject processing an already validated request", async () => {
(db.getRequestById as any).mockResolvedValue({
id: 5,
titre: "Subvention test",
type: "subvention_projet",
status: "validee",
associationId: 1,
});
const request = await db.getRequestById(5);
expect(request!.status === "validee" || request!.status === "refusee").toBe(true);
});
it("should create email action tokens with correct expiry", async () => {
(db.createEmailActionToken as any).mockResolvedValue("new-token");
const expiresAt = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000);
await db.createEmailActionToken({
token: "validate-token-123",
requestId: 10,
action: "validee",
expiresAt,
});
expect(db.createEmailActionToken).toHaveBeenCalledWith({
token: "validate-token-123",
requestId: 10,
action: "validee",
expiresAt,
});
});
it("should mark token as used after processing", async () => {
(db.markTokenAsUsed as any).mockResolvedValue(undefined);
await db.markTokenAsUsed("used-token", 1);
expect(db.markTokenAsUsed).toHaveBeenCalledWith("used-token", 1);
});
});