-
-
Notifications
You must be signed in to change notification settings - Fork 150
/
api_test.go
128 lines (110 loc) · 3.54 KB
/
api_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
125
126
127
128
package huma_test
import (
"context"
"net/http"
"testing"
"github.com/danielgtaylor/huma/v2"
"github.com/danielgtaylor/huma/v2/adapters/humachi"
"github.com/danielgtaylor/huma/v2/humatest"
"github.com/go-chi/chi/v5"
"github.com/stretchr/testify/assert"
)
func TestBlankConfig(t *testing.T) {
adapter := humatest.NewAdapter()
assert.NotPanics(t, func() {
huma.NewAPI(huma.Config{}, adapter)
})
}
// ExampleAdapter_handle demonstrates how to use the adapter directly
// instead of using the `huma.Register` convenience function to add a new
// operation and handler to the API.
//
// Note that you are responsible for defining all of the operation details,
// including the parameter and response definitions & schemas.
func ExampleAdapter_handle() {
// Create an adapter for your chosen router.
adapter := NewExampleAdapter()
// Register an operation with a custom handler.
adapter.Handle(&huma.Operation{
OperationID: "example-operation",
Method: "GET",
Path: "/example/{name}",
Summary: "Example operation",
Parameters: []*huma.Param{
{
Name: "name",
In: "path",
Description: "Name to return",
Required: true,
Schema: &huma.Schema{
Type: "string",
},
},
},
Responses: map[string]*huma.Response{
"200": {
Description: "OK",
Content: map[string]*huma.MediaType{
"text/plain": {
Schema: &huma.Schema{
Type: "string",
},
},
},
},
},
}, func(ctx huma.Context) {
// Get the `name` path parameter.
name := ctx.Param("name")
// Set the response content type, status code, and body.
ctx.SetHeader("Content-Type", "text/plain; charset=utf-8")
ctx.SetStatus(http.StatusOK)
ctx.BodyWriter().Write([]byte("Hello, " + name))
})
}
func TestContextValue(t *testing.T) {
_, api := humatest.New(t)
api.UseMiddleware(func(ctx huma.Context, next func(huma.Context)) {
// Make an updated context available to the handler.
ctx = huma.WithValue(ctx, "foo", "bar")
next(ctx)
assert.Equal(t, http.StatusNoContent, ctx.Status())
})
// Register a simple hello world operation in the API.
huma.Get(api, "/test", func(ctx context.Context, input *struct{}) (*struct{}, error) {
assert.Equal(t, "bar", ctx.Value("foo"))
return nil, nil
})
resp := api.Get("/test")
assert.Equal(t, http.StatusNoContent, resp.Code)
}
func TestChiRouterPrefix(t *testing.T) {
mux := chi.NewMux()
var api huma.API
mux.Route("/api", func(r chi.Router) {
config := huma.DefaultConfig("My API", "1.0.0")
config.Servers = []*huma.Server{{URL: "http://localhost:8888/api"}}
api = humachi.New(r, config)
})
type TestOutput struct {
Body struct {
Field string `json:"field"`
}
}
// Register a simple hello world operation in the API.
huma.Get(api, "/test", func(ctx context.Context, input *struct{}) (*TestOutput, error) {
return &TestOutput{}, nil
})
// Create a test API around the underlying router to make easier requests.
tapi := humatest.Wrap(t, humachi.New(mux, huma.DefaultConfig("Test", "1.0.0")))
// The top-level router should respond to the full path even though the
// operation was registered with just `/test`.
resp := tapi.Get("/api/test")
assert.Equal(t, http.StatusOK, resp.Code)
// The transformer should generate links with the full URL path.
assert.Contains(t, resp.Header().Get("Link"), "/api/schemas/TestOutputBody.json")
// The docs HTML should point to the full URL including base path.
resp = tapi.Get("/api/docs")
assert.Equal(t, http.StatusOK, resp.Code)
assert.Contains(t, resp.Body.String(), "/api/openapi.yaml")
}