Skip to content

Commit 3e48e0d

Browse files
author
marcinromaszewicz
committed
Initial release of oapi-codegen
0 parents  commit 3e48e0d

File tree

1 file changed

+172
-0
lines changed

1 file changed

+172
-0
lines changed

request_helpers.go

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
// Copyright 2019 DeepMap, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
package testutil
15+
16+
// This is a set of fluent request builders for tests, which help us to
17+
// simplify constructing and unmarshaling test objects. For example, to post
18+
// a body and return a response, you would do something like:
19+
//
20+
// var body RequestBody
21+
// var response ResponseBody
22+
// t is *testing.T, from a unit test
23+
// e is *echo.Echo
24+
// response := NewRequest().Post("/path").WithJsonBody(body).Go(t, e)
25+
// err := response.UnmarshalBodyToObject(&response)
26+
import (
27+
"bytes"
28+
"encoding/json"
29+
"fmt"
30+
"io"
31+
"net/http/httptest"
32+
"strings"
33+
"testing"
34+
35+
"github.com/labstack/echo/v4"
36+
)
37+
38+
func NewRequest() *RequestBuilder {
39+
return &RequestBuilder{
40+
Headers: make(map[string]string),
41+
}
42+
}
43+
44+
// This structure caches request settings as we build up the request.
45+
type RequestBuilder struct {
46+
Method string
47+
Path string
48+
Headers map[string]string
49+
Body []byte
50+
Error error
51+
}
52+
53+
// Path operations
54+
func (r *RequestBuilder) WithMethod(method string, path string) *RequestBuilder {
55+
r.Method = method
56+
r.Path = path
57+
return r
58+
}
59+
60+
func (r *RequestBuilder) Get(path string) *RequestBuilder {
61+
return r.WithMethod("GET", path)
62+
}
63+
64+
func (r *RequestBuilder) Post(path string) *RequestBuilder {
65+
return r.WithMethod("POST", path)
66+
}
67+
68+
func (r *RequestBuilder) Put(path string) *RequestBuilder {
69+
return r.WithMethod("PUT", path)
70+
}
71+
72+
func (r *RequestBuilder) Delete(path string) *RequestBuilder {
73+
return r.WithMethod("DELETE", path)
74+
}
75+
76+
// Header operations
77+
func (r *RequestBuilder) WithHeader(header, value string) *RequestBuilder {
78+
r.Headers[header] = value
79+
return r
80+
}
81+
82+
func (r *RequestBuilder) WithContentType(value string) *RequestBuilder {
83+
return r.WithHeader("Content-Type", value)
84+
}
85+
86+
func (r *RequestBuilder) WithJsonContentType() *RequestBuilder {
87+
return r.WithContentType("application/json")
88+
}
89+
90+
func (r *RequestBuilder) WithAccept(value string) *RequestBuilder {
91+
return r.WithHeader("Accept", value)
92+
}
93+
94+
func (r *RequestBuilder) WithAcceptJson() *RequestBuilder {
95+
return r.WithAccept("application/json")
96+
}
97+
98+
// Request body operations
99+
100+
func (r *RequestBuilder) WithBody(body []byte) *RequestBuilder {
101+
r.Body = body
102+
return r
103+
}
104+
105+
// This function takes an object as input, marshals it to JSON, and sends it
106+
// as the body with Content-Type: application/json
107+
func (r *RequestBuilder) WithJsonBody(obj interface{}) *RequestBuilder {
108+
var err error
109+
r.Body, err = json.Marshal(obj)
110+
if err != nil {
111+
r.Error = fmt.Errorf("failed to marshal json object: %s", err)
112+
}
113+
return r.WithJsonContentType()
114+
}
115+
116+
// This function performs the request, it takes a pointer to a testing context
117+
// to print messages, and a pointer to an echo context for request handling.
118+
func (r *RequestBuilder) Go(t *testing.T, e *echo.Echo) *CompletedRequest {
119+
if r.Error != nil {
120+
// Fail the test if we had an error
121+
t.Errorf("error constructing request: %s", r.Error)
122+
return nil
123+
}
124+
var bodyReader io.Reader
125+
if r.Body != nil {
126+
bodyReader = bytes.NewReader(r.Body)
127+
}
128+
129+
req := httptest.NewRequest(r.Method, r.Path, bodyReader)
130+
for h, v := range r.Headers {
131+
req.Header.Add(h, v)
132+
}
133+
rec := httptest.NewRecorder()
134+
e.ServeHTTP(rec, req)
135+
136+
return &CompletedRequest{
137+
Recorder: rec,
138+
}
139+
}
140+
141+
// This is the result of calling Go() on the request builder. We're wrapping the
142+
// ResponseRecorder with some nice helper functions.
143+
type CompletedRequest struct {
144+
Recorder *httptest.ResponseRecorder
145+
}
146+
147+
// This function takes a destination object as input, and unmarshals the object
148+
// in the response based on the Content-Type header.
149+
func (c *CompletedRequest) UnmarshalBodyToObject(obj interface{}) error {
150+
ctype := c.Recorder.Header().Get("Content-Type")
151+
152+
// Content type can have an annotation after ;
153+
contentParts := strings.Split(ctype, ";")
154+
155+
switch strings.TrimSpace(contentParts[0]) {
156+
case "application/json":
157+
return json.Unmarshal(c.Recorder.Body.Bytes(), obj)
158+
default:
159+
return fmt.Errorf("no Content-Type on response")
160+
}
161+
}
162+
163+
// This function assumes that the response contains JSON and unmarshals it
164+
// into the specified object.
165+
func (c *CompletedRequest) UnmarshalJsonToObject(obj interface{}) error {
166+
return json.Unmarshal(c.Recorder.Body.Bytes(), obj)
167+
}
168+
169+
// Shortcut for response code
170+
func (c *CompletedRequest) Code() int {
171+
return c.Recorder.Code
172+
}

0 commit comments

Comments
 (0)