test: add unit tests for configuration and download controllers and handle electron app initialization and improve devMode logic

This commit is contained in:
MasterAcnolo
2026-10-28 21:58:46 +01:00
parent f0f3018f80
commit f650770df7
9 changed files with 629 additions and 15 deletions

View File

@@ -0,0 +1,161 @@
jest.mock("child_process");
jest.mock("../../server/helpers/path.helpers", () => ({
userYtDlp: "/mock/yt-dlp",
denoPath: "/mock/deno",
}));
jest.mock("../../server/helpers/getBrowser.helpers", () => ({
getUserBrowser: jest.fn(() => "firefox"),
}));
jest.mock("../../server/logger", () => ({
logger: {
info: jest.fn(),
error: jest.fn(),
debug: jest.fn(),
warn: jest.fn(),
},
}));
jest.mock("../../server/helpers/parseInfo.helpers", () => ({
parseVideo: jest.fn((data) => ({type: "video", ...data})),
parsePlaylist: jest.fn((data) => ({
type: "playlist",
title: data.title,
count: data.entries ? data.entries.length : 0,
videos: [],
})),
}));
jest.mock("../../server/helpers/playlist.helpers", () => ({
isUrlPlaylist: jest.fn(),
}));
const {execFile} = require("child_process");
const {fetchInfo, fetchNormalizedInfo} = require("../../server/services/info.services");
const {parseVideo, parsePlaylist} = require("../../server/helpers/parseInfo.helpers");
const {isUrlPlaylist} = require("../../server/helpers/playlist.helpers");
const {logger} = require("../../server/logger");
describe("info.services", () => {
beforeEach(() => {
jest.clearAllMocks();
});
describe("fetchInfo", () => {
test("resolves parsed json on success", async () => {
execFile.mockImplementation((cmd, args, opts, cb) => {
cb(null, JSON.stringify({_type: "video", title: "Test"}), "");
});
const result = await fetchInfo("https://youtube.com/watch?v=123");
expect(result).toEqual({_type: "video", title: "Test"});
expect(execFile).toHaveBeenCalled();
});
test("rejects when cookies error in stderr", async () => {
execFile.mockImplementation((cmd, args, opts, cb) => {
cb(null, "", "sign in to confirm you're not a bot");
});
await expect(fetchInfo("https://youtube.com/watch?v=123")).rejects.toThrow(
/Unable to extract cookies/
);
});
test("rejects on exec error", async () => {
execFile.mockImplementation((cmd, args, opts, cb) => {
cb(new Error("spawn failed"), "", "");
});
await expect(fetchInfo("https://youtube.com/watch?v=123")).rejects.toThrow(
"Unable to fetch Info."
);
});
test("rejects when no stdout", async () => {
execFile.mockImplementation((cmd, args, opts, cb) => {
cb(null, "", "");
});
await expect(fetchInfo("https://youtube.com/watch?v=123")).rejects.toThrow(
"No Data Received."
);
});
test("rejects on invalid json", async () => {
execFile.mockImplementation((cmd, args, opts, cb) => {
cb(null, "not json", "");
});
await expect(fetchInfo("https://youtube.com/watch?v=123")).rejects.toThrow(
"JSON unreadable."
);
});
});
describe("fetchNormalizedInfo", () => {
test("normalizes video", async () => {
isUrlPlaylist.mockReturnValue(false);
execFile.mockImplementation((cmd, args, opts, cb) => {
cb(null, JSON.stringify({_type: "video", title: "My Video"}), "");
});
const result = await fetchNormalizedInfo("https://youtube.com/watch?v=123");
expect(result.type).toBe("video");
expect(parseVideo).toHaveBeenCalled();
});
test("normalizes playlist", async () => {
isUrlPlaylist.mockReturnValue(true);
execFile.mockImplementation((cmd, args, opts, cb) => {
cb(
null,
JSON.stringify({
_type: "playlist",
title: "Playlist",
entries: [{id: "1"}, {id: "2"}],
}),
""
);
});
const result = await fetchNormalizedInfo("https://youtube.com/playlist?list=ABC");
expect(result.type).toBe("playlist");
expect(parsePlaylist).toHaveBeenCalled();
});
test("converts playlist with 1 entry to video", async () => {
isUrlPlaylist.mockReturnValue(true);
execFile.mockImplementation((cmd, args, opts, cb) => {
cb(
null,
JSON.stringify({
_type: "playlist",
title: "Playlist",
entries: [{id: "1", title: "Single"}],
}),
""
);
});
const result = await fetchNormalizedInfo("https://youtube.com/playlist?list=ABC");
expect(result.type).toBe("video");
expect(parseVideo).toHaveBeenCalled();
expect(logger.info).toHaveBeenCalledWith(
expect.stringContaining("Playlist with 1 item converted to video")
);
});
test("falls back to single video when playlist fetch fails", async () => {
isUrlPlaylist.mockReturnValue(true);
let callCount = 0;
execFile.mockImplementation((cmd, args, opts, cb) => {
callCount++;
if (callCount === 1) {
cb(new Error("fail"), "", "");
} else {
cb(null, JSON.stringify({_type: "video", title: "Fallback"}), "");
}
});
const result = await fetchNormalizedInfo("https://youtube.com/watch?v=123&list=ABC");
expect(result.type).toBe("video");
expect(callCount).toBe(2);
expect(logger.info).toHaveBeenCalledWith(
expect.stringContaining("Retrying as single video")
);
});
test("throws when url is invalid type", async () => {
await expect(fetchNormalizedInfo(null)).rejects.toThrow("Invalid URL");
});
});
});