homeio
PublicForked from doctor-io/homeio
service.test.ts
import { afterEach, describe, expect, it, vi } from "vitest";
import type * as NetworkActivity from "@/lib/server/modules/system/network-activity";
const { countersMock } = vi.hoisted(() => ({ countersMock: vi.fn() }));
vi.mock("node:os", () => ({
default: {
loadavg: () => [0.6, 0.5, 0.4],
cpus: () => [0, 1, 2].map(() => ({ times: { user: 100, nice: 0, sys: 50, idle: 850, irq: 0 } })),
networkInterfaces: () => ({
wlan0: [
{ address: "192.168.1.22", family: "IPv4", internal: false },
{ address: "fe80::1234", family: "IPv6", internal: false },
],
}),
totalmem: () => 1024,
freemem: () => 256,
hostname: () => "pi",
platform: () => "linux",
release: () => "6.6",
uptime: () => 3600,
arch: () => "x64",
},
}));
vi.mock("@/lib/server/modules/system/network-activity", async (importOriginal) => ({
...(await importOriginal<typeof NetworkActivity>()),
readDefaultRouteInterface: vi.fn(async () => "wlan0"),
readInterfaceCounters: countersMock,
}));
vi.mock("systeminformation", () => ({
default: {
// Must stay unused by the snapshot: each call spawns cat/grep/nmcli/ip.
currentLoad: vi.fn(),
networkInterfaces: vi.fn(),
networkStats: vi.fn(),
cpuTemperature: vi.fn(async () => ({
main: 49.2,
cores: [48.5, 51.1],
max: 51.1,
})),
battery: vi.fn(async () => ({
hasBattery: true,
isCharging: false,
percent: 78,
timeRemaining: 98,
acConnected: false,
manufacturer: "SONY",
cycleCount: 248,
designedCapacity: 50,
maxCapacity: 45,
})),
wifiConnections: vi.fn(async () => [
{
iface: "wlan0",
ssid: "HomeNet",
bssid: "11:22:33",
quality: 66,
txRate: 130,
},
]),
wifiNetworks: vi.fn(async () => [
{
ssid: "HomeNet",
channel: 1,
quality: 66,
security: ["WPA2"],
rsnFlags: [],
},
]),
fsSize: vi.fn(async () => [
{
fs: "/dev/sda1",
type: "ext4",
size: 500 * 1024 * 1024 * 1024,
used: 120 * 1024 * 1024 * 1024,
use: 24,
mount: "/",
},
]),
diskLayout: vi.fn(async () => [
{
device: "/dev/sda",
type: "SSD",
smartStatus: "Ok",
},
]),
},
}));
import { getSystemMetricsSnapshot } from "@/lib/server/modules/system/service";
describe("system service", () => {
afterEach(() => {
vi.restoreAllMocks();
});
it("returns a snapshot with expected shape", async () => {
// Network throughput is a rate between two snapshots taken 2s apart.
const now = vi.spyOn(Date, "now").mockReturnValue(10_000);
countersMock.mockResolvedValueOnce({ rxBytes: 0, txBytes: 0 });
await getSystemMetricsSnapshot({ bypassCache: true });
now.mockReturnValue(12_000);
countersMock.mockResolvedValueOnce({ rxBytes: 6_200_000, txBytes: 2_200_000 });
const snapshot = await getSystemMetricsSnapshot({ bypassCache: true });
expect(snapshot.hostname).toBe("pi");
expect(snapshot.timestamp).toBeTypeOf("string");
expect(snapshot.uptimeSeconds).toBe(3600);
expect(snapshot.cpu.normalizedPercent).toBeGreaterThanOrEqual(0);
expect(snapshot.cpu.normalizedPercent).toBeLessThanOrEqual(100);
expect(snapshot.memory.totalBytes).toBe(1024);
expect(snapshot.temperature.mainCelsius).toBe(49.2);
expect(snapshot.battery.percent).toBe(78);
expect(snapshot.battery.manufacturer).toBe("SONY");
expect(snapshot.battery.cycleCount).toBe(248);
expect(snapshot.battery.designToMaxCapacityPercent).toBe(90);
expect(snapshot.wifi.connected).toBe(true);
expect(snapshot.wifi.ssid).toBe("HomeNet");
expect(snapshot.wifi.iface).toBe("wlan0");
expect(snapshot.wifi.ipv4).toBe("192.168.1.22");
expect(snapshot.wifi.ipv6).toBe("fe80::1234");
expect(snapshot.wifi.downloadMbps).toBe(24.8);
expect(snapshot.wifi.uploadMbps).toBe(8.8);
});
it("reads network and CPU load from the kernel, without spawning commands", async () => {
const si = (await import("systeminformation")).default;
countersMock.mockResolvedValue({ rxBytes: 0, txBytes: 0 });
await getSystemMetricsSnapshot({ bypassCache: true });
expect(si.currentLoad).not.toHaveBeenCalled();
expect(si.networkInterfaces).not.toHaveBeenCalled();
expect(si.networkStats).not.toHaveBeenCalled();
});
it("serves cached snapshot unless bypassCache is set", async () => {
const cachedOne = await getSystemMetricsSnapshot();
const cachedTwo = await getSystemMetricsSnapshot();
const fresh = await getSystemMetricsSnapshot({ bypassCache: true });
expect(cachedTwo).toBe(cachedOne);
expect(fresh).not.toBe(cachedOne);
});
});