- Optimize session cloning: replace JSON.parse/stringify with shallow spread (~10x faster for large queues) - Convert blocking fs.existsSync/statSync to async on download hot path - Fix EXDEV cross-device rename in sync saveSettings/saveSession (network drive support) - Fix double-delete bug in applyCompletedCleanupPolicy (package_done + immediate) - Fix dangling runPackageIds/runCompletedPackages in removePackageFromSession - Fix AdmZip partial extraction: use overwrite mode for external fallback - Add null byte stripping to sanitizeFilename (path traversal prevention) - Add 5MB size limit for hash manifest files (OOM prevention) - Add 256KB size limit for link artifact file content check - Deduplicate cleanup code via centralized removePackageFromSession Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
46 lines
2.0 KiB
TypeScript
46 lines
2.0 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { parsePackagesFromLinksText, isHttpLink, sanitizeFilename, formatEta, filenameFromUrl, looksLikeOpaqueFilename } from "../src/main/utils";
|
|
|
|
describe("utils", () => {
|
|
it("validates http links", () => {
|
|
expect(isHttpLink("https://example.com/file")).toBe(true);
|
|
expect(isHttpLink("http://example.com/file")).toBe(true);
|
|
expect(isHttpLink("ftp://example.com")).toBe(false);
|
|
expect(isHttpLink("foo bar")).toBe(false);
|
|
});
|
|
|
|
it("sanitizes filenames", () => {
|
|
expect(sanitizeFilename("foo/bar:baz*")).toBe("foo bar baz");
|
|
expect(sanitizeFilename(" ")).toBe("Paket");
|
|
expect(sanitizeFilename("test\0file.txt")).toBe("testfile.txt");
|
|
expect(sanitizeFilename("\0\0\0")).toBe("Paket");
|
|
});
|
|
|
|
it("parses package markers", () => {
|
|
const parsed = parsePackagesFromLinksText(
|
|
"# package: A\nhttps://a.com/1\nhttps://a.com/2\n# package: B\nhttps://b.com/1\n",
|
|
"Default"
|
|
);
|
|
expect(parsed).toHaveLength(2);
|
|
expect(parsed[0].name).toBe("A");
|
|
expect(parsed[0].links).toHaveLength(2);
|
|
expect(parsed[1].name).toBe("B");
|
|
});
|
|
|
|
it("formats eta", () => {
|
|
expect(formatEta(-1)).toBe("--");
|
|
expect(formatEta(65)).toBe("01:05");
|
|
expect(formatEta(3661)).toBe("01:01:01");
|
|
});
|
|
|
|
it("normalizes filenames from links", () => {
|
|
expect(filenameFromUrl("https://rapidgator.net/file/id/show.part1.rar.html")).toBe("show.part1.rar");
|
|
expect(filenameFromUrl("https://debrid.example/dl/abc?filename=Movie.S01E01.mkv")).toBe("Movie.S01E01.mkv");
|
|
expect(filenameFromUrl("https://debrid.example/dl/%E0%A4%A")).toBe("%E0%A4%A");
|
|
expect(filenameFromUrl("https://debrid.example/dl/e51f6809bb6ca615601f5ac5db433737")).toBe("e51f6809bb6ca615601f5ac5db433737");
|
|
expect(looksLikeOpaqueFilename("download.bin")).toBe(true);
|
|
expect(looksLikeOpaqueFilename("e51f6809bb6ca615601f5ac5db433737")).toBe(true);
|
|
expect(looksLikeOpaqueFilename("movie.part1.rar")).toBe(false);
|
|
});
|
|
});
|