diff --git a/tests/debrid.test.ts b/tests/debrid.test.ts index 233d83b..c21bce0 100644 --- a/tests/debrid.test.ts +++ b/tests/debrid.test.ts @@ -1400,6 +1400,62 @@ describe("debrid service", () => { } }); + it("rotation per-account timeout: a hanging account is skipped so the next account is tried", async () => { + // Kern des v1.7.168-Fix: haengt Account 1, darf das NICHT die ganze Rotation + // fressen — der Per-Account-Timeout (PER_ACCOUNT_ATTEMPT_TIMEOUT_MS, default 25s) + // bricht NUR acc1 ab (kurzer Cooldown), der Loop probiert acc2. Ohne globales + // Signal (kein download-manager-Wrap) testet das den Per-Account-Timeout isoliert. + const settings = { + ...defaultSettings(), + token: "", + bestToken: "", + allDebridToken: "", + megaLogin: "user1", + megaPassword: "pass1", + megaCredentials: "user1:pass1\nuser2:pass2", + providerOrder: [] as const, + providerPrimary: "megadebrid" as const, + providerSecondary: "none" as const, + providerTertiary: "none" as const, + autoProviderFallback: false + }; + + // API connect schlaegt pro Account schnell fehl (500) -> Web-Fallback (megaWeb). + globalThis.fetch = (async () => new Response("error", { status: 500 })) as typeof fetch; + + let call = 0; + const megaWeb = vi.fn((_link: string, signal?: AbortSignal) => { + call += 1; + if (call === 1) { + // Account 1 haengt, bis sein eigener Per-Account-Timeout das Signal abortet. + return new Promise((_, reject) => { + if (signal?.aborted) { reject(new Error("aborted:acc1-hang")); return; } + signal?.addEventListener("abort", () => reject(new Error("aborted:acc1-hang")), { once: true }); + }); + } + // Account 2 liefert sofort. + return Promise.resolve({ + fileName: "acc2.rar", + directUrl: "https://mega-web.example/acc2.rar", + fileSize: null, + retriesUsed: 0 + }); + }); + + const service = new DebridService(settings, { megaWebUnrestrict: megaWeb }); + vi.useFakeTimers(); + try { + const pending = service.unrestrictLink("https://rapidgator.net/file/rotate-acc"); + // Per-Account-Timeout von acc1 (25s) feuern lassen -> acc1 faellt -> Loop -> acc2. + await vi.advanceTimersByTimeAsync(30000); + const result = await pending; + expect(result.directUrl).toBe("https://mega-web.example/acc2.rar"); + expect(megaWeb).toHaveBeenCalledTimes(2); + } finally { + vi.useRealTimers(); + } + }); + it("respects provider selection and does not append hidden providers", async () => { const settings = { ...defaultSettings(),