use javascript chart instead of svg
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2026-02-06 16:42:48 +11:00
parent 9677d083a8
commit a993aedf79
13 changed files with 1152 additions and 1290 deletions

View File

@@ -0,0 +1,101 @@
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)
}
}