635f2fd9fc
- #3 nudge-on-own-turn: distinct result code nudge_own_turn + i18n (was reused 'not_your_turn') - #2 sanitize connector registration name to the editable format; Player/Игрок-XXXXX fallback - #5 variant-aware robot name pools (composed full/colloquial first + surname forms; ru gets <=20% latin) - #4 move-number-aware robot move timing (early 1-5min -> late 10-90min, skew k=4) - #7 emit move event to the actor too (multi-device sync); opponent_moved stays in-app only - #1 live game_move_duration{variant,phase} histogram + admin console per-user min/avg/max columns and an inline-SVG move-time-by-move-number chart (offline from the journal) - ProvisionRobot bypasses editor name validation (system names like 'Peter J.')
52 lines
1.4 KiB
Go
52 lines
1.4 KiB
Go
package adminconsole
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestFormatDuration(t *testing.T) {
|
|
cases := map[float64]string{
|
|
0: "0s", 30: "30s", 59: "59s", 60: "1m", 150: "3m", 3600: "1h", 3660: "1h1m", 7800: "2h10m",
|
|
}
|
|
for secs, want := range cases {
|
|
if got := FormatDuration(secs); got != want {
|
|
t.Errorf("FormatDuration(%v) = %q, want %q", secs, got, want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestMoveDurationChartEmpty(t *testing.T) {
|
|
if got := MoveDurationChart(nil); got != "" {
|
|
t.Errorf("empty chart = %q, want empty", got)
|
|
}
|
|
}
|
|
|
|
func TestMoveDurationChart(t *testing.T) {
|
|
pts := []ChartPoint{{Ordinal: 1, Min: 5, Max: 20, Avg: 10}, {Ordinal: 2, Min: 8, Max: 40, Avg: 18}, {Ordinal: 3, Min: 12, Max: 90, Avg: 30}}
|
|
svg := string(MoveDurationChart(pts))
|
|
for _, want := range []string{"<svg", "ln-min", "ln-avg", "ln-max", "</svg>"} {
|
|
if !strings.Contains(svg, want) {
|
|
t.Errorf("chart missing %q\n%s", want, svg)
|
|
}
|
|
}
|
|
if n := strings.Count(svg, "<polyline"); n != 3 {
|
|
t.Errorf("polylines = %d, want 3", n)
|
|
}
|
|
}
|
|
|
|
func TestXTicks(t *testing.T) {
|
|
cases := map[int][]int{1: {1}, 2: {1, 2}, 3: {1, 2, 3}, 10: {1, 5, 10}}
|
|
for maxOrd, want := range cases {
|
|
got := xTicks(maxOrd)
|
|
if len(got) != len(want) {
|
|
t.Fatalf("xTicks(%d) = %v, want %v", maxOrd, got, want)
|
|
}
|
|
for i := range want {
|
|
if got[i] != want[i] {
|
|
t.Errorf("xTicks(%d) = %v, want %v", maxOrd, got, want)
|
|
}
|
|
}
|
|
}
|
|
}
|