Luigit
repositories / dotfiles

dotfiles

bugabingas dorkfiles

owned by admin

quickshell/nuguland/popout-catalog.test.mjs

Raw
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import vm from "node:vm";

const qml = readFileSync(new URL("./SurfaceManager.qml", import.meta.url), "utf8");
assert.match(qml, /import "popoutCatalog\.js" as PopoutCatalog/);
const catalogSource = readFileSync(new URL("./popoutCatalog.js", import.meta.url), "utf8");
const catalog = vm.createContext({});
vm.runInContext(catalogSource.replace(/^\.pragma library\s*/, ""), catalog);
const diagnostics = vm.createContext({ PopoutCatalog: catalog });
vm.runInContext(readFileSync(new URL("./diagnostics.js", import.meta.url), "utf8").replace(/^\.(?:pragma|import).*$/gm, ""), diagnostics);
const start = qml.indexOf("    function parseRect(");
const end = qml.indexOf("    Timer {", start);
assert.ok(start >= 0 && end > start, "execute the actual SurfaceManager functions");
const surfaces = {
    screenWidth: 0, screenHeight: 0, barHeight: 34, vertical: false,
    goldenRatio: 1.61803, powerService: null, PopoutCatalog: catalog,
    DiagnosticData: diagnostics, operationId: 0, console: { info() {} },
    popoutName: "clock", popoutAnchor: { x: 100, y: 0, width: 40, height: 34 },
    popoutOpen: false, popoutClosing: false, popoutPhase: "closed", popoutOutput: "",
    popoutProgress: 0, activeLoaderName: "", pendingLoaderName: "", removingLoaderName: "",
    previousContent: {}, lastInteraction: "", lastCloseReason: "", dismissing() {}, niriService: null, returnWindowId: null,
    Qt: { rect: (x, y, width, height) => ({ x, y, width, height }) },
    openTimer: { stop() {}, restart() {} }, unloadTimer: { stop() {} },
};
surfaces.root = surfaces;
vm.createContext(surfaces);
vm.runInContext(qml.slice(start, end), surfaces);
const plain = value => JSON.parse(JSON.stringify(value));

// The public catalog is descriptive only: preserve its exact serialized shape and order.
const expectedCatalog = {
    host: "PopoutHost.qml",
    loaderPolicy: "single-active-loader-with-close-retention",
    completeContent: true,
    entries: {
        clock: { component: "calendar-agenda", source: "Time.qml", visual: ["clock", "date", "calendar-grid", "agenda"] },
        system: { component: "system-resources", source: "Resources.qml", visual: ["identity-card", "live-metrics", "sparklines", "issues-band", "top-processes"] },
        notifications: { component: "notification-history", source: "Notifications.qml", visual: ["summary", "attention", "actions"] },
        tray: { component: "tray-menu-host", source: "Tray.qml", visual: ["items", "attention", "native-menu-host"] },
        media: { component: "media-controls", source: "Media.qml", visual: ["active-player", "transport", "progress", "selection"] },
        noko: { component: "speech-transcription", source: "Noko.qml noko.mjs", visual: ["doctor", "setup", "record", "history"] },
        clipboard: { component: "clipboard-history", source: "Clipboard.qml", visual: ["search", "cards", "thumbnails", "private-mode"] },
        vault: { component: "vault-browser", source: "Vault.qml VaultPanel.qml vault-native", visual: ["search", "favorites", "details", "totp", "unlock"] },
        launcher: { component: "app-launcher", source: "Launcher.qml", visual: ["app-search", "desktop-icons", "desktop-actions", "desktop-entry-details"] },
        audio: { component: "audio-mixer", source: "Audio.qml", visual: ["sinks", "sources", "streams", "mute"] },
        brightness: { component: "brightness-control", source: "Brightness.qml", visual: ["level", "luminance-shader", "osd"] },
        connectivity: { component: "connectivity-panel", source: "Network.qml+Bluetooth.qml", visual: ["network", "wifi", "bluetooth", "devices"] },
        power: { component: "power-battery", source: "Power.qml", visual: ["battery", "profile", "session", "confirmation"] },
    },
};
assert.equal(surfaces.popoutContentCatalog(), JSON.stringify(expectedCatalog));
const heights = { clock: 580, system: 600, notifications: 460, tray: 440, media: 420, noko: 560, clipboard: 560, vault: 580, launcher: 432, audio: 520, brightness: 340, connectivity: 540, power: 188 };
assert.deepEqual(Object.keys(heights), Object.keys(expectedCatalog.entries));

const widths = { clock: 760, system: 780, notifications: 560, tray: 520, media: 560, noko: 640, clipboard: 520, vault: 840, launcher: 760, audio: 488, brightness: 488, connectivity: 620, power: 368 };
for (const [screenWidth, vertical] of [[0, false], [300, false], [1366, false], [2560, false], [1366, true], [34, true], [35, true]]) {
    Object.assign(surfaces, { screenWidth, vertical });
    const available = screenWidth - (vertical ? 34 : 0);
    for (const [name, height] of Object.entries(heights)) {
        const width = available > 0 ? Math.min(widths[name], Math.max(1, available - 16)) : widths[name];
        assert.equal(surfaces.popoutWidth(name), width);
        assert.deepEqual(plain(surfaces.popoutContentSize(name)), { width, height }, `${name}: width ${screenWidth}, vertical ${vertical}`);
    }
}

