1package modes
2
3import (
4 "errors"
5 "strings"
6 "testing"
7
8 "github.com/bnema/zut/packages/tui"
9)
10
11func TestRescueErrorPreservesFullDiagnostic(t *testing.T) {
12 msg := `opencode-go: http 403: {"type":"error","error":{"type":"DataPolicyError","message":"` + strings.Repeat("policy details ", 30) + `review consent at https://example.com/workspace/go"}}`
13 ok, reason := classifyRescueError(errors.New(msg))
14 if !ok || !strings.Contains(reason, msg) {
15 t.Fatalf("diagnostic was truncated: %q", reason)
16 }
17}
18
19func TestRescueDialogFullErrorView(t *testing.T) {
20 d := newRescueDialog()
21 reason := strings.Repeat("diagnostic 界 details ", 100) + "FINAL-DIAGNOSTIC"
22 d.Open("", nil, "opencode-go", "example", reason, "prompt")
23 d.HandleKey(tui.Key{Kind: tui.KeyTab})
24 const width, height = 40, 10
25 rows := d.Render(tui.Theme{}, width, height)
26 assertRowsFitWidth(t, rows, width)
27 if len(rows) > height+2 {
28 t.Fatalf("error view exceeds viewport: %d", len(rows))
29 }
30 if !strings.Contains(strings.Join(rows, "\n"), "diagnostic") {
31 t.Fatal("missing start of error")
32 }
33 for n := 0; n < 100; n++ {
34 d.HandleKey(tui.Key{Kind: tui.KeyPageDown})
35 rows = d.Render(tui.Theme{}, width, height)
36 }
37 if !strings.Contains(strings.Join(rows, "\n"), "FINAL-DIAGNOSTIC") {
38 t.Fatal("cannot scroll to end of error")
39 }
40 d.HandleKey(tui.Key{Kind: tui.KeyHome})
41 rows = d.Render(tui.Theme{}, width, height)
42 if !strings.Contains(strings.Join(rows, "\n"), "diagnostic") {
43 t.Fatal("cannot return to start")
44 }
45 if act := d.HandleKey(tui.Key{Kind: tui.KeyEnter}); act.Select || act.Close {
46 t.Fatal("error view must not retry a model")
47 }
48 d.HandleKey(tui.Key{Kind: tui.KeyEsc})
49 if !d.Active() || d.details {
50 t.Fatal("escape should return to picker")
51 }
52 d.HandleKey(tui.Key{Kind: tui.KeyEsc})
53 if d.Active() {
54 t.Fatal("escape should dismiss picker")
55 }
56}