Files
Multi-Debrid-Downloader/tests/visual/driver-test.tsx
Sucukdeluxe 069babfd54 feat: deliver the redesigned desktop workspace
Rebuild downloads, link collection, settings, history, and statistics around a responsive desktop shell with compact account and queue tables, contextual navigation, persistent update affordances, unified overlays, and accessible keyboard interactions.

Add safe history-folder reveal IPC, responsive 2560/1920/1366/1120 coverage, deterministic visual fixtures, focused component regressions, and release-tree exclusions for internal working files. Bump the public application version to 2.0.13.
2026-08-10 14:15:57 +02:00

157 lines
6.3 KiB
TypeScript

import { useState } from "react";
import { createRoot } from "react-dom/client";
import {
loadVisualCapture,
prepareVisualCapture,
type MainViewId
} from "./ui-driver";
const views: Array<{ id: MainViewId; name: string }> = [
{ id: "downloads", name: "Downloads" },
{ id: "collector", name: "Linksammler" },
{ id: "settings", name: "Einstellungen" },
{ id: "history", name: "Verlauf" },
{ id: "statistics", name: "Statistiken" }
];
function DriverTestApp({ updateAvailable }: { updateAvailable: boolean }) {
const [activeView, setActiveView] = useState<MainViewId>("downloads");
const [collectorOpen, setCollectorOpen] = useState(false);
const [collectorValue, setCollectorValue] = useState("");
const [collectorRows, setCollectorRows] = useState<string[]>([]);
const [accountMenuOpen, setAccountMenuOpen] = useState(false);
const [updateDialogOpen, setUpdateDialogOpen] = useState(updateAvailable);
const [updateTooltipOpen, setUpdateTooltipOpen] = useState(false);
const [infoOpen, setInfoOpen] = useState(false);
return (
<>
<nav aria-label="Hauptnavigation">
{views.map((view) => (
<button
key={view.id}
type="button"
aria-current={activeView === view.id ? "page" : undefined}
onClick={() => setActiveView(view.id)}
>
{view.name}
</button>
))}
</nav>
<main data-visual-active-view={activeView}>
{activeView === "downloads" && (
<>
<div data-visual-region="downloads-sidebar">Download-Seitenleiste</div>
<div data-visual-region="downloads-sidebar-status">3 Pakete aktiv</div>
<div data-visual-region="downloads-toolbar">Download-Werkzeuge</div>
<div data-visual-region="downloads-table-body">
<div role="row">Dokumentation Staffel 1</div>
</div>
<div data-visual-region="downloads-pagination">Seite 1 von 1</div>
<button type="button" onClick={() => setInfoOpen((open) => !open)}>Informationen</button>
{infoOpen && <section aria-label="Informationen zu Downloads">Drei Downloads sind sichtbar.</section>}
</>
)}
{activeView === "collector" && (
<>
<div data-visual-region="collector-sidebar">Linksammler-Seitenleiste</div>
<div data-visual-region="collector-toolbar">Linksammler-Werkzeuge</div>
<button type="button" onClick={() => setCollectorOpen(true)}>Links hinzufügen</button>
{collectorRows.length === 0 && <div data-visual-region="collector-empty-state">Keine Links</div>}
<div data-visual-region="collector-table-body">
{collectorRows.map((link) => <div role="row" key={link}>{link}</div>)}
</div>
</>
)}
{activeView === "settings" && (
<>
<div data-visual-region="settings-sidebar">Einstellungs-Seitenleiste</div>
<button type="button">Accounts</button>
<div data-visual-region="accounts-table-body"><div role="row">Visual Account</div></div>
<button
type="button"
disabled={updateDialogOpen}
onClick={() => setAccountMenuOpen((open) => !open)}
>
Kontomenü
</button>
</>
)}
{activeView === "history" && (
<>
<div data-visual-region="history-sidebar">Verlauf-Seitenleiste</div>
<div data-visual-region="history-toolbar">Verlauf-Werkzeuge</div>
<div data-visual-region="history-table-body"><div role="row">Naturfilm Sammlung</div></div>
<div data-visual-region="history-pagination">Seite 1 von 1</div>
</>
)}
{activeView === "statistics" && (
<>
<div data-visual-region="statistics-sidebar">Statistik-Seitenleiste</div>
<div data-visual-region="statistics-kpis">919,82 GB</div>
<div data-visual-region="statistics-chart">Download-Verlauf</div>
</>
)}
</main>
{collectorOpen && (
<div role="dialog" aria-label="Links hinzufügen">
<textarea aria-label="Links" value={collectorValue} onChange={(event) => setCollectorValue(event.target.value)} />
<button
type="button"
onClick={() => {
setCollectorRows(collectorValue.split(/\r?\n/).map((value) => value.trim()).filter(Boolean));
setCollectorOpen(false);
}}
>
Übernehmen
</button>
</div>
)}
{updateDialogOpen && (
<div role="dialog" aria-label="Update installieren">
<strong>Update installieren</strong>
<button type="button" onClick={() => setUpdateDialogOpen(false)}>Später</button>
</div>
)}
{accountMenuOpen && (
<div role="menu" aria-label="Kontomenü">
<button
type="button"
aria-label="Update verfügbar"
onMouseEnter={() => setUpdateTooltipOpen(true)}
onFocus={() => setUpdateTooltipOpen(true)}
>
Update verfügbar
</button>
</div>
)}
{updateTooltipOpen && <div role="tooltip" aria-label="Update verfügbar">Version 9.9.9 verfügbar</div>}
</>
);
}
async function startDriverTest(): Promise<void> {
const rootElement = document.getElementById("root");
if (!rootElement) {
throw new Error("Root element fehlt");
}
const captureName = new URLSearchParams(window.location.search).get("capture");
if (!captureName) {
throw new Error("Capture fehlt");
}
try {
const capture = await loadVisualCapture(captureName);
createRoot(rootElement).render(<DriverTestApp updateAvailable={capture.scenario === "update"} />);
await new Promise<void>((resolve) => requestAnimationFrame(() => requestAnimationFrame(() => resolve())));
await prepareVisualCapture(capture, document);
await new Promise<void>((resolve) => requestAnimationFrame(() => requestAnimationFrame(() => resolve())));
document.documentElement.dataset.visualReady = "true";
} catch (error) {
delete document.documentElement.dataset.visualReady;
rootElement.dataset.visualError = "true";
rootElement.textContent = `Visual-Harness-Fehler: ${error instanceof Error ? error.message : String(error)}`;
}
}
void startDriverTest();