feat: add session indicators and top exec commands to dashboard

Add visual indicators to session tables (replay badge when events exist,
exec badge for exec sessions) and a new "Top Exec Commands" table on the
dashboard. Includes EventCount field on Session, GetTopExecCommands on
Store interface, and truncateCommand template function.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-15 19:38:10 +01:00
parent 0b44d1c83f
commit 4f10a8a422
9 changed files with 243 additions and 25 deletions

View File

@@ -340,6 +340,61 @@ func TestMetricsBearerToken(t *testing.T) {
})
}
func TestTruncateCommand(t *testing.T) {
funcMap := templateFuncMap()
fn := funcMap["truncateCommand"].(func(string) string)
tests := []struct {
input string
want string
}{
{"short", "short"},
{"exactly fifty characters long! that is what it i.", "exactly fifty characters long! that is what it i."},
{"this string is definitely longer than fifty characters and should be truncated", "this string is definitely longer than fifty charac..."},
{"", ""},
}
for _, tt := range tests {
got := fn(tt.input)
if got != tt.want {
t.Errorf("truncateCommand(%q) = %q, want %q", tt.input, got, tt.want)
}
}
}
func TestDashboardExecCommands(t *testing.T) {
store := storage.NewMemoryStore()
ctx := context.Background()
id, err := store.CreateSession(ctx, "10.0.0.1", "root", "bash", "")
if err != nil {
t.Fatalf("creating session: %v", err)
}
if err := store.SetExecCommand(ctx, id, "uname -a"); err != nil {
t.Fatalf("setting exec command: %v", err)
}
srv, err := NewServer(store, slog.Default(), nil, "")
if err != nil {
t.Fatalf("NewServer: %v", err)
}
req := httptest.NewRequest(http.MethodGet, "/", nil)
w := httptest.NewRecorder()
srv.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Errorf("status = %d, want 200", w.Code)
}
body := w.Body.String()
if !strings.Contains(body, "Top Exec Commands") {
t.Error("response should contain 'Top Exec Commands'")
}
if !strings.Contains(body, "uname -a") {
t.Error("response should contain exec command 'uname -a'")
}
}
func TestStaticAssets(t *testing.T) {
srv := newTestServer(t)