Object.assign(surfaces, { screenWidth: 1366, vertical: false });
for (const name of ["", "unknown", "screenshots", "toString", "constructor", "__proto__", null, undefined, 42]) {
    assert.deepEqual(plain(surfaces.popoutContentSize(name)), { width: 520, height: 300 }, `unknown name ${String(name)}`);
}
assert.deepEqual(plain(surfaces.popoutContentSize({ toString: () => "clock" })), { width: 760, height: 580 });

for (const [screenHeight, vertical, ceiling] of [[0, false, 680], [600, false, 518], [600, true, 552], [200, false, 260], [1080, false, 998]]) {
    Object.assign(surfaces, { screenHeight, vertical });
    assert.equal(surfaces.heightBudget(2000), ceiling);
    assert.equal(surfaces.heightBudget(0), 220);
    assert.equal(surfaces.heightBudget("300"), Math.min(ceiling, 300));
    for (const [name, height] of Object.entries(heights)) {
        assert.equal(surfaces.popoutContentSize(name).height, Math.min(ceiling, height), `${name}: screen height ${screenHeight}, vertical ${vertical}`);
    }
}

// Read fresh synthetic power state each time, including absent battery/devices.
let powerState = {};
let powerReads = 0;
surfaces.powerService = { stateJson() { powerReads++; return JSON.stringify(powerState); } };
Object.assign(surfaces, { screenWidth: 1366, screenHeight: 1080, vertical: false });
for (const [state, height] of [
    [{}, 188],
    [{ battery: null, externalDevices: null }, 188],
    [{ battery: { present: false }, externalDevices: [{}] }, 232],
    [{ battery: { present: true } }, 248],
    [{ battery: { present: true }, externalDevices: [] }, 248],
    [{ battery: { present: true }, externalDevices: [{}] }, 292],
    [{ battery: { present: true }, externalDevices: [{}, {}] }, 292],
    [{ battery: { present: true }, externalDevices: [{}, {}, {}] }, 332],
    [{ pendingConfirmation: 'reboot' }, 304],
    [{ battery: { present: true }, pendingConfirmation: 'poweroff' }, 364],
]) {
    powerState = state;
    const before = powerReads;
    assert.deepEqual(plain(surfaces.popoutContentSize("power")), { width: 368, height });
    assert.equal(powerReads, before + 1, "power sizing reads the live service once");
    assert.deepEqual(plain(surfaces.powerContentSize()), { width: 368, height });
}
surfaces.screenHeight = 200;
assert.equal(surfaces.popoutContentSize("power").height, 260, "dynamic power height still respects the budget");
surfaces.powerService = null;
assert.deepEqual(plain(surfaces.popoutContentSize("power")), { width: 368, height: 188 });

for (const name of ['media', 'tray']) {
    let rows = [];
    surfaces[`${name}Service`] = { stateJson: () => JSON.stringify({ [name === 'media' ? 'players' : 'items']: rows }) };
    for (const vertical of [false, true]) {
        Object.assign(surfaces, { screenHeight: 768, vertical });
        assert.deepEqual(plain(surfaces.popoutContentSize(name)), { width: 368, height: 104 }, `${name} empty popup shrinks in either orientation`);
        rows = [{}];
        assert.deepEqual(plain(surfaces.popoutContentSize(name)), { width: widths[name], height: heights[name] }, `${name} arrival restores populated dimensions`);
        rows = [];
        assert.deepEqual(plain(surfaces.popoutContentSize(name)), { width: 368, height: 104 }, `${name} removal shrinks again`);
    }
    surfaces[`${name}Service`] = null;
}

// Consumers retain geometry and state computed by SurfaceManager.
Object.assign(surfaces, { screenWidth: 1366, screenHeight: 768, vertical: false, popoutName: "clock" });
assert.deepEqual(plain(surfaces.popupWindowAnchorRect()), { x: 0, y: 34, width: 1366, height: 1 });
assert.deepEqual(plain(surfaces.popupCardFrame(1)), {
    source: "simple-center-slide-fade", progress: 1,
    currentRect: { x: 311, y: 42, width: 744, height: 564 }, opacity: 1,
});
surfaces.vertical = true;
assert.deepEqual(plain(surfaces.popupWindowAnchorRect()), { x: 34, y: 0, width: 1, height: 768 });
assert.deepEqual(plain(surfaces.popupCardFrame(1)), {
    source: "left-bar-slide-fade", progress: 1,
    currentRect: { x: 42, y: 102, width: 744, height: 564 }, opacity: 1,
});
surfaces.vertical = false;
const opened = JSON.parse(surfaces.openPopout("clock", "100,0,40,34", "synthetic"));
assert.equal(opened.phase, "opening");
assert.equal(opened.activeLoaderName, "clock");
assert.deepEqual(opened.contentSize, { width: 760, height: 580 });
assert.equal(opened.transition.animation, "simple-center-slide-fade");
const switched = JSON.parse(surfaces.openPopout("power", "100,0,40,34", "synthetic"));
assert.equal(switched.phase, "open");
assert.equal(switched.progress, 1);
assert.deepEqual(switched.contentSize, { width: 368, height: 188 });
const closed = JSON.parse(surfaces.closePopout("escape-key"));
assert.equal(closed.phase, "closed");
assert.equal(closed.activeLoaderName, "");
assert.equal(closed.lastCloseReason, "escape-key");
assert.deepEqual(closed.contentSize, { width: 520, height: 300 });

console.log("popout-catalog.test.mjs: ALL PASS");