Checkpoint: Ajout de l'onglet "Paramétrage" dans la page Ventilation FreePro :

- Table DB freeproSettings (URL portail, credentials, fréquence, date antériorité, statut dernière récupération)
- Service freeproAutoImport.ts : connexion HTTP au portail FreePro, téléchargement CSV, pipeline d'import
- Procédures tRPC : getSettings, saveSettings, testConnection, forceImport
- Job périodique en mémoire (daily/weekly/monthly) via setInterval
- Frontend : wrapper Tabs (onglet 1 = Import & Historique, onglet 2 = Paramétrage)
- Onglet Paramétrage : credentials, fréquence, date antériorité, bouton "Forcer récupération", statut
- Tests unitaires : 8 tests passés
This commit is contained in:
Manus
2026-06-08 09:24:05 -04:00
parent 51830b88be
commit e32d540bc9
10 changed files with 3615 additions and 295 deletions

View File

@@ -0,0 +1,101 @@
/**
* Tests unitaires pour le module FreePro Settings
* Couvre : helpers DB, service auto-import, procédures tRPC
*/
import { describe, it, expect, vi, beforeEach } from "vitest";
// ── Tests helpers freeproAutoImport ────────────────────────────────────────
describe("frequencyToMs", () => {
it("retourne 0 pour manual", async () => {
const { frequencyToMs } = await import("./freeproAutoImport");
expect(frequencyToMs("manual")).toBe(0);
});
it("retourne 24h en ms pour daily", async () => {
const { frequencyToMs } = await import("./freeproAutoImport");
expect(frequencyToMs("daily")).toBe(24 * 60 * 60 * 1000);
});
it("retourne 7j en ms pour weekly", async () => {
const { frequencyToMs } = await import("./freeproAutoImport");
expect(frequencyToMs("weekly")).toBe(7 * 24 * 60 * 60 * 1000);
});
it("retourne 30j en ms pour monthly", async () => {
const { frequencyToMs } = await import("./freeproAutoImport");
expect(frequencyToMs("monthly")).toBe(30 * 24 * 60 * 60 * 1000);
});
it("retourne 0 pour une valeur inconnue", async () => {
const { frequencyToMs } = await import("./freeproAutoImport");
expect(frequencyToMs("unknown")).toBe(0);
});
});
// ── Tests runFreeproAutoImport ─────────────────────────────────────────────
describe("runFreeproAutoImport", () => {
beforeEach(() => {
vi.resetModules();
});
it("retourne un message d'erreur si les paramètres ne sont pas configurés", async () => {
vi.doMock("./db", () => ({
getFreeproSettings: vi.fn().mockResolvedValue(null),
updateFreeproLastRun: vi.fn().mockResolvedValue(undefined),
getFreeproImportsByUser: vi.fn().mockResolvedValue([]),
createFreeproImport: vi.fn().mockResolvedValue(1),
}));
const { runFreeproAutoImport } = await import("./freeproAutoImport");
const result = await runFreeproAutoImport(999);
expect(result.success).toBe(false);
expect(result.message).toContain("Paramètres FreePro non configurés");
});
it("retourne une erreur si les identifiants sont manquants", async () => {
vi.doMock("./db", () => ({
getFreeproSettings: vi.fn().mockResolvedValue({
id: 1,
userId: 1,
portalUrl: "https://pro.free.fr",
loginEmail: null,
loginPassword: null,
frequency: "manual",
maxAnteriority: null,
autoEnabled: 0,
lastSuccessAt: null,
lastStatus: null,
lastImportCount: 0,
createdAt: new Date(),
updatedAt: new Date(),
}),
updateFreeproLastRun: vi.fn().mockResolvedValue(undefined),
getFreeproImportsByUser: vi.fn().mockResolvedValue([]),
createFreeproImport: vi.fn().mockResolvedValue(1),
}));
const { runFreeproAutoImport } = await import("./freeproAutoImport");
const result = await runFreeproAutoImport(1);
expect(result.success).toBe(false);
expect(result.message).toContain("Identifiants FreePro non configurés");
});
});
// ── Tests startFreeproAutoJob / stopFreeproAutoJob ─────────────────────────
describe("startFreeproAutoJob / stopFreeproAutoJob", () => {
it("démarre et arrête un job sans erreur", async () => {
const { startFreeproAutoJob, stopFreeproAutoJob } = await import("./freeproAutoImport");
// Utiliser un intervalle très long pour ne pas déclencher le callback
startFreeproAutoJob(99999, 999999999);
// Arrêter immédiatement
stopFreeproAutoJob(99999);
// Arrêter à nouveau (ne doit pas lever d'erreur)
stopFreeproAutoJob(99999);
});
});