@@ -40,33 +40,46 @@ func renderTestHeader(header string, spinner spinner.Model, isFinished bool, isS
4040}
4141
4242func renderTestResponseVars (respVars []api.HTTPRequestResponseVariable ) string {
43- var str string
43+ var str strings.Builder
44+ var edges strings.Builder
45+
4446 for _ , respVar := range respVars {
4547 varStr := gray .Render (fmt .Sprintf (" * Saving `%s` from `%s`" , respVar .Name , respVar .Path ))
46- edges := " ├─"
47- for range lipgloss .Height (varStr ) - 1 {
48- edges += "\n │ "
48+ height := lipgloss .Height (varStr )
49+
50+ edges .Reset () // Reset and reuse edges builder
51+ edges .WriteString (" ├─" )
52+ for i := 1 ; i < height ; i ++ {
53+ edges .WriteString ("\n │ " )
4954 }
50- str += lipgloss .JoinHorizontal (lipgloss .Top , edges , varStr )
51- str += "\n "
55+
56+ str .WriteString (lipgloss .JoinHorizontal (lipgloss .Top , edges .String (), varStr ))
57+ str .WriteByte ('\n' )
5258 }
53- return str
59+
60+ return str .String ()
5461}
5562
5663func renderTests (tests []testModel , spinner string ) string {
57- var str string
64+ var str strings.Builder
65+ var edges strings.Builder
66+
5867 for _ , test := range tests {
5968 testStr := renderTest (test .text , spinner , test .finished , nil , test .passed )
6069 testStr = fmt .Sprintf (" %s" , testStr )
70+ height := lipgloss .Height (testStr )
6171
62- edges := " ├─"
63- for range lipgloss .Height (testStr ) - 1 {
64- edges += "\n │ "
72+ edges .Reset () // Reset and reuse edges builder
73+ edges .WriteString (" ├─" )
74+ for i := 1 ; i < height ; i ++ {
75+ edges .WriteString ("\n │ " )
6576 }
66- str += lipgloss .JoinHorizontal (lipgloss .Top , edges , testStr )
67- str += "\n "
77+
78+ str .WriteString (lipgloss .JoinHorizontal (lipgloss .Top , edges .String (), testStr ))
79+ str .WriteByte ('\n' )
6880 }
69- return str
81+
82+ return str .String ()
7083}
7184
7285func renderTest (text string , spinner string , isFinished bool , isSubmit * bool , passed * bool ) string {
@@ -190,15 +203,16 @@ func (m rootModel) View() string {
190203 return ""
191204 }
192205 s := m .spinner .View ()
193- var str string
206+ var str strings. Builder
194207 for _ , step := range m .steps {
195- str += renderTestHeader (step .step , m .spinner , step .finished , m .isSubmit , step .passed )
196- str += renderTests (step .tests , s )
197- str += renderTestResponseVars (step .responseVariables )
208+ str . WriteString ( renderTestHeader (step .step , m .spinner , step .finished , m .isSubmit , step .passed ) )
209+ str . WriteString ( renderTests (step .tests , s ) )
210+ str . WriteString ( renderTestResponseVars (step .responseVariables ) )
198211
199212 if step .sleepAfter != "" && step .finished {
200213 sleepBox := borderBox .Render (fmt .Sprintf (" %s " , step .sleepAfter ))
201- str += sleepBox + "\n "
214+ str .WriteString (sleepBox )
215+ str .WriteByte ('\n' )
202216 }
203217
204218 if step .result == nil || ! m .finalized {
@@ -210,40 +224,40 @@ func (m rootModel) View() string {
210224 for _ , test := range step .tests {
211225 // for clarity, only show exit code if it's tested
212226 if strings .Contains (test .text , "exit code" ) {
213- str += fmt .Sprintf ( "\n > Command exit code: %d\n " , step .result .CLICommandResult .ExitCode )
227+ fmt .Fprintf ( & str , "\n > Command exit code: %d\n " , step .result .CLICommandResult .ExitCode )
214228 break
215229 }
216230 }
217- str += " > Command stdout:\n \n "
231+ str . WriteString ( " > Command stdout:\n \n " )
218232 sliced := strings .Split (step .result .CLICommandResult .Stdout , "\n " )
219233 for _ , s := range sliced {
220- str += gray .Render (s ) + "\n "
234+ str .WriteString (gray .Render (s ))
235+ str .WriteByte ('\n' )
221236 }
222237 }
223238
224239 if step .result .HTTPRequestResult != nil {
225- str += printHTTPRequestResult (* step .result .HTTPRequestResult )
240+ str . WriteString ( printHTTPRequestResult (* step .result .HTTPRequestResult ) )
226241 }
227242 }
228243 if m .failure != nil {
229- str += "\n \n " + red .Render ("Tests failed! ❌" )
230- str += red .Render (fmt .Sprintf ("\n \n Failed Step: %v" , m .failure .FailedStepIndex + 1 ))
231- str += red .Render ("\n Error: " + m .failure .ErrorMessage ) + "\n \n "
244+ str . WriteString ( "\n \n " + red .Render ("Tests failed! ❌" ) )
245+ str . WriteString ( red .Render (fmt .Sprintf ("\n \n Failed Step: %v" , m .failure .FailedStepIndex + 1 ) ))
246+ str . WriteString ( red .Render ("\n Error: " + m .failure .ErrorMessage ) + "\n \n " )
232247 } else if m .success {
233- str += "\n \n " + green .Render ("All tests passed! 🎉" ) + "\n \n "
234- str += green .Render ("Return to your browser to continue with the next lesson." ) + "\n \n "
248+ str . WriteString ( "\n \n " + green .Render ("All tests passed! 🎉" ) + "\n \n " )
249+ str . WriteString ( green .Render ("Return to your browser to continue with the next lesson." ) + "\n \n " )
235250 }
236- return str
251+ return str . String ()
237252}
238253
239254func printHTTPRequestResult (result api.HTTPRequestResult ) string {
240255 if result .Err != "" {
241256 return fmt .Sprintf (" Err: %v\n \n " , result .Err )
242257 }
243258
244- str := ""
245-
246- str += fmt .Sprintf (" Response Status Code: %v\n " , result .StatusCode )
259+ var str strings.Builder
260+ fmt .Fprintf (& str , " Response Status Code: %v\n " , result .StatusCode )
247261
248262 filteredHeaders := make (map [string ]string )
249263 for respK , respV := range result .ResponseHeaders {
@@ -273,13 +287,13 @@ func printHTTPRequestResult(result api.HTTPRequestResult) string {
273287 }
274288
275289 if len (filteredHeaders ) > 0 {
276- str += " Response Headers: \n "
290+ str . WriteString ( " Response Headers: \n " )
277291 for k , v := range filteredHeaders {
278- str += fmt .Sprintf ( " - %v: %v\n " , k , v )
292+ fmt .Fprintf ( & str , " - %v: %v\n " , k , v )
279293 }
280294 }
281295
282- str += " Response Body: \n "
296+ str . WriteString ( " Response Body: \n " )
283297 bytes := []byte (result .BodyString )
284298 contentType := http .DetectContentType (bytes )
285299 if contentType == "application/json" || strings .HasPrefix (contentType , "text/" ) {
@@ -288,41 +302,42 @@ func printHTTPRequestResult(result api.HTTPRequestResult) string {
288302 if err == nil {
289303 pretty , err := json .MarshalIndent (unmarshalled , "" , " " )
290304 if err == nil {
291- str += string (pretty )
305+ str . Write (pretty )
292306 } else {
293- str += result .BodyString
307+ str . WriteString ( result .BodyString )
294308 }
295309 } else {
296- str += result .BodyString
310+ str . WriteString ( result .BodyString )
297311 }
298312 } else {
299- str += fmt .Sprintf (
313+ fmt .Fprintf (
314+ & str ,
300315 "Binary %s file. Raw data hidden. To manually debug, use curl -o myfile.bin and inspect the file" ,
301316 contentType ,
302317 )
303318 }
304- str += " \n "
319+ str . WriteByte ( '\n' )
305320
306321 if len (filteredTrailers ) > 0 {
307- str += " Response Trailers: \n "
322+ str . WriteString ( " Response Trailers: \n " )
308323 for k , v := range filteredTrailers {
309- str += fmt .Sprintf ( " - %v: %v\n " , k , v )
324+ fmt .Fprintf ( & str , " - %v: %v\n " , k , v )
310325 }
311326 }
312327
313328 if len (result .Variables ) > 0 {
314- str += " Variables available: \n "
329+ str . WriteString ( " Variables available: \n " )
315330 for k , v := range result .Variables {
316331 if v != "" {
317- str += fmt .Sprintf ( " - %v: %v\n " , k , v )
332+ fmt .Fprintf ( & str , " - %v: %v\n " , k , v )
318333 } else {
319- str += fmt .Sprintf ( " - %v: [not found]\n " , k )
334+ fmt .Fprintf ( & str , " - %v: [not found]\n " , k )
320335 }
321336 }
322337 }
323- str += " \n "
338+ str . WriteByte ( '\n' )
324339
325- return str
340+ return str . String ()
326341}
327342
328343func StartRenderer (data api.CLIData , isSubmit bool , ch chan tea.Msg ) func (* api.VerificationResultStructuredErrCLI ) {
0 commit comments