package app import ( "context" "net/http" "testing" ) func TestBatchImportHTTP(t *testing.T) { t.Parallel() t.Run("POST create run returns run summary", func(t *testing.T) { t.Parallel() handler := NewAPIHandler("secret-token", ActionSet{ CreateBatchImportRun: func(_ context.Context, req CreateBatchImportRunRequest) (BatchImportRunCreateResponse, error) { if req.HostID != "host-1" { t.Fatalf("HostID = %q, want host-1", req.HostID) } if req.AccessMode != "subscription" { t.Fatalf("AccessMode = %q, want subscription", req.AccessMode) } if len(req.SubscriptionUsers) != 1 || req.SubscriptionUsers[0] != "user-1" { t.Fatalf("SubscriptionUsers = %#v, want [user-1]", req.SubscriptionUsers) } if len(req.Entries) != 1 || req.Entries[0].BaseURL != "https://kimi.example.com/v1" { t.Fatalf("Entries = %#v, want request payload", req.Entries) } return BatchImportRunCreateResponse{ RunID: "run_20260522_0001", State: "running", ResultPage: "/batch-import/runs/run_20260522_0001", TotalItems: 1, ActiveItems: 0, DegradedItems: 0, BrokenItems: 0, WarningItems: 0, }, nil }, }) req := httptestRequest(t, http.MethodPost, "/api/batch-import/runs", map[string]any{ "host_id": "host-1", "mode": "strict", "access_mode": "subscription", "subscription_users": []string{"user-1"}, "subscription_days": 30, "entries": []map[string]any{ {"base_url": "https://kimi.example.com/v1", "api_key": "sk-test", "requested_models": []string{"kimi-k2.6"}}, }, }, "secret-token") res := httptestRecorder(handler, req) assertStatusCode(t, res, http.StatusOK) assertJSONContains(t, res.Body().Bytes(), "run_id", "run_20260522_0001") assertJSONContains(t, res.Body().Bytes(), "result_page", "/batch-import/runs/run_20260522_0001") }) t.Run("subscription request requires subscription fields", func(t *testing.T) { t.Parallel() handler := NewAPIHandler("secret-token", ActionSet{ CreateBatchImportRun: func(_ context.Context, req CreateBatchImportRunRequest) (BatchImportRunCreateResponse, error) { t.Fatal("CreateBatchImportRun should not be called when request is invalid") return BatchImportRunCreateResponse{}, nil }, }) req := httptestRequest(t, http.MethodPost, "/api/batch-import/runs", map[string]any{ "host_id": "host-1", "mode": "strict", "access_mode": "subscription", "entries": []map[string]any{ {"base_url": "https://kimi.example.com/v1", "api_key": "sk-test"}, }, }, "secret-token") res := httptestRecorder(handler, req) assertStatusCode(t, res, http.StatusBadRequest) assertJSONContains(t, res.Body().Bytes(), "error.code", "invalid_request") }) t.Run("self service request requires probe api key", func(t *testing.T) { t.Parallel() handler := NewAPIHandler("secret-token", ActionSet{ CreateBatchImportRun: func(_ context.Context, req CreateBatchImportRunRequest) (BatchImportRunCreateResponse, error) { t.Fatal("CreateBatchImportRun should not be called when request is invalid") return BatchImportRunCreateResponse{}, nil }, }) req := httptestRequest(t, http.MethodPost, "/api/batch-import/runs", map[string]any{ "host_id": "host-1", "mode": "partial", "access_mode": "self_service", "entries": []map[string]any{ {"base_url": "https://deepseek.example.com/v1", "api_key": "sk-test"}, }, }, "secret-token") res := httptestRecorder(handler, req) assertStatusCode(t, res, http.StatusBadRequest) assertJSONContains(t, res.Body().Bytes(), "error.code", "invalid_request") assertJSONContains(t, res.Body().Bytes(), "error.message", "probe_api_key is required when access_mode=self_service") }) t.Run("create run requires host id", func(t *testing.T) { t.Parallel() handler := NewAPIHandler("secret-token", ActionSet{ CreateBatchImportRun: func(_ context.Context, req CreateBatchImportRunRequest) (BatchImportRunCreateResponse, error) { t.Fatal("CreateBatchImportRun should not be called when host_id is missing") return BatchImportRunCreateResponse{}, nil }, }) req := httptestRequest(t, http.MethodPost, "/api/batch-import/runs", map[string]any{ "mode": "strict", "access_mode": "subscription", "subscription_users": []string{"user-1"}, "subscription_days": 30, "entries": []map[string]any{ {"base_url": "https://kimi.example.com/v1", "api_key": "sk-test"}, }, }, "secret-token") res := httptestRecorder(handler, req) assertStatusCode(t, res, http.StatusBadRequest) assertJSONContains(t, res.Body().Bytes(), "error.code", "invalid_request") assertJSONContains(t, res.Body().Bytes(), "error.message", "host_id is required") }) }