Files

172 lines
5.2 KiB
Go

// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-present Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package mcp
import (
"context"
"net/http"
"strconv"
"strings"
"testing"
"github.com/danielgtaylor/huma/v2"
"github.com/danielgtaylor/huma/v2/autopatch"
"github.com/danielgtaylor/huma/v2/humatest"
"github.com/stretchr/testify/require"
)
func newTestModule(t *testing.T) *Module {
t.Helper()
m, err := New(newTestAPI(t), nil)
require.NoError(t, err)
return m
}
type testThing struct {
ID int64 `json:"id" readOnly:"true"`
Title string `json:"title" valid:"required" minLength:"1"`
Description string `json:"description"`
Done bool `json:"done"`
Owner *testOwner `json:"owner" readOnly:"true"`
Reminders []*testWhen `json:"reminders"`
}
type testOwner struct {
ID int64 `json:"id"`
Name string `json:"name"`
}
type testWhen struct {
At string `json:"at" format:"date-time"`
}
type testThingBody struct{ Body *testThing }
type echoBody struct {
Body struct {
Method string `json:"method"`
Path string `json:"path"`
Query map[string]string `json:"query"`
Auth string `json:"auth"`
CT string `json:"content_type"`
Body *testThing `json:"body,omitempty"`
}
}
func newTestAPI(t *testing.T) huma.API {
t.Helper()
cfg := huma.DefaultConfig("test", "1")
cfg.FieldsOptionalByDefault = true
_, api := humatest.New(t, cfg)
huma.Register(api, huma.Operation{
OperationID: "things-list",
Method: http.MethodGet,
Path: "/things",
Summary: "List things",
},
func(_ context.Context, in *struct {
Q string `query:"q"`
Filter string `query:"filter" doc:"Filter things."`
Page int `query:"page" default:"1" minimum:"1"`
Expand []string `query:"expand,explode" enum:"a,b"`
Format string `query:"format" enum:"html,markdown"`
Auth string `header:"Authorization"`
}) (*echoBody, error) {
out := &echoBody{}
out.Body.Method, out.Body.Path, out.Body.Auth = http.MethodGet, "/things", in.Auth
out.Body.Query = map[string]string{
"q": in.Q,
"format": in.Format,
"expand": strings.Join(in.Expand, "|"),
}
return out, nil
})
huma.Register(api, huma.Operation{
OperationID: "things-read",
Method: http.MethodGet,
Path: "/things/{id}",
}, func(_ context.Context, in *struct {
ID int64 `path:"id"`
}) (*testThingBody, error) {
if in.ID == 404 {
return nil, huma.Error404NotFound("no such thing")
}
if in.ID == 401 {
return nil, huma.Error401Unauthorized("Unauthorized")
}
return &testThingBody{
Body: &testThing{
ID: in.ID,
Title: "stored",
Description: "keep me",
Owner: &testOwner{ID: 1},
},
}, nil
})
huma.Register(api, huma.Operation{
OperationID: "things-create",
Method: http.MethodPost,
Path: "/things",
}, func(_ context.Context, in *struct {
Body testThing
CT string `header:"Content-Type"`
}) (*echoBody, error) {
out := &echoBody{}
out.Body.Method, out.Body.Path, out.Body.CT = http.MethodPost, "/things", in.CT
out.Body.Body = &in.Body
return out, nil
})
huma.Register(api, huma.Operation{
OperationID: "things-update",
Method: http.MethodPut,
Path: "/things/{id}",
Summary: "Update a thing",
Description: "Moving a thing needs write access to the target.",
}, func(_ context.Context, in *struct {
ID int64 `path:"id"`
Body testThing
CT string `header:"Content-Type"`
}) (*echoBody, error) {
out := &echoBody{}
out.Body.Method, out.Body.Path, out.Body.CT = http.MethodPut, "/things/"+strconv.FormatInt(in.ID, 10), in.CT
out.Body.Body = &in.Body
return out, nil
})
huma.Register(api, huma.Operation{
OperationID: "things-delete",
Method: http.MethodDelete,
Path: "/things/{id}",
}, func(_ context.Context, _ *struct {
ID int64 `path:"id"`
}) (*struct{}, error) {
return nil, nil
})
huma.Register(api, huma.Operation{
OperationID: "tokens-create",
Method: http.MethodPost,
Path: "/tokens",
}, func(_ context.Context, _ *struct{ Body testThing }) (*testThingBody, error) { return nil, nil })
huma.Register(api, huma.Operation{
OperationID: "things-upload",
Method: http.MethodPost,
Path: "/things/{id}/file",
}, func(_ context.Context, _ *struct {
ID int64 `path:"id"`
RawBody huma.MultipartFormFiles[struct{}]
}) (*struct{}, error) {
return nil, nil
})
autopatch.AutoPatch(api)
return api
}