mirror of
https://github.com/MasterAcnolo/Freedom-Loader.git
synced 2026-11-13 15:09:20 +01:00
test: add unit tests for configuration and download controllers and handle electron app initialization and improve devMode logic
This commit is contained in:
161
test/unit/info.services.test.js
Normal file
161
test/unit/info.services.test.js
Normal 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");
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user