package handler import ( "encoding/json" "testing" "time" "vctp/components/views" ) func TestBuildVcenterChartEncodesClientConfig(t *testing.T) { entries := []views.VcenterTotalsEntry{ { RawTime: 2_000, VmCount: 30, VcpuTotal: 80, RamTotalGB: 120, }, { RawTime: 1_000, VmCount: 20, VcpuTotal: 60, RamTotalGB: 90, }, } chart := buildVcenterChart(entries) if chart.ConfigJSON == "" { t.Fatal("expected config json for non-empty vcenter chart") } var cfg lineChartConfig if err := json.Unmarshal([]byte(chart.ConfigJSON), &cfg); err != nil { t.Fatalf("failed to decode chart config json: %v", err) } if len(cfg.Labels) != 2 { t.Fatalf("expected 2 labels, got %d", len(cfg.Labels)) } expectedFirst := time.Unix(1_000, 0).Local().Format("2006-01-02 15:04:05") if cfg.Labels[0] != expectedFirst { t.Fatalf("expected oldest label first %q, got %q", expectedFirst, cfg.Labels[0]) } if len(cfg.Series) != 3 { t.Fatalf("expected 3 series, got %d", len(cfg.Series)) } if cfg.Series[0].Values[0] != 20 { t.Fatalf("expected first VM value 20, got %v", cfg.Series[0].Values[0]) } } func TestBuildVmTraceChartEncodesPoolState(t *testing.T) { entries := []views.VmTraceEntry{ { RawTime: 1_000, ResourcePool: "Tin", VcpuCount: 4, RamGB: 16, }, { RawTime: 2_000, ResourcePool: "Gold", VcpuCount: 8, RamGB: 24, }, } chart := buildVmTraceChart(entries) if chart.ConfigJSON == "" { t.Fatal("expected config json for non-empty vm trace chart") } var cfg lineChartConfig if err := json.Unmarshal([]byte(chart.ConfigJSON), &cfg); err != nil { t.Fatalf("failed to decode vm trace chart config: %v", err) } if len(cfg.Series) != 6 { t.Fatalf("expected 6 series, got %d", len(cfg.Series)) } if len(cfg.HoverRows) != 1 || cfg.HoverRows[0].Name != "Resource Pool" { t.Fatalf("expected resource pool hover row, got %#v", cfg.HoverRows) } if cfg.HoverRows[0].Values[0] != "Tin" || cfg.HoverRows[0].Values[1] != "Gold" { t.Fatalf("unexpected hover row values: %#v", cfg.HoverRows[0].Values) } if cfg.Series[2].Values[0] == 0 || cfg.Series[2].Values[1] != 0 { t.Fatalf("tin series should be active only for first point: %#v", cfg.Series[2].Values) } if cfg.Series[5].Values[0] != 0 || cfg.Series[5].Values[1] == 0 { t.Fatalf("gold series should be active only for second point: %#v", cfg.Series[5].Values) } } func TestBuildChartsEmptyInput(t *testing.T) { if chart := buildVcenterChart(nil); chart.ConfigJSON != "" { t.Fatalf("expected empty config for empty vcenter input, got %q", chart.ConfigJSON) } if chart := buildVmTraceChart(nil); chart.ConfigJSON != "" { t.Fatalf("expected empty config for empty vm trace input, got %q", chart.ConfigJSON) } }