Files
YouTubeDL/tests/helper-lifecycle.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

96 lines
6.8 KiB
JavaScript

import assert from "node:assert/strict";
import fs from "node:fs/promises";
import path from "node:path";
import os from "node:os";
import { createHash } from "node:crypto";
import { execFile } from "node:child_process";
import { promisify } from "node:util";
import { fileURLToPath } from "node:url";
import { chromium } from "playwright";
import { installedHelperRoot } from "./installed-helper.mjs";
const root = path.dirname(path.dirname(fileURLToPath(import.meta.url)));
const artifacts = path.join(root, "test-artifacts");
const installedRoot = await installedHelperRoot();
await fs.mkdir(artifacts, { recursive: true });
const profile = await fs.mkdtemp(path.join(os.tmpdir(), "ytdl-lifecycle-test-"));
const context = await chromium.launchPersistentContext(profile, {
headless: true, acceptDownloads: true,
executablePath: "C:/Program Files (x86)/Microsoft/Edge/Application/msedge.exe",
ignoreDefaultArgs: ["--disable-extensions"], args: ["--enable-unsafe-extension-debugging"],
});
try {
const cdp = await context.browser().newBrowserCDPSession();
const { id } = await cdp.send("Extensions.loadUnpacked", { path: path.join(root, "extension") });
const worker = context.serviceWorkers()[0] || await context.waitForEvent("serviceworker");
const page = await context.newPage();
await page.goto(`chrome-extension://${id}/downloader.html`);
await page.locator('#helper-panel[data-state="running"]').waitFor({ timeout: 90000 });
await page.locator('#setup[open]').waitFor();
await page.locator('#setup-next').click();
await page.locator('#setup-next:not([disabled])').waitFor();
assert.match(await page.locator('#setup-helper-status').textContent(), /компоненты готовы/);
assert.match(await page.locator('#setup-gpu').textContent(), /RTX 5080/);
await page.locator('#setup-next').click();
assert.ok(await page.locator('#setup-folder').inputValue());
await page.locator('#setup-quality').selectOption('1080');
await page.locator('#setup-next').click();
await page.locator('[data-setup-step="3"]').waitFor({state:'visible'});
await page.screenshot({path:path.join(artifacts,'onboarding-native.png'),animations:'disabled'});
await page.locator('#setup-next').click();
await page.locator('#setup').waitFor({state:'hidden'});
const firstRun = await worker.evaluate(() => chrome.storage.local.get(['preferences','onboarding']));
assert.equal(firstRun.onboarding.state,'complete'); assert.equal(firstRun.preferences.quality.height,1080);
await page.reload();
await page.locator('#helper-panel[data-state="running"]').waitFor({timeout:90000});
assert.equal(await page.locator('#setup').evaluate(dialog => dialog.open),false);
await page.locator("#helper-panel > summary").click();
assert.equal(await page.locator('.dependency-row[data-status="installed"]').count(), 5);
await context.route("https://git.lonarpgproxy.space/OwnerLink/YouTubeDL/releases/latest", route => route.fulfill({ contentType: "text/html", body: "<h1>релизов проекта test destination</h1>" }));
const releaseTab = page.waitForEvent("popup");
await page.locator("#helper-install").click();
const popup = await releaseTab;
await popup.waitForURL("https://git.lonarpgproxy.space/OwnerLink/YouTubeDL/releases/latest");
assert.equal(await page.locator("#helper-install").getAttribute("download"), null);
await popup.close();
const installerPath = path.join(artifacts, "YouTubeDL-Helper-Test.exe");
await fs.copyFile(path.join(root, "dist/YouTubeDL-Helper-Setup.exe"), installerPath);
const downloaded = await fs.readFile(installerPath);
assert.equal(downloaded.subarray(0, 2).toString(), "MZ");
assert.equal(createHash("sha256").update(downloaded).digest("hex"), createHash("sha256").update(await fs.readFile(path.join(root,"dist/YouTubeDL-Helper-Setup.exe"))).digest("hex"));
console.log("Extension opens the external release page; installer comes from the separate release asset.");
await page.locator("#helper-remove").click();
await page.locator('#helper-panel[data-state="missing"]').waitFor();
assert.equal(await page.locator('.dependency-row[data-status="installed"]').count(), 0);
await page.locator("#helper-start").click();
await page.locator('#helper-panel[data-state="missing"]').waitFor();
const deadline = Date.now() + 40000;
while (Date.now() < deadline) {
try { await fs.access(path.join(installedRoot,"installation.json")); }
catch { break; }
await new Promise(resolve => setTimeout(resolve, 100));
}
await assert.rejects(fs.access(path.join(installedRoot,"installation.json")));
console.log("Uninstall verified; missing helper cannot report Running.");
const installed = await promisify(execFile)("powershell.exe", ["-NoProfile", "-ExecutionPolicy", "Bypass", "-File", path.join(root, "tools/run-installer-test.ps1"), "-InstallerPath", installerPath], { timeout: 600000 });
console.log(installed.stdout.trim());
await page.locator("#helper-start").click();
await page.locator('#helper-panel[data-state="running"]').waitFor({ timeout: 90000 });
assert.equal(await page.locator('.dependency-row[data-status="installed"]').count(), 5);
assert.equal(await page.locator('.dependency-row button').count(), 0);
assert.match(await page.locator('#helper-message').textContent(), /Автономный комплект/);
assert.match(await page.locator('[data-dependency="python"] .dependency-version').textContent(), /3\.13\./);
const restoredRoot = await installedHelperRoot();
const restoredMarker = JSON.parse((await fs.readFile(path.join(restoredRoot,'installation.json'),'utf8')).replace(/^\uFEFF/,''));
assert.equal(restoredMarker.version,'1.3.0');
await fs.access(path.join(restoredRoot,'YouTubeDL-Manager.exe'));
assert.equal(path.dirname(path.dirname(path.resolve(restoredMarker.current))),path.resolve(restoredRoot),'Manager, marker and registered runtime must share the same physical installation');
if (!await page.locator('#helper-panel').evaluate(panel => panel.open)) await page.locator('#helper-panel > summary').click();
await page.locator('.dependencies summary').click();
await page.screenshot({ path: path.join(artifacts, "helper-components.png"), animations: "disabled" });
await fs.writeFile(path.join(artifacts, "helper-lifecycle.json"), JSON.stringify({ installer: "YouTubeDL-Helper-Setup.exe", externalReleaseLink: "passed", installerSHA256: createHash("sha256").update(downloaded).digest("hex"), firstRun: "passed", firstRunPersistence: "passed", uninstall: "passed", manualStart: "passed", autonomousBundle: "passed" }, null, 2));
console.log("Helper lifecycle passed: external release link, scoped uninstall, missing state, offline installation, manual start and bundled components.");
} finally {
await context.close();
if (path.dirname(path.resolve(profile)) === path.resolve(os.tmpdir()) && path.basename(profile).startsWith("ytdl-lifecycle-test-")) await fs.rm(profile, { recursive: true, force: true });
}