Files
vmux/protocol_test.go
Pierre Martin e1b176cf55 feat(03-01): HookEvent struct, processHookEvent mapping, UpdateFromHook, WaitType
- HookEvent struct parses Claude Code hook JSON payload
- processHookEvent maps Notification/Stop/PostToolUse/PreToolUse to State+WaitType
- UpdateFromHook creates new entries and manages WaitingSince transitions
- SessionInfo.WaitType serialized in JSON with omitempty
- 12 tests cover all event mappings, edge cases, and JSON serialization

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 19:40:02 +01:00

150 lines
3.1 KiB
Go

package main
import (
"encoding/json"
"testing"
"time"
)
func TestRequestMarshal(t *testing.T) {
req := Request{Action: "list"}
data, err := json.Marshal(req)
if err != nil {
t.Fatalf("marshal: %v", err)
}
var got Request
if err := json.Unmarshal(data, &got); err != nil {
t.Fatalf("unmarshal: %v", err)
}
if got.Action != "list" {
t.Errorf("action = %q, want %q", got.Action, "list")
}
}
func TestRequestMarshalWithArgs(t *testing.T) {
args, _ := json.Marshal(LabelArgs{SessionID: "abc", Label: "review MR"})
req := Request{Action: "label", Args: args}
data, err := json.Marshal(req)
if err != nil {
t.Fatalf("marshal: %v", err)
}
var got Request
if err := json.Unmarshal(data, &got); err != nil {
t.Fatalf("unmarshal: %v", err)
}
if got.Action != "label" {
t.Errorf("action = %q, want %q", got.Action, "label")
}
var la LabelArgs
if err := json.Unmarshal(got.Args, &la); err != nil {
t.Fatalf("unmarshal args: %v", err)
}
if la.SessionID != "abc" || la.Label != "review MR" {
t.Errorf("args = %+v, want {abc, review MR}", la)
}
}
func TestResponseWithSessions(t *testing.T) {
now := time.Now()
resp := Response{
OK: true,
Sessions: []SessionInfo{
{
PID: 1234,
SessionID: "sess-1",
Cwd: "/home/user/project",
GitBranch: "main",
State: "Working",
Preview: "Building...",
Workspace: "3",
Label: "feature-x",
WaitingSince: &now,
},
},
}
data, err := json.Marshal(resp)
if err != nil {
t.Fatalf("marshal: %v", err)
}
var got Response
if err := json.Unmarshal(data, &got); err != nil {
t.Fatalf("unmarshal: %v", err)
}
if !got.OK {
t.Error("ok = false, want true")
}
if len(got.Sessions) != 1 {
t.Fatalf("sessions len = %d, want 1", len(got.Sessions))
}
s := got.Sessions[0]
if s.PID != 1234 {
t.Errorf("pid = %d, want 1234", s.PID)
}
if s.Workspace != "3" {
t.Errorf("workspace = %q, want %q", s.Workspace, "3")
}
if s.Label != "feature-x" {
t.Errorf("label = %q, want %q", s.Label, "feature-x")
}
if s.WaitingSince == nil {
t.Error("waiting_since = nil, want non-nil")
}
}
func TestSessionInfoWaitTypeJSON(t *testing.T) {
// WaitType="permission" should appear in JSON
info := SessionInfo{
SessionID: "sess-1",
State: "Needs Input",
WaitType: "permission",
}
data, err := json.Marshal(info)
if err != nil {
t.Fatalf("marshal: %v", err)
}
var m map[string]interface{}
if err := json.Unmarshal(data, &m); err != nil {
t.Fatalf("unmarshal map: %v", err)
}
if wt, ok := m["wait_type"]; !ok {
t.Error("wait_type field missing from JSON")
} else if wt != "permission" {
t.Errorf("wait_type = %v, want %q", wt, "permission")
}
// WaitType="" should be omitted (omitempty)
info2 := SessionInfo{
SessionID: "sess-2",
State: "Working",
WaitType: "",
}
data2, err := json.Marshal(info2)
if err != nil {
t.Fatalf("marshal: %v", err)
}
var m2 map[string]interface{}
if err := json.Unmarshal(data2, &m2); err != nil {
t.Fatalf("unmarshal map: %v", err)
}
if _, ok := m2["wait_type"]; ok {
t.Error("wait_type should be omitted when empty")
}
}