forked from danielgtaylor/huma
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathresolver_test.go
124 lines (106 loc) · 3.72 KB
/
resolver_test.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
package huma
import (
"net/http"
"net/http/httptest"
"strings"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestExhaustiveErrors(t *testing.T) {
type Input struct {
BoolParam bool `query:"bool"`
IntParam int `query:"int"`
Float32Param float32 `query:"float32"`
Float64Param float64 `query:"float64"`
Tags []int `query:"tags"`
Time time.Time `query:"time"`
Body struct {
Test int `json:"test" minimum:"5"`
}
}
app := newTestRouter()
app.Resource("/").Get("test", "Test").Run(func(ctx Context, input Input) {
// Do nothing
})
w := httptest.NewRecorder()
r, _ := http.NewRequest(http.MethodGet, "/?bool=bad&int=bad&float32=bad&float64=bad&tags=1,2,bad&time=bad", strings.NewReader(`{"test": 1}`))
r.Host = "example.com"
app.ServeHTTP(w, r)
assert.JSONEq(t, `{"$schema": "https://example.com/schemas/ErrorModel.json", "title":"Bad Request","status":400,"detail":"Error while parsing input parameters","errors":[{"message":"cannot parse boolean","location":"query.bool","value":"bad"},{"message":"cannot parse integer","location":"query.int","value":"bad"},{"message":"cannot parse float","location":"query.float32","value":"bad"},{"message":"cannot parse float","location":"query.float64","value":"bad"},{"message":"cannot parse integer","location":"query[2].tags","value":"bad"},{"message":"unable to validate against schema: invalid character 'b' looking for beginning of value","location":"query.tags","value":"[1,2,bad]"},{"message":"cannot parse time","location":"query.time","value":"bad"},{"message":"Must be greater than or equal to 5","location":"body.test","value":1}]}`, w.Body.String())
}
type Dep1 struct {
// Only *one* of the following two may be set.
One string `json:"one,omitempty"`
Two string `json:"two,omitempty"`
}
func (d *Dep1) Resolve(ctx Context, r *http.Request) {
if d.One != "" && d.Two != "" {
ctx.AddError(&ErrorDetail{
Message: "Only one of ['one', 'two'] is allowed.",
Location: "one",
Value: d.One,
})
}
}
type Dep2 struct {
// Test recursive resolver with complex input structure containing a map of
// lists of struct pointers.
Foo map[string][]*Dep1 `json:"foo"`
}
func TestNestedResolver(t *testing.T) {
app := newTestRouter()
app.Resource("/").Post("test", "Test",
NewResponse(http.StatusNoContent, "desc"),
).Run(func(ctx Context, input struct {
Body Dep2
}) {
ctx.WriteHeader(http.StatusNoContent)
})
// Test happy case just sending ONE of the two possible fields in each struct.
w := httptest.NewRecorder()
r, _ := http.NewRequest(http.MethodPost, "/", strings.NewReader(`{
"foo": {
"a": [{"one": "1"}],
"b": [{"two": "2"}]
}
}`))
app.ServeHTTP(w, r)
assert.Equal(t, http.StatusNoContent, w.Result().StatusCode)
}
func TestNestedResolverError(t *testing.T) {
app := newTestRouter()
app.Resource("/").Post("test", "Test",
NewResponse(http.StatusNoContent, "desc"),
).Run(func(ctx Context, input struct {
Body Dep2
}) {
ctx.WriteHeader(http.StatusNoContent)
})
// Test error case where we send BOTH fields in the same struct, which is
// not allowed. Should get a validation error response generated by the
// `Dep1.Resolve(...)` method above.
w := httptest.NewRecorder()
r, _ := http.NewRequest(http.MethodPost, "/", strings.NewReader(`{
"foo": {
"a": [
{"one": "1", "two": "2"}
]
}
}`))
r.Host = "example.com"
app.ServeHTTP(w, r)
assert.JSONEq(t, `{
"$schema": "https://example.com/schemas/ErrorModel.json",
"status": 400,
"title": "Bad Request",
"detail": "Error while parsing input parameters",
"errors": [
{
"message": "Only one of ['one', 'two'] is allowed.",
"location": "body.foo.a[0].one",
"value": "1"
}
]
}`, w.Body.String())
}