forked from h2non/baloo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
expect.go
243 lines (207 loc) · 6.25 KB
/
expect.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
package baloo
import (
"fmt"
"net/http"
"gopkg.in/h2non/baloo.v3/assert"
"gopkg.in/h2non/gentleman.v2"
)
// Assertions stores global assertion functions by alias name.
// Use Expect.Assert('<assertion name>') to use
// new assertion at request expectation level.
var Assertions = make(map[string]assert.Func)
// AddAssertFunc adds a new assertion function at global level by alias name.
// Then you can trigger the assertion function in any expectation test.
func AddAssertFunc(name string, fn assert.Func) {
Assertions[name] = fn
}
// FlushAssertFuncs flushes registered assertion functions.
func FlushAssertFuncs() {
Assertions = make(map[string]assert.Func)
}
// TestingT implements part of the same interface as testing.T
type TestingT interface {
Error(args ...interface{})
}
// Expect represents the HTTP expectation suite who is
// able to define multiple assertion functions to match the response.
type Expect struct {
test TestingT
request *Request
assertions []assert.Func
}
// NewExpect creates a new testing expectation instance.
func NewExpect(req *Request) *Expect {
return &Expect{request: req}
}
// BindTest binds the Go testing instance to the current suite.
// In the future multiple testing interfaces can
// be supported via adapters.
func (e *Expect) BindTest(t TestingT) *Expect {
e.test = t
return e
}
// Status asserts the response status code
// with the given status.
func (e *Expect) Status(code int) *Expect {
e.AssertFunc(assert.StatusEqual(code))
return e
}
// StatusOk asserts the response status code
// as valid response (>= 200 && < 400).
func (e *Expect) StatusOk() *Expect {
e.AssertFunc(assert.StatusOk())
return e
}
// StatusError asserts the response status code
// as client/server error response (>= 400 && < 600).
func (e *Expect) StatusError() *Expect {
e.AssertFunc(assert.StatusError())
return e
}
// StatusServerError asserts the response status code
// as server error response (>= 500 && < 600).
func (e *Expect) StatusServerError() *Expect {
e.AssertFunc(assert.StatusServerError())
return e
}
// StatusClientError asserts the response status code
// as server error response (>= 400 && < 500).
func (e *Expect) StatusClientError() *Expect {
e.AssertFunc(assert.StatusClientError())
return e
}
// Type asserts the response MIME type with the given alias or value.
func (e *Expect) Type(kind string) *Expect {
e.AssertFunc(assert.Type(kind))
return e
}
// Header asserts a response header field value matches.
// Regular expressions can be used as value to perform the specific assertions.
func (e *Expect) Header(key, value string) *Expect {
e.AssertFunc(assert.Header(key, value))
return e
}
// HeaderEquals asserts a response header field value
// is equal to the given value.
func (e *Expect) HeaderEquals(key, value string) *Expect {
e.AssertFunc(assert.HeaderEquals(key, value))
return e
}
// HeaderNotEquals asserts that a response header field value
// is not equal to the given one.
func (e *Expect) HeaderNotEquals(key, value string) *Expect {
e.AssertFunc(assert.HeaderNotEquals(key, value))
return e
}
// HeaderPresent asserts if a header field is present
// in the response.
func (e *Expect) HeaderPresent(key string) *Expect {
e.AssertFunc(assert.HeaderPresent(key))
return e
}
// HeaderNotPresent asserts if a header field is not
// present in the response.
func (e *Expect) HeaderNotPresent(key string) *Expect {
e.AssertFunc(assert.HeaderNotPresent(key))
return e
}
// RedirectTo asserts the server response redirects
// to the given URL pattern.
// Regular expressions are supported.
func (e *Expect) RedirectTo(uri string) *Expect {
e.AssertFunc(assert.RedirectTo(uri))
return e
}
// BodyEquals asserts as strict equality comparison the
// response body with a given string string.
func (e *Expect) BodyEquals(pattern string) *Expect {
e.AssertFunc(assert.BodyEquals(pattern))
return e
}
// BodyMatchString asserts a response body matching a string expression.
// Regular expressions can be used as value to perform the specific assertions.
func (e *Expect) BodyMatchString(pattern string) *Expect {
e.AssertFunc(assert.BodyMatchString(pattern))
return e
}
// BodyLength asserts a response body length.
func (e *Expect) BodyLength(length int) *Expect {
e.AssertFunc(assert.BodyLength(length))
return e
}
// JSON asserts the response body with the given JSON struct.
func (e *Expect) JSON(data interface{}) *Expect {
e.AssertFunc(assert.JSON(data))
return e
}
// JSONSchema asserts the response body with the given
// JSON schema definition.
func (e *Expect) JSONSchema(schema string) *Expect {
e.AssertFunc(assert.JSONSchema(schema))
return e
}
// Assert adds a new assertion function by alias name.
// Assertion function must be previosly registered
// via baloo.AddAssertFunc("alias", function).
func (e *Expect) Assert(assertions ...string) *Expect {
for _, alias := range assertions {
fn, ok := Assertions[alias]
if !ok {
panic("No assertion function registered by alias: " + alias)
}
e.assertions = append(e.assertions, fn)
}
return e
}
// AssertFunc adds a new assertion function.
func (e *Expect) AssertFunc(assertion ...assert.Func) *Expect {
e.assertions = append(e.assertions, assertion...)
return e
}
// Done performs and asserts the HTTP response based
// on the defined expectations.
func (e *Expect) Done() error {
// Perform the HTTP request
res, err := e.request.Send()
if err != nil {
err = fmt.Errorf("request error: %s", err)
e.test.Error(err)
return err
}
// Run assertions
err = e.run(res.RawResponse, res.RawRequest)
if err != nil {
e.test.Error(err)
}
return err
}
// End is an alias to `Done()`.
func (e *Expect) End() error {
return e.Done()
}
func (e *Expect) run(res *http.Response, req *http.Request) error {
var err error
for _, assertion := range e.assertions {
err = assertion(res, req)
if err != nil {
break
}
}
return err
}
// Send does the same as `Done()`, but it also returns the `*http.Response` along with the `error`.
func (e *Expect) Send() (*gentleman.Response, error) {
// Perform the HTTP request
res, err := e.request.Send()
if err != nil {
err = fmt.Errorf("request error: %s", err)
e.test.Error(err)
return res, err
}
// Run assertions
err = e.run(res.RawResponse, res.RawRequest)
if err != nil {
e.test.Error(err)
}
return res, err
}