package httpapi import ( "archive/zip" "bytes" "encoding/json" "io" "log/slog" "net/http" "net/http/httptest" "strings" "testing" ) func TestGetOpsManagementSkillMetadata(t *testing.T) { server := &Server{logger: slog.New(slog.NewTextHandler(io.Discard, nil))} request := httptest.NewRequest(http.MethodGet, "/api/v1/public/skills/ai-gateway-ops-management/metadata", nil) response := httptest.NewRecorder() server.getOpsManagementSkillMetadata(response, request) if response.Code != http.StatusOK { t.Fatalf("expected metadata status 200, got %d: %s", response.Code, response.Body.String()) } var metadata SkillBundleMetadataResponse if err := json.Unmarshal(response.Body.Bytes(), &metadata); err != nil { t.Fatalf("decode metadata: %v", err) } if metadata.Name != "ai-gateway-ops-management" || metadata.Version != "1.0.2" { t.Fatalf("unexpected metadata: %+v", metadata) } if len(metadata.Modules) != 1 || metadata.Modules[0] != "model-runtime" { t.Fatalf("unexpected metadata modules: %+v", metadata.Modules) } if metadata.APIDocsJSONPath != "/api-docs-json" || metadata.APIDocsYAMLPath != "/api-docs-yaml" { t.Fatalf("unexpected API docs paths: %+v", metadata) } } func TestDownloadOpsManagementSkill(t *testing.T) { server := &Server{logger: slog.New(slog.NewTextHandler(io.Discard, nil))} request := httptest.NewRequest(http.MethodGet, "/api/v1/public/skills/ai-gateway-ops-management/download", nil) response := httptest.NewRecorder() server.downloadOpsManagementSkill(response, request) if response.Code != http.StatusOK { t.Fatalf("expected download status 200, got %d: %s", response.Code, response.Body.String()) } if response.Header().Get("Content-Type") != "application/zip" { t.Fatalf("unexpected content type: %q", response.Header().Get("Content-Type")) } if disposition := response.Header().Get("Content-Disposition"); !strings.Contains(disposition, "ai-gateway-ops-management-v1.0.2.zip") { t.Fatalf("unexpected content disposition: %q", disposition) } raw := response.Body.Bytes() archive, err := zip.NewReader(bytes.NewReader(raw), int64(len(raw))) if err != nil { t.Fatalf("open downloaded archive: %v", err) } foundSkill := false for _, file := range archive.File { if file.Name == "SKILL.md" { foundSkill = true break } } if !foundSkill { t.Fatalf("downloaded archive does not contain SKILL.md") } } func TestEmbeddedAPIDocs(t *testing.T) { server := &Server{} jsonResponse := httptest.NewRecorder() server.apiDocsJSON(jsonResponse, httptest.NewRequest(http.MethodGet, "/api-docs-json", nil)) if jsonResponse.Code != http.StatusOK { t.Fatalf("expected JSON docs status 200, got %d", jsonResponse.Code) } if jsonResponse.Header().Get("Content-Type") != "application/json; charset=utf-8" { t.Fatalf("unexpected JSON docs content type: %q", jsonResponse.Header().Get("Content-Type")) } var document struct { Paths map[string]json.RawMessage `json:"paths"` } if err := json.Unmarshal(jsonResponse.Body.Bytes(), &document); err != nil { t.Fatalf("decode embedded Swagger JSON: %v", err) } for _, path := range []string{ "/api-docs-json", "/api/v1/public/skills/ai-gateway-ops-management/download", "/api/admin/catalog/providers", "/api/admin/catalog/base-models", "/api/admin/platforms", "/api/admin/runtime/policy-sets", "/api/admin/pricing/rule-sets", } { if document.Paths[path] == nil { t.Fatalf("embedded Swagger JSON missing %q", path) } } yamlResponse := httptest.NewRecorder() server.apiDocsYAML(yamlResponse, httptest.NewRequest(http.MethodGet, "/api-docs-yaml", nil)) if yamlResponse.Code != http.StatusOK { t.Fatalf("expected YAML docs status 200, got %d", yamlResponse.Code) } if yamlResponse.Header().Get("Content-Type") != "application/yaml; charset=utf-8" { t.Fatalf("unexpected YAML docs content type: %q", yamlResponse.Header().Get("Content-Type")) } if !strings.Contains(yamlResponse.Body.String(), "/api/v1/public/skills/ai-gateway-ops-management/metadata") { t.Fatalf("embedded Swagger YAML missing operations skill metadata path") } }