Skip to content

Commit 1c451f5

Browse files
authored
render the variables that are being used in http tests (#69)
1 parent e0be9d7 commit 1c451f5

File tree

4 files changed

+112
-61
lines changed

4 files changed

+112
-61
lines changed

checks/http.go

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@ import (
1717
)
1818

1919
type HttpTestResult struct {
20-
Err string `json:"-"`
21-
RequestHeaders http.Header `json:"-"`
22-
StatusCode int
23-
Headers map[string]string
24-
BodyString string
25-
Variables map[string]string
20+
Err string `json:"-"`
21+
StatusCode int
22+
ResponseHeaders map[string]string
23+
BodyString string
24+
Variables map[string]string
25+
Request api.LessonDataHTTPTestsRequest
2626
}
2727

2828
func HttpTest(
@@ -101,11 +101,11 @@ func HttpTest(
101101
}
102102
parseVariables(body, request.ResponseVariables, variables)
103103
responses[i] = HttpTestResult{
104-
RequestHeaders: r.Header,
105-
StatusCode: resp.StatusCode,
106-
Headers: headers,
107-
BodyString: truncateAndStringifyBody(body),
108-
Variables: variables,
104+
StatusCode: resp.StatusCode,
105+
ResponseHeaders: headers,
106+
BodyString: truncateAndStringifyBody(body),
107+
Variables: variables,
108+
Request: request,
109109
}
110110
}
111111
return responses, finalBaseURL
@@ -118,7 +118,6 @@ func truncateAndStringifyBody(body []byte) string {
118118
bodyString := string(body)
119119
const maxBodyLength = 100000
120120
if len(bodyString) > maxBodyLength {
121-
fmt.Printf("truncating from %v to %v", len(bodyString), maxBodyLength)
122121
bodyString = bodyString[:maxBodyLength]
123122
}
124123
return bodyString

client/lessons.go

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -45,23 +45,25 @@ type LessonDataHTTPTests struct {
4545
HttpTests struct {
4646
BaseURL *string
4747
ContainsCompleteDir bool
48-
Requests []struct {
49-
ResponseVariables []ResponseVariable
50-
Tests []HTTPTest
51-
Request struct {
52-
FullURL string // overrides BaseURL and Path if set
53-
Path string
54-
BasicAuth *struct {
55-
Username string
56-
Password string
57-
}
58-
Headers map[string]string
59-
BodyJSON map[string]interface{}
60-
Method string
61-
Actions struct {
62-
DelayRequestByMs *int32
63-
}
64-
}
48+
Requests []LessonDataHTTPTestsRequest
49+
}
50+
}
51+
52+
type LessonDataHTTPTestsRequest struct {
53+
ResponseVariables []ResponseVariable
54+
Tests []HTTPTest
55+
Request struct {
56+
FullURL string // overrides BaseURL and Path if set
57+
Path string
58+
BasicAuth *struct {
59+
Username string
60+
Password string
61+
}
62+
Headers map[string]string
63+
BodyJSON map[string]interface{}
64+
Method string
65+
Actions struct {
66+
DelayRequestByMs *int32
6567
}
6668
}
6769
}

render/common.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"strings"
66

7+
api "github.com/bootdotdev/bootdev/client"
78
"github.com/charmbracelet/bubbles/spinner"
89
"github.com/charmbracelet/lipgloss"
910
)
@@ -36,6 +37,20 @@ func renderTestHeader(header string, spinner spinner.Model, isFinished bool, isS
3637
return strings.Join(sliced, "\n") + "\n"
3738
}
3839

40+
func renderTestResponseVars(respVars []api.ResponseVariable) string {
41+
var str string
42+
for _, respVar := range respVars {
43+
varStr := gray.Render(fmt.Sprintf(" * Saving `%s` from `%s`", respVar.Name, respVar.Path))
44+
edges := " ├─"
45+
for i := 0; i < lipgloss.Height(varStr)-1; i++ {
46+
edges += "\n │ "
47+
}
48+
str += lipgloss.JoinHorizontal(lipgloss.Top, edges, varStr)
49+
str += "\n"
50+
}
51+
return str
52+
}
53+
3954
func renderTests(tests []testModel, spinner string) string {
4055
var str string
4156
for _, test := range tests {
@@ -49,7 +64,6 @@ func renderTests(tests []testModel, spinner string) string {
4964
str += lipgloss.JoinHorizontal(lipgloss.Top, edges, testStr)
5065
str += "\n"
5166
}
52-
str += "\n"
5367
return str
5468
}
5569

render/http.go

Lines changed: 67 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ type doneHttpMsg struct {
2323
}
2424

2525
type startHttpMsg struct {
26-
url string
27-
method string
26+
url string
27+
method string
28+
responseVariables []api.ResponseVariable
2829
}
2930

3031
type resolveHttpMsg struct {
@@ -33,11 +34,12 @@ type resolveHttpMsg struct {
3334
results *checks.HttpTestResult
3435
}
3536
type httpReqModel struct {
36-
request string
37-
passed *bool
38-
results *checks.HttpTestResult
39-
finished bool
40-
tests []testModel
37+
responseVariables []api.ResponseVariable
38+
request string
39+
passed *bool
40+
results *checks.HttpTestResult
41+
finished bool
42+
tests []testModel
4143
}
4244

4345
type httpRootModel struct {
@@ -78,7 +80,11 @@ func (m httpRootModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
7880
return m, tea.Quit
7981

8082
case startHttpMsg:
81-
m.reqs = append(m.reqs, httpReqModel{request: fmt.Sprintf("%s %s", msg.method, msg.url), tests: []testModel{}})
83+
m.reqs = append(m.reqs, httpReqModel{
84+
request: fmt.Sprintf("%s %s", msg.method, msg.url),
85+
tests: []testModel{},
86+
responseVariables: msg.responseVariables,
87+
})
8288
return m, nil
8389

8490
case resolveHttpMsg:
@@ -115,6 +121,7 @@ func (m httpRootModel) View() string {
115121
for _, req := range m.reqs {
116122
str += renderTestHeader(req.request, m.spinner, req.finished, m.isSubmit, req.passed)
117123
str += renderTests(req.tests, s)
124+
str += renderTestResponseVars(req.responseVariables)
118125
if req.results != nil && m.finalized {
119126
str += printHTTPResult(*req.results)
120127
}
@@ -129,37 +136,63 @@ func (m httpRootModel) View() string {
129136
}
130137

131138
func printHTTPResult(result checks.HttpTestResult) string {
132-
str := ""
133139
if result.Err != "" {
134-
str += fmt.Sprintf(" Err: %v\n", result.Err)
135-
} else {
136-
if len(result.RequestHeaders) > 0 {
137-
str += " Request Headers: \n"
138-
for k, v := range result.RequestHeaders {
139-
str += fmt.Sprintf(" - %v: %v\n", k, v[0])
140+
return fmt.Sprintf(" Err: %v\n\n", result.Err)
141+
}
142+
143+
str := ""
144+
145+
str += fmt.Sprintf(" Response Status Code: %v\n", result.StatusCode)
146+
147+
filteredHeaders := make(map[string]string)
148+
for respK, respV := range result.ResponseHeaders {
149+
for reqK := range result.Request.Request.Headers {
150+
if strings.ToLower(respK) == strings.ToLower(reqK) {
151+
filteredHeaders[respK] = respV
140152
}
141153
}
142-
str += fmt.Sprintf(" Response Status Code: %v\n", result.StatusCode)
143-
str += " Response Body: \n"
144-
unmarshalled := map[string]interface{}{}
145-
bytes := []byte(result.BodyString)
154+
}
155+
156+
if len(filteredHeaders) > 0 {
157+
str += " Response Headers: \n"
158+
for k, v := range filteredHeaders {
159+
str += fmt.Sprintf(" - %v: %v\n", k, v)
160+
}
161+
}
146162

147-
contentType := http.DetectContentType(bytes)
148-
if contentType == "application/json" || strings.HasPrefix(contentType, "text/") {
149-
err := json.Unmarshal([]byte(result.BodyString), &unmarshalled)
163+
str += " Response Body: \n"
164+
bytes := []byte(result.BodyString)
165+
contentType := http.DetectContentType(bytes)
166+
if contentType == "application/json" || strings.HasPrefix(contentType, "text/") {
167+
var unmarshalled interface{}
168+
err := json.Unmarshal([]byte(result.BodyString), &unmarshalled)
169+
if err == nil {
170+
pretty, err := json.MarshalIndent(unmarshalled, "", " ")
150171
if err == nil {
151-
pretty, err := json.MarshalIndent(unmarshalled, "", " ")
152-
if err == nil {
153-
str += string(pretty)
154-
}
172+
str += string(pretty)
155173
} else {
156174
str += result.BodyString
157175
}
158176
} else {
159-
str += fmt.Sprintf("Binary %s file", contentType)
177+
str += result.BodyString
178+
}
179+
} else {
180+
str += fmt.Sprintf("Binary %s file", contentType)
181+
}
182+
str += "\n"
183+
184+
if len(result.Variables) > 0 {
185+
str += " Variables available: \n"
186+
for k, v := range result.Variables {
187+
if v != "" {
188+
str += fmt.Sprintf(" - %v: %v\n", k, v)
189+
} else {
190+
str += fmt.Sprintf(" - %v: [not found]\n", k)
191+
}
160192
}
161193
}
162194
str += "\n"
195+
163196
return str
164197
}
165198

@@ -215,11 +248,14 @@ func httpRenderer(
215248
url = req.Request.FullURL
216249
}
217250
ch <- startHttpMsg{
218-
url: checks.InterpolateVariables(url, results[i].Variables),
219-
method: req.Request.Method,
251+
url: checks.InterpolateVariables(url, results[i].Variables),
252+
method: req.Request.Method,
253+
responseVariables: req.ResponseVariables,
220254
}
221255
for _, test := range req.Tests {
222-
ch <- startTestMsg{text: prettyPrintHTTPTest(test, results[i].Variables)}
256+
ch <- startTestMsg{
257+
text: prettyPrintHTTPTest(test, results[i].Variables),
258+
}
223259
}
224260
time.Sleep(500 * time.Millisecond)
225261
for j := range req.Tests {
@@ -267,7 +303,7 @@ func prettyPrintHTTPTest(test api.HTTPTest, variables map[string]string) string
267303
if test.HeadersContain != nil {
268304
interpolatedKey := checks.InterpolateVariables(test.HeadersContain.Key, variables)
269305
interpolatedValue := checks.InterpolateVariables(test.HeadersContain.Value, variables)
270-
return fmt.Sprintf("Expecting header to contain: '%s: %v'", interpolatedKey, interpolatedValue)
306+
return fmt.Sprintf("Expecting headers to contain: '%s: %v'", interpolatedKey, interpolatedValue)
271307
}
272308
if test.JSONValue != nil {
273309
var val any

0 commit comments

Comments
 (0)