1package tui
2
3import "testing"
4
5func TestExtractLastNewText(t *testing.T) {
6 cases := []struct {
7 name string
8 raw string
9 wantValue string
10 wantOK bool
11 wantDone bool
12 wantIdx int
13 }{
14 {
15 name: "no newText yet",
16 raw: `{"path":"/x","edits":[{"oldText":"a"}`,
17 wantValue: "",
18 wantOK: false,
19 wantDone: false,
20 wantIdx: 0,
21 },
22 {
23 name: "single newText partial",
24 raw: `{"edits":[{"oldText":"a","newText":"b`,
25 wantValue: "b",
26 wantOK: true,
27 wantDone: false,
28 wantIdx: 1,
29 },
30 {
31 name: "single newText complete",
32 raw: `{"edits":[{"oldText":"a","newText":"b"}]`,
33 wantValue: "b",
34 wantOK: true,
35 wantDone: true,
36 wantIdx: 1,
37 },
38 {
39 name: "two edits, second still streaming",
40 raw: `{"edits":[{"oldText":"x","newText":"y"},{"oldText":"a","newText":"hello wor`,
41 wantValue: "hello wor",
42 wantOK: true,
43 wantDone: false,
44 wantIdx: 2,
45 },
46 }
47 for _, c := range cases {
48 t.Run(c.name, func(t *testing.T) {
49 v, ok, done, idx := ExtractLastNewText(c.raw)
50 if v != c.wantValue || ok != c.wantOK || done != c.wantDone || idx != c.wantIdx {
51 t.Errorf("want (v=%q ok=%v done=%v idx=%d), got (v=%q ok=%v done=%v idx=%d)",
52 c.wantValue, c.wantOK, c.wantDone, c.wantIdx, v, ok, done, idx)
53 }
54 })
55 }
56}
57
58func TestExtractPartialStringField(t *testing.T) {
59 cases := []struct {
60 name string
61 raw string
62 field string
63 wantValue string
64 wantOK bool
65 wantDone bool
66 }{
67 {
68 name: "empty buffer",
69 raw: "",
70 field: "content",
71 wantValue: "",
72 wantOK: false,
73 wantDone: false,
74 },
75 {
76 name: "no such field",
77 raw: `{"path":"/x","foo":"bar"}`,
78 field: "content",
79 wantValue: "",
80 wantOK: false,
81 wantDone: false,
82 },
83 {
84 name: "complete",
85 raw: `{"path":"/x","content":"hello"}`,
86 field: "content",
87 wantValue: "hello",
88 wantOK: true,
89 wantDone: true,
90 },
91 {
92 name: "partial mid-word",
93 raw: `{"path":"/x","content":"hel`,
94 field: "content",
95 wantValue: "hel",
96 wantOK: true,
97 wantDone: false,
98 },
99 {
100 name: "escaped quote",
101 raw: `{"content":"say \"hi\""}`,
102 field: "content",
103 wantValue: `say "hi"`,
104 wantOK: true,
105 wantDone: true,
106 },
107 {
108 name: "escaped newline inside string",
109 raw: `{"content":"line1\nline2"}`,
110 field: "content",
111 wantValue: "line1\nline2",
112 wantOK: true,
113 wantDone: true,
114 },
115 {
116 name: "trailing backslash (unfinished escape)",
117 raw: `{"content":"line1\`,
118 field: "content",
119 wantValue: "line1",
120 wantOK: true,
121 wantDone: false,
122 },
123 {
124 name: "incomplete unicode escape",
125 raw: `{"content":"before\u00`,
126 field: "content",
127 wantValue: "before",
128 wantOK: true,
129 wantDone: false,
130 },
131 {
132 name: "key before value",
133 raw: `{"content":`,
134 field: "content",
135 wantValue: "",
136 wantOK: false,
137 wantDone: false,
138 },
139 }
140
141 for _, c := range cases {
142 t.Run(c.name, func(t *testing.T) {
143 v, ok, done := ExtractPartialStringField(c.raw, c.field)
144 if v != c.wantValue {
145 t.Errorf("value: want %q, got %q", c.wantValue, v)
146 }
147 if ok != c.wantOK {
148 t.Errorf("ok: want %v, got %v", c.wantOK, ok)
149 }
150 if done != c.wantDone {
151 t.Errorf("done: want %v, got %v", c.wantDone, done)
152 }
153 })
154 }
155}