Skip to content

Commit 429c96f

Browse files
authored
Merge pull request #145 from deploymenttheory/dev
Refactor success handling and added tests
2 parents 3063149 + f99e492 commit 429c96f

File tree

3 files changed

+144
-7
lines changed

3 files changed

+144
-7
lines changed

Diff for: response/parse_test.go

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// response/parse_test.go
2+
package response
3+
4+
import (
5+
"reflect"
6+
"testing"
7+
)
8+
9+
func TestParseContentTypeHeader(t *testing.T) {
10+
tests := []struct {
11+
name string
12+
header string
13+
wantType string
14+
wantParams map[string]string
15+
}{
16+
{
17+
name: "Basic",
18+
header: "text/html; charset=UTF-8",
19+
wantType: "text/html",
20+
wantParams: map[string]string{"charset": "UTF-8"},
21+
},
22+
{
23+
name: "No Params",
24+
header: "application/json",
25+
wantType: "application/json",
26+
wantParams: map[string]string{},
27+
},
28+
{
29+
name: "Multiple Params",
30+
header: "multipart/form-data; boundary=something; charset=utf-8",
31+
wantType: "multipart/form-data",
32+
wantParams: map[string]string{"boundary": "something", "charset": "utf-8"},
33+
},
34+
}
35+
36+
for _, tt := range tests {
37+
t.Run(tt.name, func(t *testing.T) {
38+
gotType, gotParams := ParseContentTypeHeader(tt.header)
39+
if gotType != tt.wantType {
40+
t.Errorf("ParseContentTypeHeader() gotType = %v, want %v", gotType, tt.wantType)
41+
}
42+
if !reflect.DeepEqual(gotParams, tt.wantParams) {
43+
t.Errorf("ParseContentTypeHeader() gotParams = %v, want %v", gotParams, tt.wantParams)
44+
}
45+
})
46+
}
47+
}
48+
49+
func TestParseContentDisposition(t *testing.T) {
50+
tests := []struct {
51+
name string
52+
header string
53+
wantType string
54+
wantParams map[string]string
55+
}{
56+
{
57+
name: "Attachment with Filename",
58+
header: "attachment; filename=\"filename.jpg\"",
59+
wantType: "attachment",
60+
wantParams: map[string]string{"filename": "filename.jpg"},
61+
},
62+
{
63+
name: "Inline",
64+
header: "inline",
65+
wantType: "inline",
66+
wantParams: map[string]string{},
67+
},
68+
// Add more test cases as needed
69+
}
70+
71+
for _, tt := range tests {
72+
t.Run(tt.name, func(t *testing.T) {
73+
gotType, gotParams := ParseContentDisposition(tt.header)
74+
if gotType != tt.wantType {
75+
t.Errorf("ParseContentDisposition() gotType = %v, want %v", gotType, tt.wantType)
76+
}
77+
if !reflect.DeepEqual(gotParams, tt.wantParams) {
78+
t.Errorf("ParseContentDisposition() gotParams = %v, want %v", gotParams, tt.wantParams)
79+
}
80+
})
81+
}
82+
}

Diff for: response/success.go

+12-7
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,17 @@ import (
1616
"go.uber.org/zap"
1717
)
1818

19-
// Refactored contentHandler to accept io.Reader instead of []byte for streaming support.
19+
// contentHandler defines the signature for unmarshaling content from an io.Reader.
2020
type contentHandler func(io.Reader, interface{}, logger.Logger, string) error
2121

