Files
Multi-Debrid-Downloader/tests/clipboard-ipc.test.ts
T
Sucukdeluxe 25ebc55f4f fix: strengthen live recovery and support diagnostics
Apply account and key changes to active queues without a restart and isolate provider attempt cancellation so fallback accounts remain usable. Preserve pause ownership, bound persisted HTTP 416 recovery, reconcile resets with authoritative state, and stabilize package ordering and live update cadence. Correlate rotation, conversion, resume, disk, queue-control, clipboard, and support-export events while redacting sensitive data at every persistent boundary and again in generated bundles. Release as v2.0.31 with updated English documentation and regression coverage.
2026-08-13 11:36:51 +02:00

97 lines
2.9 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from "vitest";
import { writeClipboardTextFromIpc } from "../src/main/clipboard-ipc";
import type { TrustedIpcOptions } from "../src/main/ipc-security";
const electronMocks = vi.hoisted(() => ({
writeText: vi.fn()
}));
const loggerMocks = vi.hoisted(() => ({
info: vi.fn(),
warn: vi.fn()
}));
vi.mock("electron", () => ({
clipboard: {
writeText: electronMocks.writeText
}
}));
vi.mock("../src/main/logger", () => ({
logger: loggerMocks
}));
const trustedOptions: TrustedIpcOptions = {
isPackaged: false,
devServerUrl: "http://localhost:5180",
appPath: "C:\\Program Files\\MDD"
};
function eventFor(url: string) {
return {
senderFrame: { url },
sender: {
getURL: () => url
}
};
}
beforeEach(() => {
electronMocks.writeText.mockReset();
loggerMocks.info.mockReset();
loggerMocks.warn.mockReset();
});
describe("clipboard IPC", () => {
it("writes trusted renderer text through Electron clipboard", () => {
const result = writeClipboardTextFromIpc(
eventFor("http://localhost:5180/downloads"),
"https://rapidgator.net/file/example",
trustedOptions
);
expect(result).toBe(true);
expect(electronMocks.writeText).toHaveBeenCalledOnce();
expect(electronMocks.writeText).toHaveBeenCalledWith("https://rapidgator.net/file/example");
expect(loggerMocks.info).toHaveBeenCalledWith("Zwischenablage geschrieben: bytes=35");
expect(JSON.stringify(loggerMocks.info.mock.calls)).not.toContain("rapidgator.net");
});
it("rejects untrusted renderer calls before touching the clipboard", () => {
expect(() => writeClipboardTextFromIpc(
eventFor("https://attacker.example/downloads"),
"private value",
trustedOptions
)).toThrow("IPC-Absender ist nicht vertrauenswürdig");
expect(electronMocks.writeText).not.toHaveBeenCalled();
});
it("logs native clipboard failures without the copied value", () => {
electronMocks.writeText.mockImplementationOnce(() => {
throw new Error("Clipboard busy");
});
expect(() => writeClipboardTextFromIpc(
eventFor("http://localhost:5180/downloads"),
"private-link-value",
trustedOptions
)).toThrow("Clipboard busy");
expect(loggerMocks.warn).toHaveBeenCalledWith("Zwischenablage-Schreiben fehlgeschlagen: Error: Clipboard busy");
expect(JSON.stringify(loggerMocks.warn.mock.calls)).not.toContain("private-link-value");
});
it("rejects UTF-8 payloads larger than 16 MiB before touching the clipboard", () => {
const oversizedText = "ä".repeat((8 * 1024 * 1024) + 1);
expect(Buffer.byteLength(oversizedText, "utf8")).toBe((16 * 1024 * 1024) + 2);
expect(() => writeClipboardTextFromIpc(
eventFor("http://localhost:5180/downloads"),
oversizedText,
trustedOptions
)).toThrow("Ungültiger Zwischenablageinhalt");
expect(electronMocks.writeText).not.toHaveBeenCalled();
});
});