1package modes
2
3import (
4 "context"
5 "path/filepath"
6 "strings"
7 "testing"
8
9 "github.com/bnema/zut/packages/core"
10 "github.com/bnema/zut/packages/provider"
11 "github.com/bnema/zut/packages/tui"
12)
13
14func TestRunInfoShowsCurrentSessionDetails(t *testing.T) {
15 root := t.TempDir()
16 sessionPath := filepath.Join(root, "state", "session.jsonl")
17 cwd := filepath.Join(root, "workspace")
18 agent := &core.Agent{}
19 if err := agent.BindSessionID("session-123"); err != nil {
20 t.Fatal(err)
21 }
22 i := &Interactive{
23 agent: agent,
24 cfg: InteractiveConfig{
25 CWD: cwd,
26 Provider: "openai-codex",
27 Model: "gpt-5.6",
28 CurrentSessionPath: func() string { return sessionPath },
29 },
30 }
31
32 i.runSlash(context.Background(), "/INFO")
33
34 if len(i.sessionInfoBlocks) != 1 {
35 t.Fatalf("/info blocks = %d, want 1", len(i.sessionInfoBlocks))
36 }
37 got := strings.Join(i.sessionInfoBlocks[0].lines, "\n")
38 for _, want := range []string{
39 "session info",
40 "session-123",
41 sessionPath,
42 cwd,
43 "openai-codex",
44 "gpt-5.6",
45 } {
46 if !strings.Contains(got, want) {
47 t.Fatalf("/info output missing %q:\n%s", want, got)
48 }
49 }
50 if len(i.helpBlock) != 0 {
51 t.Fatalf("/info retained help block: %#v", i.helpBlock)
52 }
53 if got := len(agent.Messages()); got != 0 {
54 t.Fatalf("/info added %d messages to provider context", got)
55 }
56}
57
58func TestRunInfoAppendsEachInvocation(t *testing.T) {
59 i := &Interactive{}
60
61 i.runSlash(context.Background(), "/info")
62 i.runSlash(context.Background(), "/info")
63
64 if got := len(i.sessionInfoBlocks); got != 2 {
65 t.Fatalf("/info blocks = %d, want one per invocation", got)
66 }
67}
68
69func TestInfoScrollsWithTranscript(t *testing.T) {
70 agent := &core.Agent{}
71 agent.SetMessages([]provider.Message{{
72 Role: provider.RoleAssistant,
73 Content: []provider.Content{provider.TextBlock{Text: "before info"}},
74 }})
75 i := &Interactive{agent: agent, view: &tui.View{}}
76
77 i.runSlash(context.Background(), "/info")
78 agent.SetMessages(append(agent.Messages(), provider.Message{
79 Role: provider.RoleUser,
80 Content: []provider.Content{provider.TextBlock{Text: "after info"}},
81 }))
82
83 i.mu.Lock()
84 got := strings.Join(i.buildChatLocked(80), "\n")
85 i.mu.Unlock()
86 before := strings.Index(got, "before info")
87 info := strings.Index(got, "session info")
88 after := strings.Index(got, "after info")
89 if before < 0 || info < before || after < info {
90 t.Fatalf("/info did not stay at its transcript position:\n%s", got)
91 }
92}
93
94func TestRenderSessionInfoMarksUnavailableValues(t *testing.T) {
95 got := strings.Join(renderSessionInfoBlock(tui.Theme{}, 80, "", "", "", "", ""), "\n")
96 if count := strings.Count(got, "unavailable"); count != 5 {
97 t.Fatalf("unavailable value count = %d, want 5:\n%s", count, got)
98 }
99}