// server/services/aptParse.test.ts import { describe, it, expect } from "vitest"; import { readFileSync } from "node:fs"; import { fileURLToPath } from "node:url"; import { parseAptSimulate, parseRebootRequired, parseAptRemovals, parseHeld, parseRebootDetail, buildAptSnapshotDetail, parseDpkgList, buildAptExecutionResult } from "./aptParse.js"; const raw = readFileSync(fileURLToPath(new URL("./__fixtures__/apt-simulate.txt", import.meta.url)), "utf8"); const ua = readFileSync(fileURLToPath(new URL("./__fixtures__/apt-update-analyze.txt", import.meta.url)), "utf8"); function section(rawInput: string, start: string, end: string): string { const s = rawInput.indexOf(start); if (s === -1) return ""; const from = s + start.length; const e = rawInput.indexOf(end, from); return rawInput.slice(from, e === -1 ? undefined : e).trim(); } describe("parseAptSimulate", () => { it("extrait les paquets upgradables avec versions et origine", () => { const pkgs = parseAptSimulate(raw); expect(pkgs).toEqual([ { name: "libc6", currentVersion: "2.31-13", targetVersion: "2.31-13+deb11u5", origin: "Debian:11.6/stable" }, { name: "pve-manager", currentVersion: "8.4-1", targetVersion: "8.4-3", origin: "Proxmox VE:8.x" }, { name: "newpkg", currentVersion: null, targetVersion: "1.0.0", origin: "Debian:11.6/stable" }, ]); }); it("retourne un tableau vide quand aucun Inst", () => { expect(parseAptSimulate("Reading package lists...\nDone")).toEqual([]); }); }); describe("parseRebootRequired", () => { it("détecte le marqueur REBOOT_REQUIRED=1", () => { expect(parseRebootRequired("REBOOT_REQUIRED=1")).toBe(true); expect(parseRebootRequired("REBOOT_REQUIRED=0")).toBe(false); expect(parseRebootRequired("rien")).toBe(false); }); }); describe("parseAptRemovals", () => { it("extrait les suppressions Remv", () => { expect(parseAptRemovals("Remv oldpkg [3.2-1]\nInst x [1] (2 Y [amd64])")) .toEqual([{ name: "oldpkg", currentVersion: "3.2-1" }]); }); }); describe("parseHeld", () => { it("liste les paquets retenus non vides", () => { expect(parseHeld("frozenpkg\n\n other ")).toEqual(["frozenpkg", "other"]); }); }); describe("parseRebootDetail", () => { it("lit le flag et les paquets reboot", () => { expect(parseRebootDetail("REBOOT_REQUIRED=1\nPKG=linux-image-amd64\nPKG=foo")) .toEqual({ rebootRequired: true, pkgs: ["linux-image-amd64", "foo"] }); expect(parseRebootDetail("REBOOT_REQUIRED=0")).toEqual({ rebootRequired: false, pkgs: [] }); }); }); const BEFORE = "libc6\t2.31-13\tamd64\noldpkg\t3.2-1\tamd64\nstable\t1.0\tamd64"; const AFTER = "libc6\t2.31-14\tamd64\nnewpkg\t1.0.0\tall\nstable\t1.0\tamd64"; describe("parseDpkgList", () => { it("indexe par package:arch", () => { const m = parseDpkgList("libc6\t2.31-13\tamd64"); expect(m["libc6:amd64"]).toEqual({ version: "2.31-13", arch: "amd64" }); }); }); describe("buildAptExecutionResult", () => { it("calcule le diff réel before/after", () => { const r = buildAptExecutionResult(BEFORE, AFTER, "REBOOT_REQUIRED=1"); expect(r.applied.find((c) => c.name === "libc6")).toMatchObject({ operation: "upgraded", fromVersion: "2.31-13", toVersion: "2.31-14" }); expect(r.installed.map((c) => c.name)).toEqual(["newpkg"]); expect(r.removed.map((c) => c.name)).toEqual(["oldpkg"]); expect(r.applied.some((c) => c.name === "stable")).toBe(false); // unchanged exclu expect(r.rebootRequiredAfterRun).toBe(true); }); }); describe("buildAptSnapshotDetail", () => { it("construit le détail enrichi depuis les sections", () => { const detail = buildAptSnapshotDetail({ upgradeSim: section(ua, "===SU:APT_SIM_UPGRADE===", "===SU:APT_SIM_DISTUPGRADE==="), distUpgradeSim: section(ua, "===SU:APT_SIM_DISTUPGRADE===", "===SU:APT_HELD==="), heldRaw: section(ua, "===SU:APT_HELD===", "===SU:REBOOT==="), rebootRaw: section(ua, "===SU:REBOOT===", "===SU:EXIT"), updateFailed: false, }); expect(detail.enabled).toBe(true); expect(detail.count).toBe(2); // 2 Inst en dist-upgrade expect(detail.upgradeCount).toBe(1); // 1 Inst en upgrade expect(detail.distUpgradeCount).toBe(2); expect(detail.rebootRequired).toBe(true); expect(detail.rebootPkgs).toEqual(["linux-image-amd64"]); expect(detail.held).toEqual(["frozenpkg"]); expect(detail.removed?.map((r) => r.name)).toEqual(["oldpkg"]); expect(detail.installed?.map((p) => p.name)).toEqual(["newdep"]); expect(detail.status).toBe("warning"); // car removed + held non vides }); it("status=updates_available sans removed/held, error si update échoue", () => { const ok = buildAptSnapshotDetail({ upgradeSim: "Inst a [1] (2 Y [amd64])", distUpgradeSim: "Inst a [1] (2 Y [amd64])", heldRaw: "", rebootRaw: "REBOOT_REQUIRED=0", updateFailed: false }); expect(ok.status).toBe("updates_available"); const err = buildAptSnapshotDetail({ upgradeSim: "", distUpgradeSim: "", heldRaw: "", rebootRaw: "REBOOT_REQUIRED=0", updateFailed: true }); expect(err.status).toBe("error"); }); });