Files
YouTubeDL/tests/extension.test.mjs
DepressedCat 5f2aad00f4
Check extension and helper / check (push) Canceled after 0s
Publish YouTubeDL 1.4.5 and website on Gitea
2026-10-10 23:53:17 +03:00

74 lines
5.6 KiB
JavaScript

import test from "node:test";
import assert from "node:assert/strict";
import fs from "node:fs";
import crypto from "node:crypto";
import { canonicalUrl, bytes, duration, progressText, preferenceOptions, stabilizeDownloadSpeed, checkHelperCompatibility } from "../extension/shared.js";
test("URLs accept watch and Shorts but reject arbitrary origins and credentials", () => {
assert.equal(canonicalUrl("https://www.youtube.com/shorts/jNQXAC9IVRw"), "https://www.youtube.com/watch?v=jNQXAC9IVRw");
assert.equal(canonicalUrl("https://youtu.be/jNQXAC9IVRw?list=123"), "https://www.youtube.com/watch?v=jNQXAC9IVRw");
for (const url of ["https://youtube.com.evil/watch?v=jNQXAC9IVRw", "http://youtube.com/watch?v=jNQXAC9IVRw", "https://user@youtube.com/watch?v=jNQXAC9IVRw"]) assert.equal(canonicalUrl(url), null);
});
test("progress labels distinguish download tracks and GPU conversion", () => {
assert.equal(progressText({ stage: "downloading", track: "audio" }), "Скачивание · аудио");
assert.equal(progressText({ stage: "encoding", engine: "nvenc" }), "Перекодирование · NVIDIA NVENC");
assert.equal(progressText({ stage: "encoding", engine: "amf" }), "Перекодирование · AMD AMF");
assert.equal(progressText({ stage: "encoding", engine: "cpu" }), "Перекодирование · CPU");
assert.equal(progressText({ stage: "merging", engine: "copy" }), "Объединение дорожек · без перекодирования");
assert.equal(progressText({ stage: "remuxing", engine: "copy" }), "Подготовка файла · без перекодирования");
assert.equal(progressText({ stage: "finalizing", engine: "copy", message: "Финализация файла" }), "Финализация файла");
assert.equal(progressText({ stage: "audio", engine: "cpu" }), "Обработка аудио · CPU");
assert.equal(duration(3661), "1:01:01");
assert.equal(duration(61), "1:01");
assert.equal(bytes(0), "");
assert.match(bytes(1048576), /1 МБ/);
});
test("saved quality adapts to another video's formats and never upscales", () => {
const metadata = { videos: [{ id: "new-4k", height: 2160, fps: 60, codec: "av01" }, { id: "new-720", height: 720, fps: 30, codec: "avc1" }],
audios: [{ id: "new-audio", language: "en" }] };
const preference = { folder: "D:\\Videos", videoId: "old-format", audioId: "old-audio", quality: { height: 1080, fps: 30, codec: "H.264" }, audioLanguage: "en", codec: "hevc", engine: "nvenc", videoContainer: "mkv" };
const result = preferenceOptions(metadata, preference);
assert.equal(result.videoId, "new-720"); assert.equal(result.audioId, "new-audio");
assert.equal(result.codec, "hevc"); assert.equal(result.container, "mkv"); assert.equal(result.folder, "D:\\Videos");
assert.equal(preferenceOptions(metadata, { ...preference, videoId: "best" }).videoId, "best");
assert.equal(preferenceOptions(metadata, { ...preference, mode: "audio", audioContainer: "mp3" }).container, "mp3");
});
test("fixed extension ID matches the native host allowed origin", () => {
const manifest = JSON.parse(fs.readFileSync(new URL("../extension/manifest.json", import.meta.url)));
const digest = crypto.createHash("sha256").update(Buffer.from(manifest.key, "base64")).digest().subarray(0, 16).toString("hex");
const id = [...digest].map(character => "abcdefghijklmnop"[parseInt(character, 16)]).join("");
assert.equal(id, "ndnoeiaecgmjnjneekaeapeecmmjheli");
assert.ok(manifest.permissions.includes("nativeMessaging"));
assert.ok(!manifest.host_permissions.includes("<all_urls>"));
});
test("brief missing speed samples do not flicker, expire and reset between tracks", () => {
const sample = { id: "speed", status: "running", stage: "downloading", track: "video", speed: 4.2 * 1048576 };
let previous = stabilizeDownloadSpeed(sample, null, 1000);
for (const now of [1200, 1600, 2000, 2400]) {
previous = stabilizeDownloadSpeed({ ...sample, speed: null }, previous, now);
assert.equal(previous.speed, sample.speed);
assert.equal(previous.speedUpdatedAt, 1000, 'Missing samples must not extend the lifetime of the last measurement');
}
assert.equal(stabilizeDownloadSpeed({ ...sample, speed: null }, previous, 2500).speed, null);
assert.equal(stabilizeDownloadSpeed({ ...sample, speed: 0 }, previous, 1200).speed, 0);
assert.equal(stabilizeDownloadSpeed({ ...sample, track: "audio", speed: null }, previous, 1200).speed, null);
assert.equal(stabilizeDownloadSpeed({ ...sample, stage: "merging", speed: "8x" }, previous, 1200).speedUpdatedAt, null);
});
test("helper compatibility detects outdated, newer and unidentifiable versions in both directions", () => {
assert.equal(checkHelperCompatibility({ version: "1.3.2" }, "1.4.5").compatible, true);
assert.equal(checkHelperCompatibility({ bundle: { version: "1.3.2" } }, "1.4.5").compatible, true);
assert.equal(checkHelperCompatibility({ version: "1.3.2.0" }, "1.4.5").compatible, true);
for (const version of ["1.3.0", "1.2.10", undefined, "unknown"]) {
const result = checkHelperCompatibility({ version }, "1.4.5");
assert.equal(result.compatible, false);
assert.equal(result.update, "helper");
}
for (const version of ["1.3.3", "1.3.20", "2.0.0"]) {
const result = checkHelperCompatibility({ version }, "1.4.5");
assert.equal(result.compatible, false);
assert.equal(result.update, "extension");
}
assert.equal(checkHelperCompatibility({ version: "1.3.2" }, "1.4.2").update, "extension");
assert.equal(checkHelperCompatibility({ version: "1.3.2", minimumExtensionVersion: "1.4.6" }, "1.4.5").update, "extension");
});