96 lines
6.8 KiB
JavaScript
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 });
|
|
}
|