5dc277f2b1
- style.css: navy token palette (--bg-0/1/2, --line, --text-1/2/3, --blue, --warn, --crit), single 2px radius, all box-shadows and the bg grid overlay removed, fonts via --font-ui/--font-data. - Components: .meter (3px hairline track, blue nominal fill, neutral 70/85 ticks, warn/crit flag), .tag (square 2px state chip + dot, pulse on progress, reduced-motion respected), .metarow (icon + text, no container), .panel/.list/.section-h primitives, boxless .stats with hairline dividers, buttons 2px (danger = crit outline). - funcmap: stateColor -> run/progress/warn/neutral/off (stopped is neutral, NOT red — operator-approved exception-color change), usageColor/tempColor -> nominal/warn/crit (thresholds unchanged); stateLabel Hungarian copy untouched (guarded by test). - layout.html: sprite nav icons (layout-grid/cloud/shield/cpu/wrench/ settings), alert banner emoji -> triangle-alert/info icons. - dashboard.html: meters with disk warn/crit flags (Fogyóban a hely / Kritikusan kevés hely), boxless stats (Leállítva 0 muted, >0 amber), single-panel stack list with 2px state edges, tags instead of badges, icon action buttons. - stacks.html: state tag + metarow rows; catalog keeps its grid. - setup minimalCSS retokened to v2 (drops GitHub-dark hexes). - Tests: §8 truth tables for stateColor/usageColor/tempColor + stateLabel byte-identity guard (red-proven vs pre-change funcmap: stopped->red and 0->green failed as required).
114 lines
3.0 KiB
Go
114 lines
3.0 KiB
Go
package web
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"gitea.dooplex.hu/admin/felhom-controller/internal/stacks"
|
|
)
|
|
|
|
// TASK-D0 §8 truth tables. These are the semantic contract of the v2 re-skin:
|
|
// every class suffix the templates key on comes from these three functions.
|
|
|
|
func TestStateColorTruthTable(t *testing.T) {
|
|
s := &Server{}
|
|
fm := s.templateFuncMap()
|
|
stateColor := fm["stateColor"].(func(stacks.ContainerState) string)
|
|
|
|
cases := []struct {
|
|
state stacks.ContainerState
|
|
want string
|
|
}{
|
|
{stacks.StateRunning, "run"},
|
|
{stacks.StateStarting, "progress"},
|
|
{stacks.StateDeploying, "progress"},
|
|
{stacks.StateUnhealthy, "warn"},
|
|
{stacks.StateRestarting, "warn"}, // a restart loop is a problem, not progress
|
|
{stacks.StateStopped, "neutral"}, // deliberately NOT red — customer-stopped is not an emergency
|
|
{stacks.StateExited, "neutral"},
|
|
{stacks.StatePaused, "neutral"},
|
|
{stacks.StateNotDeployed, "off"},
|
|
{stacks.ContainerState("bogus"), "off"},
|
|
}
|
|
for _, c := range cases {
|
|
if got := stateColor(c.state); got != c.want {
|
|
t.Errorf("stateColor(%q) = %q, want %q", c.state, got, c.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestUsageColorTruthTable(t *testing.T) {
|
|
s := &Server{}
|
|
fm := s.templateFuncMap()
|
|
usageColor := fm["usageColor"].(func(float64) string)
|
|
|
|
cases := []struct {
|
|
percent float64
|
|
want string
|
|
}{
|
|
{0, "nominal"},
|
|
{69.9, "nominal"},
|
|
{70, "warn"},
|
|
{84.9, "warn"},
|
|
{85, "crit"},
|
|
{100, "crit"},
|
|
}
|
|
for _, c := range cases {
|
|
if got := usageColor(c.percent); got != c.want {
|
|
t.Errorf("usageColor(%v) = %q, want %q", c.percent, got, c.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTempColorTruthTable(t *testing.T) {
|
|
s := &Server{}
|
|
fm := s.templateFuncMap()
|
|
tempColor := fm["tempColor"].(func(float64) string)
|
|
|
|
// thresholds unchanged from v1: >75 crit, >=60 warn, else nominal
|
|
cases := []struct {
|
|
celsius float64
|
|
want string
|
|
}{
|
|
{40, "nominal"},
|
|
{59.9, "nominal"},
|
|
{60, "warn"},
|
|
{75, "warn"},
|
|
{75.1, "crit"},
|
|
{90, "crit"},
|
|
}
|
|
for _, c := range cases {
|
|
if got := tempColor(c.celsius); got != c.want {
|
|
t.Errorf("tempColor(%v) = %q, want %q", c.celsius, got, c.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestStateLabelUnchanged guards the Hungarian copy against accidental edits
|
|
// during the re-skin — labels must stay byte-identical to pre-D0.
|
|
func TestStateLabelUnchanged(t *testing.T) {
|
|
s := &Server{}
|
|
fm := s.templateFuncMap()
|
|
stateLabel := fm["stateLabel"].(func(stacks.ContainerState) string)
|
|
|
|
cases := []struct {
|
|
state stacks.ContainerState
|
|
want string
|
|
}{
|
|
{stacks.StateRunning, "Fut"},
|
|
{stacks.StateStarting, "Indulás..."},
|
|
{stacks.StateDeploying, "Telepítés..."},
|
|
{stacks.StateUnhealthy, "Nem egészséges"},
|
|
{stacks.StateStopped, "Leállítva"},
|
|
{stacks.StateExited, "Leállítva"},
|
|
{stacks.StateRestarting, "Újraindítás..."},
|
|
{stacks.StateNotDeployed, "Nincs telepítve"},
|
|
{stacks.StatePaused, "Szüneteltetve"},
|
|
{stacks.ContainerState("bogus"), "Ismeretlen"},
|
|
}
|
|
for _, c := range cases {
|
|
if got := stateLabel(c.state); got != c.want {
|
|
t.Errorf("stateLabel(%q) = %q, want %q", c.state, got, c.want)
|
|
}
|
|
}
|
|
}
|