1import { describe, expect, it } from "vite-plus/test";
2
3import type { ResourceTelemetryProcess } from "@t3tools/contracts";
4import * as DateTime from "effect/DateTime";
5
6import {
7 resourceHistoryBarHeight,
8 resourceHistoryCpuScaleMax,
9 shouldShowResourceMonitorRetry,
10 visibleResourceTelemetryProcesses,
11} from "./ResourceTelemetryDiagnostics.logic";
12
13const process = (pid: number, ppid: number, depth: number): ResourceTelemetryProcess => ({
14 identity: { pid, startTimeMs: pid * 1_000 },
15 ppid,
16 childPids: [],
17 depth,
18 name: `process-${pid}`,
19 command: `process-${pid}`,
20 status: "Running",
21 category: pid === 1 ? "server" : "server-child",
22 cpuPercent: 0,
23 cpuTimeMs: 0,
24 residentBytes: 0,
25 peakResidentBytes: 0,
26 virtualBytes: 0,
27 ioReadBytes: 0,
28 ioWriteBytes: 0,
29 ioReadBytesPerSecond: 0,
30 ioWriteBytesPerSecond: 0,
31 ioSemantics: "storage",
32 runTimeMs: 0,
33 firstSeenAt: DateTime.makeUnsafe(0),
34 lastSeenAt: DateTime.makeUnsafe(0),
35});
36
37describe("shouldShowResourceMonitorRetry", () => {
38 it("allows retry when the initial telemetry request fails before a snapshot", () => {
39 expect(
40 shouldShowResourceMonitorRetry({
41 nativeStatus: null,
42 error: "Resource monitor is unavailable.",
43 }),
44 ).toBe(true);
45 });
46
47 it("does not show retry for an initial load without an error or a healthy snapshot", () => {
48 expect(shouldShowResourceMonitorRetry({ nativeStatus: null, error: null })).toBe(false);
49 expect(shouldShowResourceMonitorRetry({ nativeStatus: "healthy", error: null })).toBe(false);
50 });
51});
52
53describe("resourceHistoryBarHeight", () => {
54 it("renders an exactly zero sample with no visible bar", () => {
55 expect(resourceHistoryBarHeight({ value: 0, max: 100, minimumVisiblePercent: 2 })).toBe(0);
56 });
57
58 it("keeps nonzero samples visible without changing proportional heights", () => {
59 expect(resourceHistoryBarHeight({ value: 0.5, max: 100, minimumVisiblePercent: 2 })).toBe(2);
60 expect(resourceHistoryBarHeight({ value: 50, max: 100, minimumVisiblePercent: 2 })).toBe(50);
61 });
62});
63
64describe("resourceHistoryCpuScaleMax", () => {
65 it("scales average bars independently of brief peak spikes", () => {
66 const buckets = [
67 { avgCpuPercent: 1, maxCpuPercent: 100 },
68 { avgCpuPercent: 8, maxCpuPercent: 8 },
69 ];
70 expect(resourceHistoryCpuScaleMax(buckets)).toBe(8);
71 });
72});
73
74describe("visibleResourceTelemetryProcesses", () => {
75 it("hides descendants by parentage even when rows are not depth-first", () => {
76 const processes = [
77 process(1, 0, 0),
78 process(10, 0, 0),
79 process(2, 1, 1),
80 process(11, 10, 1),
81 process(3, 2, 2),
82 ];
83
84 expect(visibleResourceTelemetryProcesses(processes, new Set(["1:1000"]))).toEqual([
85 processes[0],
86 processes[1],
87 processes[3],
88 ]);
89 });
90});