22-
// Updated handlers map to use the new contentHandler signature.
23-
var handlers = map[string]contentHandler{
22+
// responseUnmarshallers maps MIME types to the corresponding contentHandler functions.
23+
var responseUnmarshallers = map[string]contentHandler{
2424
"application/json": unmarshalJSON,
2525
"application/xml": unmarshalXML,
2626
"text/xml": unmarshalXML,
2727
}
2828

29-
// HandleAPISuccessResponse reads the response body and unmarshals it based on the content type.
29+
// HandleAPISuccessResponse reads the response body, logs the raw response details, and unmarshals the response based on the content type.
3030
func HandleAPISuccessResponse(resp *http.Response, out interface{}, log logger.Logger) error {
3131
if resp.Request.Method == "DELETE" {
3232
return handleDeleteRequest(resp, log)
@@ -38,7 +38,7 @@ func HandleAPISuccessResponse(resp *http.Response, out interface{}, log logger.L
3838
mimeType, _ := ParseContentTypeHeader(resp.Header.Get("Content-Type"))
3939
contentDisposition := resp.Header.Get("Content-Disposition")
4040

41-
if handler, ok := handlers[mimeType]; ok {
41+
if handler, ok := responseUnmarshallers[mimeType]; ok {
4242
// Pass resp.Body directly to the handler for streaming.
4343
return handler(resp.Body, out, log, mimeType)
4444
} else if isBinaryData(mimeType, contentDisposition) {
@@ -54,10 +54,15 @@ func HandleAPISuccessResponse(resp *http.Response, out interface{}, log logger.L
5454
// handleDeleteRequest handles the special case for DELETE requests, where a successful response might not contain a body.
5555
func handleDeleteRequest(resp *http.Response, log logger.Logger) error {
5656
if resp.StatusCode >= 200 && resp.StatusCode < 300 {
57-
log.Info("Successfully processed DELETE request", zap.String("URL", resp.Request.URL.String()), zap.Int("Status Code", resp.StatusCode))
57+
if log != nil {
58+
log.Info("Successfully processed DELETE request", zap.String("URL", resp.Request.URL.String()), zap.Int("Status Code", resp.StatusCode))
59+
}
5860
return nil
5961
}
60-
return log.Error("DELETE request failed", zap.String("URL", resp.Request.URL.String()), zap.Int("Status Code", resp.StatusCode))
62+
if log != nil {
63+
return log.Error("DELETE request failed", zap.String("URL", resp.Request.URL.String()), zap.Int("Status Code", resp.StatusCode))
64+
}
65+
return fmt.Errorf("DELETE request failed, status code: %d", resp.StatusCode)
6166
}
6267

6368
// Adjusted logResponseDetails to handle a potential nil bodyBytes.

Diff for: response/success_test.go

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// response/success_test.go
2+
package response
3+
4+
import (
5+
"net/http"
6+
"net/url"
7+
"testing"
8+
9+
"github.com/stretchr/testify/assert"
10+
)
11+
12+
func TestHandleDeleteRequest_Success(t *testing.T) {
13+
resp := &http.Response{
14+
StatusCode: http.StatusOK, // Simulate a successful DELETE request
15+
Request: &http.Request{
16+
Method: "DELETE",
17+
URL: &url.URL{
18+
Scheme: "http",
19+
Host: "example.com",
20+
Path: "/test",
21+
},
22+
},
23+
}
24+
25+
// Call handleDeleteRequest with a nil logger since logging is ignored in this test
26+
err := handleDeleteRequest(resp, nil)
27+
28+
// No error is expected for a successful DELETE request
29+
assert.NoError(t, err, "handleDeleteRequest should not return an error for successful DELETE requests")
30+
}
31+
32+
func TestHandleDeleteRequest_Failure(t *testing.T) {
33+
resp := &http.Response{
34+
StatusCode: http.StatusBadRequest, // Simulate a failed DELETE request
35+
Request: &http.Request{
36+
Method: "DELETE",
37+
URL: &url.URL{
38+
Scheme: "http",
39+
Host: "example.com",
40+
Path: "/test",
41+
},
42+
},
43+
}
44+
45+
// Call handleDeleteRequest with a nil logger since logging is ignored in this test
46+
err := handleDeleteRequest(resp, nil)
47+
48+
// An error is expected for a failed DELETE request
49+
assert.Error(t, err, "handleDeleteRequest should return an error for failed DELETE requests")
50+
}

0 commit comments

Comments
 (0)