package openapi_test import ( "encoding/json" omni "git.yuntuo.hk/k2safe/go-omni" "git.yuntuo.hk/k2safe/go-omni/httpx" "git.yuntuo.hk/k2safe/go-omni/openapi" "net/http/httptest" "testing" ) func TestRouteAndContract(t *testing.T) { type item struct { ID int64 `json:"id,string"` RequestID string `json:"requestId,omitempty"` Payload json.RawMessage `json:"payload"` } schema, err := openapi.SchemaOf[item]() if err != nil || schema.Properties["id"].Type != "string" || schema.Properties["payload"].Type != "" { t.Fatal(schema, err) } api, _ := openapi.New("Test API", "1") app := omni.New(omni.WithLogger(false)) op := openapi.Operation{Method: "GET", Path: "/items/:id", OperationID: "getItem", Parameters: []openapi.Parameter{{Name: "id", In: "path", Required: true, Schema: &openapi.Schema{Type: "string"}}}, Responses: map[int]openapi.Response{200: {Description: "OK", Schema: openapi.Envelope(schema)}}} if err = api.Handle(app, op, func(c *httpx.Context) error { return c.OK(item{ID: 1, Payload: json.RawMessage(`{}`)}) }); err != nil { t.Fatal(err) } // Caller edits must not mutate the published contract. schema.Properties["id"].Type = "boolean" if err = api.Handle(app, op, func(*httpx.Context) error { return nil }); err == nil { t.Fatal("duplicate accepted") } app.GET("/openapi.json", api.Handler()) r := httptest.NewRecorder() app.ServeHTTP(r, httptest.NewRequest("GET", "/openapi.json", nil)) var doc struct { OpenAPI string `json:"openapi"` Paths map[string]json.RawMessage `json:"paths"` } if err = json.Unmarshal(r.Body.Bytes(), &doc); err != nil || doc.OpenAPI != "3.0.3" || doc.Paths["/items/{id}"] == nil { t.Fatal(r.Body.String(), err) } r = httptest.NewRecorder() app.ServeHTTP(r, httptest.NewRequest("GET", "/items/1", nil)) if r.Code != 200 { t.Fatal(r.Code) } type recursive struct { Next *recursive `json:"next"` } if _, err = openapi.SchemaOf[recursive](); err == nil { t.Fatal("recursive DTO silently truncated") } }