From c245da12215b044a31a4f9548865df25f2965011 Mon Sep 17 00:00:00 2001 From: JoannaaKL Date: Fri, 19 Dec 2025 14:28:24 +0100 Subject: [PATCH] Continue replacing migueleliasweb/go-github-mock --- pkg/github/actions_test.go | 123 ++++++++-------- pkg/github/helper_test.go | 175 +++++++++++++++++++++- pkg/github/projects_test.go | 283 ++++++++++++++++++------------------ pkg/github/search_test.go | 99 +++++++------ 4 files changed, 425 insertions(+), 255 deletions(-) diff --git a/pkg/github/actions_test.go b/pkg/github/actions_test.go index f2d336e21..8ce5bd2e3 100644 --- a/pkg/github/actions_test.go +++ b/pkg/github/actions_test.go @@ -18,7 +18,6 @@ import ( "github.com/github/github-mcp-server/pkg/translations" "github.com/google/go-github/v79/github" "github.com/google/jsonschema-go/jsonschema" - "github.com/migueleliasweb/go-github-mock/src/mock" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -1394,9 +1393,9 @@ func Test_RerunFailedJobs(t *testing.T) { }{ { name: "successful rerun of failed jobs", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{ + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{ Pattern: "/repos/owner/repo/actions/runs/12345/rerun-failed-jobs", Method: "POST", }, @@ -1414,7 +1413,7 @@ func Test_RerunFailedJobs(t *testing.T) { }, { name: "missing required parameter run_id", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]any{ "owner": "owner", "repo": "repo", @@ -1466,9 +1465,9 @@ func Test_RerunWorkflowRun_Behavioral(t *testing.T) { }{ { name: "successful rerun of workflow run", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{ + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{ Pattern: "/repos/owner/repo/actions/runs/12345/rerun", Method: "POST", }, @@ -1486,7 +1485,7 @@ func Test_RerunWorkflowRun_Behavioral(t *testing.T) { }, { name: "missing required parameter run_id", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]any{ "owner": "owner", "repo": "repo", @@ -1538,9 +1537,9 @@ func Test_ListWorkflowRuns_Behavioral(t *testing.T) { }{ { name: "successful workflow runs listing", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.GetReposActionsWorkflowsRunsByOwnerByRepoByWorkflowId, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + GetReposActionsWorkflowsRunsByOwnerByRepoByWorkflowID, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { runs := &github.WorkflowRuns{ TotalCount: github.Ptr(2), @@ -1573,7 +1572,7 @@ func Test_ListWorkflowRuns_Behavioral(t *testing.T) { }, { name: "missing required parameter workflow_id", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]any{ "owner": "owner", "repo": "repo", @@ -1625,9 +1624,9 @@ func Test_GetWorkflowRun_Behavioral(t *testing.T) { }{ { name: "successful get workflow run", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.GetReposActionsRunsByOwnerByRepoByRunId, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + GetReposActionsRunsByOwnerByRepoByRunID, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { run := &github.WorkflowRun{ ID: github.Ptr(int64(12345)), @@ -1649,7 +1648,7 @@ func Test_GetWorkflowRun_Behavioral(t *testing.T) { }, { name: "missing required parameter run_id", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]any{ "owner": "owner", "repo": "repo", @@ -1701,9 +1700,9 @@ func Test_GetWorkflowRunLogs_Behavioral(t *testing.T) { }{ { name: "successful get workflow run logs", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.GetReposActionsRunsLogsByOwnerByRepoByRunId, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + GetReposActionsRunsLogsByOwnerByRepoByRunID, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.Header().Set("Location", "https://github.com/logs/run/12345") w.WriteHeader(http.StatusFound) @@ -1719,7 +1718,7 @@ func Test_GetWorkflowRunLogs_Behavioral(t *testing.T) { }, { name: "missing required parameter run_id", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]any{ "owner": "owner", "repo": "repo", @@ -1771,9 +1770,9 @@ func Test_ListWorkflowJobs_Behavioral(t *testing.T) { }{ { name: "successful list workflow jobs", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.GetReposActionsRunsJobsByOwnerByRepoByRunId, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + GetReposActionsRunsJobsByOwnerByRepoByRunID, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { jobs := &github.Jobs{ TotalCount: github.Ptr(2), @@ -1806,7 +1805,7 @@ func Test_ListWorkflowJobs_Behavioral(t *testing.T) { }, { name: "missing required parameter run_id", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]any{ "owner": "owner", "repo": "repo", @@ -1873,9 +1872,9 @@ func Test_ActionsList_ListWorkflows(t *testing.T) { }{ { name: "successful workflow list", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.GetReposActionsWorkflowsByOwnerByRepo, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + GetReposActionsWorkflowsByOwnerByRepo, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { workflows := &github.Workflows{ TotalCount: github.Ptr(2), @@ -1908,7 +1907,7 @@ func Test_ActionsList_ListWorkflows(t *testing.T) { }, { name: "missing required parameter method", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]any{ "owner": "owner", "repo": "repo", @@ -1952,9 +1951,9 @@ func Test_ActionsList_ListWorkflowRuns(t *testing.T) { toolDef := ActionsList(translations.NullTranslationHelper) t.Run("successful workflow runs list", func(t *testing.T) { - mockedClient := mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.GetReposActionsWorkflowsRunsByOwnerByRepoByWorkflowId, + mockedClient := NewMockedHTTPClient( + WithRequestMatchHandler( + GetReposActionsWorkflowsRunsByOwnerByRepoByWorkflowID, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { runs := &github.WorkflowRuns{ TotalCount: github.Ptr(1), @@ -1998,7 +1997,7 @@ func Test_ActionsList_ListWorkflowRuns(t *testing.T) { }) t.Run("missing resource_id for list_workflow_runs", func(t *testing.T) { - mockedClient := mock.NewMockedHTTPClient() + mockedClient := NewMockedHTTPClient() client := github.NewClient(mockedClient) deps := BaseDeps{ @@ -2040,9 +2039,9 @@ func Test_ActionsGet_GetWorkflow(t *testing.T) { toolDef := ActionsGet(translations.NullTranslationHelper) t.Run("successful workflow get", func(t *testing.T) { - mockedClient := mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.GetReposActionsWorkflowsByOwnerByRepoByWorkflowId, + mockedClient := NewMockedHTTPClient( + WithRequestMatchHandler( + GetReposActionsWorkflowsByOwnerByRepoByWorkflowID, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { workflow := &github.Workflow{ ID: github.Ptr(int64(1)), @@ -2086,9 +2085,9 @@ func Test_ActionsGet_GetWorkflowRun(t *testing.T) { toolDef := ActionsGet(translations.NullTranslationHelper) t.Run("successful workflow run get", func(t *testing.T) { - mockedClient := mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.GetReposActionsRunsByOwnerByRepoByRunId, + mockedClient := NewMockedHTTPClient( + WithRequestMatchHandler( + GetReposActionsRunsByOwnerByRepoByRunID, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { run := &github.WorkflowRun{ ID: github.Ptr(int64(12345)), @@ -2157,9 +2156,9 @@ func Test_ActionsRunTrigger_RunWorkflow(t *testing.T) { }{ { name: "successful workflow run", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.PostReposActionsWorkflowsDispatchesByOwnerByRepoByWorkflowId, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + PostReposActionsWorkflowsDispatchesByOwnerByRepoByWorkflowID, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNoContent) }), @@ -2176,7 +2175,7 @@ func Test_ActionsRunTrigger_RunWorkflow(t *testing.T) { }, { name: "missing required parameter workflow_id", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]any{ "method": "run_workflow", "owner": "owner", @@ -2188,7 +2187,7 @@ func Test_ActionsRunTrigger_RunWorkflow(t *testing.T) { }, { name: "missing required parameter ref", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]any{ "method": "run_workflow", "owner": "owner", @@ -2233,9 +2232,9 @@ func Test_ActionsRunTrigger_CancelWorkflowRun(t *testing.T) { toolDef := ActionsRunTrigger(translations.NullTranslationHelper) t.Run("successful workflow run cancellation", func(t *testing.T) { - mockedClient := mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{ + mockedClient := NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{ Pattern: "/repos/owner/repo/actions/runs/12345/cancel", Method: "POST", }, @@ -2270,9 +2269,9 @@ func Test_ActionsRunTrigger_CancelWorkflowRun(t *testing.T) { }) t.Run("conflict when cancelling a workflow run", func(t *testing.T) { - mockedClient := mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{ + mockedClient := NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{ Pattern: "/repos/owner/repo/actions/runs/12345/cancel", Method: "POST", }, @@ -2304,7 +2303,7 @@ func Test_ActionsRunTrigger_CancelWorkflowRun(t *testing.T) { }) t.Run("missing run_id for non-run_workflow methods", func(t *testing.T) { - mockedClient := mock.NewMockedHTTPClient() + mockedClient := NewMockedHTTPClient() client := github.NewClient(mockedClient) deps := BaseDeps{ @@ -2351,9 +2350,9 @@ func Test_ActionsGetJobLogs_SingleJob(t *testing.T) { toolDef := ActionsGetJobLogs(translations.NullTranslationHelper) t.Run("successful single job logs with URL", func(t *testing.T) { - mockedClient := mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.GetReposActionsJobsLogsByOwnerByRepoByJobId, + mockedClient := NewMockedHTTPClient( + WithRequestMatchHandler( + GetReposActionsJobsLogsByOwnerByRepoByJobID, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.Header().Set("Location", "https://github.com/logs/job/123") w.WriteHeader(http.StatusFound) @@ -2392,9 +2391,9 @@ func Test_ActionsGetJobLogs_FailedJobs(t *testing.T) { toolDef := ActionsGetJobLogs(translations.NullTranslationHelper) t.Run("successful failed jobs logs", func(t *testing.T) { - mockedClient := mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.GetReposActionsRunsJobsByOwnerByRepoByRunId, + mockedClient := NewMockedHTTPClient( + WithRequestMatchHandler( + GetReposActionsRunsJobsByOwnerByRepoByRunID, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { jobs := &github.Jobs{ TotalCount: github.Ptr(3), @@ -2420,8 +2419,8 @@ func Test_ActionsGetJobLogs_FailedJobs(t *testing.T) { _ = json.NewEncoder(w).Encode(jobs) }), ), - mock.WithRequestMatchHandler( - mock.GetReposActionsJobsLogsByOwnerByRepoByJobId, + WithRequestMatchHandler( + GetReposActionsJobsLogsByOwnerByRepoByJobID, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Location", "https://github.com/logs/job/"+r.URL.Path[len(r.URL.Path)-1:]) w.WriteHeader(http.StatusFound) @@ -2457,9 +2456,9 @@ func Test_ActionsGetJobLogs_FailedJobs(t *testing.T) { }) t.Run("no failed jobs found", func(t *testing.T) { - mockedClient := mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.GetReposActionsRunsJobsByOwnerByRepoByRunId, + mockedClient := NewMockedHTTPClient( + WithRequestMatchHandler( + GetReposActionsRunsJobsByOwnerByRepoByRunID, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { jobs := &github.Jobs{ TotalCount: github.Ptr(2), diff --git a/pkg/github/helper_test.go b/pkg/github/helper_test.go index 56a236660..1e7cb37aa 100644 --- a/pkg/github/helper_test.go +++ b/pkg/github/helper_test.go @@ -41,7 +41,7 @@ const ( // Git endpoints GetReposGitTreesByOwnerByRepoByTree = "GET /repos/{owner}/{repo}/git/trees/{tree}" - GetReposGitRefByOwnerByRepoByRef = "GET /repos/{owner}/{repo}/git/ref/{ref}" + GetReposGitRefByOwnerByRepoByRef = "GET /repos/{owner}/{repo}/git/ref/{ref:.*}" PostReposGitRefsByOwnerByRepo = "POST /repos/{owner}/{repo}/git/refs" PatchReposGitRefsByOwnerByRepoByRef = "PATCH /repos/{owner}/{repo}/git/refs/{ref}" GetReposGitCommitsByOwnerByRepoByCommitSHA = "GET /repos/{owner}/{repo}/git/commits/{commit_sha}" @@ -564,10 +564,183 @@ func MockHTTPClientWithHandlers(handlers map[string]http.HandlerFunc) *http.Clie return &http.Client{Transport: transport} } +// mockHTTPClientOption configures a mocked HTTP client. +// +// This intentionally mirrors the go-github-mock API shape used across tests +// (NewMockedHTTPClient + WithRequestMatch/WithRequestMatchHandler) so we can +// remove that dependency while keeping test diffs minimal. +type mockHTTPClientOption func(*sequencedMultiHandlerTransport) + +// MockBackendOption mirrors the go-github-mock option type used throughout tests. +// It's an alias so existing call sites can keep the same shape after removing +// the external dependency. +type MockBackendOption = mockHTTPClientOption + +// EndpointPattern mirrors go-github-mock's EndpointPattern. +// It allows registering handlers for an exact method + path. +type EndpointPattern struct { + Pattern string + Method string +} + +// NewMockedHTTPClient creates an HTTP client that dispatches requests to the +// provided handlers based on method + path matching. +// +// Handlers can be registered multiple times per endpoint; they will be consumed +// in the order they were added. +func NewMockedHTTPClient(opts ...MockBackendOption) *http.Client { + transport := &sequencedMultiHandlerTransport{handlers: map[string][]http.HandlerFunc{}} + for _, opt := range opts { + opt(transport) + } + return &http.Client{Transport: transport} +} + +// WithRequestMatchHandler registers a handler for the given endpoint key. +// +// Endpoint keys are of the form: "METHOD /path/pattern". +func WithRequestMatchHandler(endpoint any, handler http.HandlerFunc) MockBackendOption { + endpointKey := normalizeEndpointKey(endpoint) + return func(t *sequencedMultiHandlerTransport) { + t.handlers[endpointKey] = append(t.handlers[endpointKey], handler) + } +} + +// WithRequestMatch registers a default JSON response (HTTP 200) for the given endpoint. +func WithRequestMatch(endpoint any, body any) MockBackendOption { + handler := http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusOK) + if body == nil { + return + } + if s, ok := body.(string); ok { + _, _ = w.Write([]byte(s)) + return + } + b, err := json.Marshal(body) + if err != nil { + panic(err) + } + _, _ = w.Write(b) + }) + return WithRequestMatchHandler(endpoint, handler) +} + +func normalizeEndpointKey(endpoint any) string { + switch v := endpoint.(type) { + case string: + return v + case EndpointPattern: + return v.Method + " " + v.Pattern + case *EndpointPattern: + if v == nil { + panic("nil EndpointPattern") + } + return v.Method + " " + v.Pattern + default: + panic("unsupported endpoint type") + } +} + +// MustMarshal marshals v to JSON and panics on error. +func MustMarshal(v any) []byte { + b, err := json.Marshal(v) + if err != nil { + panic(err) + } + return b +} + type multiHandlerTransport struct { handlers map[string]http.HandlerFunc } +type sequencedMultiHandlerTransport struct { + handlers map[string][]http.HandlerFunc +} + +func (m *sequencedMultiHandlerTransport) RoundTrip(req *http.Request) (*http.Response, error) { + // Check for catch-all handler. + if handler := m.popHandler(""); handler != nil { + return executeHandler(handler, req), nil + } + + key := req.Method + " " + req.URL.Path + if handler := m.popHandler(key); handler != nil { + return executeHandler(handler, req), nil + } + + // Pattern matching, prioritizing patterns without wildcards. + var wildcardPattern string + var wildcardHandler http.HandlerFunc + + for pattern := range m.handlers { + if pattern == "" { + continue + } + parts := strings.SplitN(pattern, " ", 2) + if len(parts) != 2 { + continue + } + method, pathPattern := parts[0], parts[1] + if req.Method != method { + continue + } + + isWildcard := strings.Contains(pathPattern, ":.*}") + if !matchPath(pathPattern, req.URL.Path) { + continue + } + + if isWildcard { + if handler := m.peekHandler(pattern); handler != nil { + wildcardPattern = pattern + wildcardHandler = handler + } + continue + } + + if handler := m.popHandler(pattern); handler != nil { + return executeHandler(handler, req), nil + } + } + + if wildcardPattern != "" && wildcardHandler != nil { + if handler := m.popHandler(wildcardPattern); handler != nil { + return executeHandler(handler, req), nil + } + } + + return &http.Response{ + StatusCode: http.StatusNotFound, + Body: io.NopCloser(bytes.NewReader([]byte("not found"))), + Request: req, + }, nil +} + +func (m *sequencedMultiHandlerTransport) peekHandler(key string) http.HandlerFunc { + queue, ok := m.handlers[key] + if !ok || len(queue) == 0 { + return nil + } + return queue[0] +} + +func (m *sequencedMultiHandlerTransport) popHandler(key string) http.HandlerFunc { + queue, ok := m.handlers[key] + if !ok || len(queue) == 0 { + return nil + } + h := queue[0] + queue = queue[1:] + if len(queue) == 0 { + delete(m.handlers, key) + return h + } + m.handlers[key] = queue + return h +} + func (m *multiHandlerTransport) RoundTrip(req *http.Request) (*http.Response, error) { // Check for catch-all handler if handler, ok := m.handlers[""]; ok { diff --git a/pkg/github/projects_test.go b/pkg/github/projects_test.go index e443b9ecd..f7ad5ea6d 100644 --- a/pkg/github/projects_test.go +++ b/pkg/github/projects_test.go @@ -11,7 +11,6 @@ import ( "github.com/github/github-mcp-server/pkg/translations" gh "github.com/google/go-github/v79/github" "github.com/google/jsonschema-go/jsonschema" - "github.com/migueleliasweb/go-github-mock/src/mock" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -45,12 +44,12 @@ func Test_ListProjects(t *testing.T) { }{ { name: "success organization", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{Pattern: "/orgs/{org}/projectsV2", Method: http.MethodGet}, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{Pattern: "/orgs/{org}/projectsV2", Method: http.MethodGet}, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) - _, _ = w.Write(mock.MustMarshal(orgProjects)) + _, _ = w.Write(MustMarshal(orgProjects)) }), ), ), @@ -63,12 +62,12 @@ func Test_ListProjects(t *testing.T) { }, { name: "success user", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{Pattern: "/users/{username}/projectsV2", Method: http.MethodGet}, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{Pattern: "/users/{username}/projectsV2", Method: http.MethodGet}, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) - _, _ = w.Write(mock.MustMarshal(userProjects)) + _, _ = w.Write(MustMarshal(userProjects)) }), ), ), @@ -81,14 +80,14 @@ func Test_ListProjects(t *testing.T) { }, { name: "success organization with pagination & query", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{Pattern: "/orgs/{org}/projectsV2", Method: http.MethodGet}, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{Pattern: "/orgs/{org}/projectsV2", Method: http.MethodGet}, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { q := r.URL.Query() if q.Get("per_page") == "50" && q.Get("q") == "roadmap" { w.WriteHeader(http.StatusOK) - _, _ = w.Write(mock.MustMarshal(orgProjects)) + _, _ = w.Write(MustMarshal(orgProjects)) return } w.WriteHeader(http.StatusBadRequest) @@ -107,9 +106,9 @@ func Test_ListProjects(t *testing.T) { }, { name: "api error", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{Pattern: "/orgs/{org}/projectsV2", Method: http.MethodGet}, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{Pattern: "/orgs/{org}/projectsV2", Method: http.MethodGet}, mockResponse(t, http.StatusInternalServerError, map[string]string{"message": "boom"}), ), ), @@ -122,7 +121,7 @@ func Test_ListProjects(t *testing.T) { }, { name: "missing owner", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]interface{}{ "owner_type": "org", }, @@ -130,7 +129,7 @@ func Test_ListProjects(t *testing.T) { }, { name: "missing owner_type", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]interface{}{ "owner": "octo-org", }, @@ -204,9 +203,9 @@ func Test_GetProject(t *testing.T) { }{ { name: "success organization project fetch", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{Pattern: "/orgs/{org}/projectsV2/123", Method: http.MethodGet}, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{Pattern: "/orgs/{org}/projectsV2/123", Method: http.MethodGet}, mockResponse(t, http.StatusOK, project), ), ), @@ -219,9 +218,9 @@ func Test_GetProject(t *testing.T) { }, { name: "success user project fetch", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{Pattern: "/users/{username}/projectsV2/456", Method: http.MethodGet}, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{Pattern: "/users/{username}/projectsV2/456", Method: http.MethodGet}, mockResponse(t, http.StatusOK, project), ), ), @@ -234,9 +233,9 @@ func Test_GetProject(t *testing.T) { }, { name: "api error", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{Pattern: "/orgs/{org}/projectsV2/999", Method: http.MethodGet}, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{Pattern: "/orgs/{org}/projectsV2/999", Method: http.MethodGet}, mockResponse(t, http.StatusInternalServerError, map[string]string{"message": "boom"}), ), ), @@ -250,7 +249,7 @@ func Test_GetProject(t *testing.T) { }, { name: "missing project_number", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]interface{}{ "owner": "octo-org", "owner_type": "org", @@ -259,7 +258,7 @@ func Test_GetProject(t *testing.T) { }, { name: "missing owner", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]interface{}{ "project_number": float64(123), "owner_type": "org", @@ -268,7 +267,7 @@ func Test_GetProject(t *testing.T) { }, { name: "missing owner_type", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]interface{}{ "project_number": float64(123), "owner": "octo-org", @@ -343,12 +342,12 @@ func Test_ListProjectFields(t *testing.T) { }{ { name: "success organization fields", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{Pattern: "/orgs/{org}/projectsV2/{project}/fields", Method: http.MethodGet}, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{Pattern: "/orgs/{org}/projectsV2/{project}/fields", Method: http.MethodGet}, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) - _, _ = w.Write(mock.MustMarshal(orgFields)) + _, _ = w.Write(MustMarshal(orgFields)) }), ), ), @@ -361,14 +360,14 @@ func Test_ListProjectFields(t *testing.T) { }, { name: "success user fields with per_page override", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{Pattern: "/users/{user}/projectsV2/{project}/fields", Method: http.MethodGet}, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{Pattern: "/users/{user}/projectsV2/{project}/fields", Method: http.MethodGet}, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { q := r.URL.Query() if q.Get("per_page") == "50" { w.WriteHeader(http.StatusOK) - _, _ = w.Write(mock.MustMarshal(userFields)) + _, _ = w.Write(MustMarshal(userFields)) return } w.WriteHeader(http.StatusBadRequest) @@ -386,9 +385,9 @@ func Test_ListProjectFields(t *testing.T) { }, { name: "api error", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{Pattern: "/orgs/{org}/projectsV2/{project}/fields", Method: http.MethodGet}, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{Pattern: "/orgs/{org}/projectsV2/{project}/fields", Method: http.MethodGet}, mockResponse(t, http.StatusInternalServerError, map[string]string{"message": "boom"}), ), ), @@ -402,7 +401,7 @@ func Test_ListProjectFields(t *testing.T) { }, { name: "missing owner", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]interface{}{ "owner_type": "org", "project_number": 10, @@ -411,7 +410,7 @@ func Test_ListProjectFields(t *testing.T) { }, { name: "missing owner_type", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]interface{}{ "owner": "octo-org", "project_number": 10, @@ -420,7 +419,7 @@ func Test_ListProjectFields(t *testing.T) { }, { name: "missing project_number", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]interface{}{ "owner": "octo-org", "owner_type": "org", @@ -500,9 +499,9 @@ func Test_GetProjectField(t *testing.T) { }{ { name: "success organization field", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{Pattern: "/orgs/{org}/projectsV2/{project}/fields/{field_id}", Method: http.MethodGet}, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{Pattern: "/orgs/{org}/projectsV2/{project}/fields/{field_id}", Method: http.MethodGet}, mockResponse(t, http.StatusOK, orgField), ), ), @@ -516,9 +515,9 @@ func Test_GetProjectField(t *testing.T) { }, { name: "success user field", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{Pattern: "/users/{user}/projectsV2/{project}/fields/{field_id}", Method: http.MethodGet}, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{Pattern: "/users/{user}/projectsV2/{project}/fields/{field_id}", Method: http.MethodGet}, mockResponse(t, http.StatusOK, userField), ), ), @@ -532,9 +531,9 @@ func Test_GetProjectField(t *testing.T) { }, { name: "api error", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{Pattern: "/orgs/{org}/projectsV2/{project}/fields/{field_id}", Method: http.MethodGet}, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{Pattern: "/orgs/{org}/projectsV2/{project}/fields/{field_id}", Method: http.MethodGet}, mockResponse(t, http.StatusInternalServerError, map[string]string{"message": "boom"}), ), ), @@ -549,7 +548,7 @@ func Test_GetProjectField(t *testing.T) { }, { name: "missing owner", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]any{ "owner_type": "org", "project_number": float64(10), @@ -559,7 +558,7 @@ func Test_GetProjectField(t *testing.T) { }, { name: "missing owner_type", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]any{ "owner": "octo-org", "project_number": float64(10), @@ -569,7 +568,7 @@ func Test_GetProjectField(t *testing.T) { }, { name: "missing project_number", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]any{ "owner": "octo-org", "owner_type": "org", @@ -579,7 +578,7 @@ func Test_GetProjectField(t *testing.T) { }, { name: "missing field_id", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]any{ "owner": "octo-org", "owner_type": "org", @@ -671,9 +670,9 @@ func Test_ListProjectItems(t *testing.T) { }{ { name: "success organization items", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{Pattern: "/orgs/{org}/projectsV2/{project}/items", Method: http.MethodGet}, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{Pattern: "/orgs/{org}/projectsV2/{project}/items", Method: http.MethodGet}, mockResponse(t, http.StatusOK, orgItems), ), ), @@ -686,14 +685,14 @@ func Test_ListProjectItems(t *testing.T) { }, { name: "success organization items with fields", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{Pattern: "/orgs/{org}/projectsV2/{project}/items", Method: http.MethodGet}, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{Pattern: "/orgs/{org}/projectsV2/{project}/items", Method: http.MethodGet}, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { q := r.URL.Query() if q.Get("fields") == "123,456,789" { w.WriteHeader(http.StatusOK) - _, _ = w.Write(mock.MustMarshal(orgItems)) + _, _ = w.Write(MustMarshal(orgItems)) return } w.WriteHeader(http.StatusBadRequest) @@ -711,9 +710,9 @@ func Test_ListProjectItems(t *testing.T) { }, { name: "success user items", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{Pattern: "/users/{user}/projectsV2/{project}/items", Method: http.MethodGet}, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{Pattern: "/users/{user}/projectsV2/{project}/items", Method: http.MethodGet}, mockResponse(t, http.StatusOK, userItems), ), ), @@ -726,14 +725,14 @@ func Test_ListProjectItems(t *testing.T) { }, { name: "success with pagination and query", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{Pattern: "/orgs/{org}/projectsV2/{project}/items", Method: http.MethodGet}, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{Pattern: "/orgs/{org}/projectsV2/{project}/items", Method: http.MethodGet}, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { q := r.URL.Query() if q.Get("per_page") == "50" && q.Get("q") == "bug" { w.WriteHeader(http.StatusOK) - _, _ = w.Write(mock.MustMarshal(orgItems)) + _, _ = w.Write(MustMarshal(orgItems)) return } w.WriteHeader(http.StatusBadRequest) @@ -752,9 +751,9 @@ func Test_ListProjectItems(t *testing.T) { }, { name: "api error", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{Pattern: "/orgs/{org}/projectsV2/{project}/items", Method: http.MethodGet}, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{Pattern: "/orgs/{org}/projectsV2/{project}/items", Method: http.MethodGet}, mockResponse(t, http.StatusInternalServerError, map[string]string{"message": "boom"}), ), ), @@ -768,7 +767,7 @@ func Test_ListProjectItems(t *testing.T) { }, { name: "missing owner", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]interface{}{ "owner_type": "org", "project_number": float64(10), @@ -777,7 +776,7 @@ func Test_ListProjectItems(t *testing.T) { }, { name: "missing owner_type", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]interface{}{ "owner": "octo-org", "project_number": float64(10), @@ -786,7 +785,7 @@ func Test_ListProjectItems(t *testing.T) { }, { name: "missing project_number", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]interface{}{ "owner": "octo-org", "owner_type": "org", @@ -877,9 +876,9 @@ func Test_GetProjectItem(t *testing.T) { }{ { name: "success organization item", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{Pattern: "/orgs/{org}/projectsV2/{project}/items/{item_id}", Method: http.MethodGet}, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{Pattern: "/orgs/{org}/projectsV2/{project}/items/{item_id}", Method: http.MethodGet}, mockResponse(t, http.StatusOK, orgItem), ), ), @@ -893,14 +892,14 @@ func Test_GetProjectItem(t *testing.T) { }, { name: "success organization item with fields", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{Pattern: "/orgs/{org}/projectsV2/{project}/items/{item_id}", Method: http.MethodGet}, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{Pattern: "/orgs/{org}/projectsV2/{project}/items/{item_id}", Method: http.MethodGet}, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { q := r.URL.Query() if q.Get("fields") == "123,456" { w.WriteHeader(http.StatusOK) - _, _ = w.Write(mock.MustMarshal(orgItem)) + _, _ = w.Write(MustMarshal(orgItem)) return } w.WriteHeader(http.StatusBadRequest) @@ -919,9 +918,9 @@ func Test_GetProjectItem(t *testing.T) { }, { name: "success user item", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{Pattern: "/users/{user}/projectsV2/{project}/items/{item_id}", Method: http.MethodGet}, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{Pattern: "/users/{user}/projectsV2/{project}/items/{item_id}", Method: http.MethodGet}, mockResponse(t, http.StatusOK, userItem), ), ), @@ -935,9 +934,9 @@ func Test_GetProjectItem(t *testing.T) { }, { name: "api error", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{Pattern: "/orgs/{org}/projectsV2/{project}/items/{item_id}", Method: http.MethodGet}, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{Pattern: "/orgs/{org}/projectsV2/{project}/items/{item_id}", Method: http.MethodGet}, mockResponse(t, http.StatusInternalServerError, map[string]string{"message": "boom"}), ), ), @@ -952,7 +951,7 @@ func Test_GetProjectItem(t *testing.T) { }, { name: "missing owner", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]any{ "owner_type": "org", "project_number": float64(10), @@ -962,7 +961,7 @@ func Test_GetProjectItem(t *testing.T) { }, { name: "missing owner_type", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]any{ "owner": "octo-org", "project_number": float64(10), @@ -972,7 +971,7 @@ func Test_GetProjectItem(t *testing.T) { }, { name: "missing project_number", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]any{ "owner": "octo-org", "owner_type": "org", @@ -982,7 +981,7 @@ func Test_GetProjectItem(t *testing.T) { }, { name: "missing item_id", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]any{ "owner": "octo-org", "owner_type": "org", @@ -1086,9 +1085,9 @@ func Test_AddProjectItem(t *testing.T) { }{ { name: "success organization issue", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{Pattern: "/orgs/{org}/projectsV2/{project}/items", Method: http.MethodPost}, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{Pattern: "/orgs/{org}/projectsV2/{project}/items", Method: http.MethodPost}, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { body, err := io.ReadAll(r.Body) assert.NoError(t, err) @@ -1100,7 +1099,7 @@ func Test_AddProjectItem(t *testing.T) { assert.Equal(t, "Issue", payload.Type) assert.Equal(t, 9876, payload.ID) w.WriteHeader(http.StatusCreated) - _, _ = w.Write(mock.MustMarshal(orgItem)) + _, _ = w.Write(MustMarshal(orgItem)) }), ), ), @@ -1117,9 +1116,9 @@ func Test_AddProjectItem(t *testing.T) { }, { name: "success user pull request", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{Pattern: "/users/{user}/projectsV2/{project}/items", Method: http.MethodPost}, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{Pattern: "/users/{user}/projectsV2/{project}/items", Method: http.MethodPost}, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { body, err := io.ReadAll(r.Body) assert.NoError(t, err) @@ -1131,7 +1130,7 @@ func Test_AddProjectItem(t *testing.T) { assert.Equal(t, "PullRequest", payload.Type) assert.Equal(t, 7654, payload.ID) w.WriteHeader(http.StatusCreated) - _, _ = w.Write(mock.MustMarshal(userItem)) + _, _ = w.Write(MustMarshal(userItem)) }), ), ), @@ -1148,9 +1147,9 @@ func Test_AddProjectItem(t *testing.T) { }, { name: "api error", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{Pattern: "/orgs/{org}/projectsV2/{project}/items", Method: http.MethodPost}, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{Pattern: "/orgs/{org}/projectsV2/{project}/items", Method: http.MethodPost}, mockResponse(t, http.StatusInternalServerError, map[string]string{"message": "boom"}), ), ), @@ -1166,7 +1165,7 @@ func Test_AddProjectItem(t *testing.T) { }, { name: "missing owner", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]any{ "owner_type": "org", "project_number": float64(1), @@ -1177,7 +1176,7 @@ func Test_AddProjectItem(t *testing.T) { }, { name: "missing owner_type", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]any{ "owner": "octo-org", "project_number": float64(1), @@ -1188,7 +1187,7 @@ func Test_AddProjectItem(t *testing.T) { }, { name: "missing project_number", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]any{ "owner": "octo-org", "owner_type": "org", @@ -1199,7 +1198,7 @@ func Test_AddProjectItem(t *testing.T) { }, { name: "missing item_type", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]any{ "owner": "octo-org", "owner_type": "org", @@ -1210,7 +1209,7 @@ func Test_AddProjectItem(t *testing.T) { }, { name: "missing item_id", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]any{ "owner": "octo-org", "owner_type": "org", @@ -1310,9 +1309,9 @@ func Test_UpdateProjectItem(t *testing.T) { }{ { name: "success organization update", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{Pattern: "/orgs/{org}/projectsV2/{project}/items/{item_id}", Method: http.MethodPatch}, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{Pattern: "/orgs/{org}/projectsV2/{project}/items/{item_id}", Method: http.MethodPatch}, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { body, err := io.ReadAll(r.Body) assert.NoError(t, err) @@ -1327,7 +1326,7 @@ func Test_UpdateProjectItem(t *testing.T) { assert.Equal(t, 101, payload.Fields[0].ID) assert.Equal(t, "Done", payload.Fields[0].Value) w.WriteHeader(http.StatusOK) - _, _ = w.Write(mock.MustMarshal(orgUpdatedItem)) + _, _ = w.Write(MustMarshal(orgUpdatedItem)) }), ), ), @@ -1345,9 +1344,9 @@ func Test_UpdateProjectItem(t *testing.T) { }, { name: "success user update", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{Pattern: "/users/{user}/projectsV2/{project}/items/{item_id}", Method: http.MethodPatch}, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{Pattern: "/users/{user}/projectsV2/{project}/items/{item_id}", Method: http.MethodPatch}, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { body, err := io.ReadAll(r.Body) assert.NoError(t, err) @@ -1362,7 +1361,7 @@ func Test_UpdateProjectItem(t *testing.T) { assert.Equal(t, 202, payload.Fields[0].ID) assert.Equal(t, 42.0, payload.Fields[0].Value) w.WriteHeader(http.StatusOK) - _, _ = w.Write(mock.MustMarshal(userUpdatedItem)) + _, _ = w.Write(MustMarshal(userUpdatedItem)) }), ), ), @@ -1380,9 +1379,9 @@ func Test_UpdateProjectItem(t *testing.T) { }, { name: "api error", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{Pattern: "/orgs/{org}/projectsV2/{project}/items/{item_id}", Method: http.MethodPatch}, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{Pattern: "/orgs/{org}/projectsV2/{project}/items/{item_id}", Method: http.MethodPatch}, mockResponse(t, http.StatusInternalServerError, map[string]string{"message": "boom"}), ), ), @@ -1401,7 +1400,7 @@ func Test_UpdateProjectItem(t *testing.T) { }, { name: "missing owner", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]any{ "owner_type": "org", "project_number": float64(1), @@ -1415,7 +1414,7 @@ func Test_UpdateProjectItem(t *testing.T) { }, { name: "missing owner_type", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]any{ "owner": "octo-org", "project_number": float64(1), @@ -1429,7 +1428,7 @@ func Test_UpdateProjectItem(t *testing.T) { }, { name: "missing project_number", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]any{ "owner": "octo-org", "owner_type": "org", @@ -1443,7 +1442,7 @@ func Test_UpdateProjectItem(t *testing.T) { }, { name: "missing item_id", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]any{ "owner": "octo-org", "owner_type": "org", @@ -1457,7 +1456,7 @@ func Test_UpdateProjectItem(t *testing.T) { }, { name: "missing updated_field", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]any{ "owner": "octo-org", "owner_type": "org", @@ -1468,7 +1467,7 @@ func Test_UpdateProjectItem(t *testing.T) { }, { name: "updated_field not object", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]any{ "owner": "octo-org", "owner_type": "org", @@ -1480,7 +1479,7 @@ func Test_UpdateProjectItem(t *testing.T) { }, { name: "updated_field missing id", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]any{ "owner": "octo-org", "owner_type": "org", @@ -1492,7 +1491,7 @@ func Test_UpdateProjectItem(t *testing.T) { }, { name: "updated_field missing value", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]any{ "owner": "octo-org", "owner_type": "org", @@ -1580,9 +1579,9 @@ func Test_DeleteProjectItem(t *testing.T) { }{ { name: "success organization delete", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{Pattern: "/orgs/{org}/projectsV2/{project}/items/{item_id}", Method: http.MethodDelete}, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{Pattern: "/orgs/{org}/projectsV2/{project}/items/{item_id}", Method: http.MethodDelete}, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNoContent) }), @@ -1598,9 +1597,9 @@ func Test_DeleteProjectItem(t *testing.T) { }, { name: "success user delete", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{Pattern: "/users/{user}/projectsV2/{project}/items/{item_id}", Method: http.MethodDelete}, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{Pattern: "/users/{user}/projectsV2/{project}/items/{item_id}", Method: http.MethodDelete}, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNoContent) }), @@ -1616,9 +1615,9 @@ func Test_DeleteProjectItem(t *testing.T) { }, { name: "api error", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.EndpointPattern{Pattern: "/orgs/{org}/projectsV2/{project}/items/{item_id}", Method: http.MethodDelete}, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + EndpointPattern{Pattern: "/orgs/{org}/projectsV2/{project}/items/{item_id}", Method: http.MethodDelete}, mockResponse(t, http.StatusInternalServerError, map[string]string{"message": "boom"}), ), ), @@ -1633,7 +1632,7 @@ func Test_DeleteProjectItem(t *testing.T) { }, { name: "missing owner", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]any{ "owner_type": "org", "project_number": float64(1), @@ -1643,7 +1642,7 @@ func Test_DeleteProjectItem(t *testing.T) { }, { name: "missing owner_type", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]any{ "owner": "octo-org", "project_number": float64(1), @@ -1653,7 +1652,7 @@ func Test_DeleteProjectItem(t *testing.T) { }, { name: "missing project_number", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]any{ "owner": "octo-org", "owner_type": "org", @@ -1663,7 +1662,7 @@ func Test_DeleteProjectItem(t *testing.T) { }, { name: "missing item_id", - mockedClient: mock.NewMockedHTTPClient(), + mockedClient: NewMockedHTTPClient(), requestArgs: map[string]any{ "owner": "octo-org", "owner_type": "org", diff --git a/pkg/github/search_test.go b/pkg/github/search_test.go index be1b26714..9cc454072 100644 --- a/pkg/github/search_test.go +++ b/pkg/github/search_test.go @@ -10,7 +10,6 @@ import ( "github.com/github/github-mcp-server/pkg/translations" "github.com/google/go-github/v79/github" "github.com/google/jsonschema-go/jsonschema" - "github.com/migueleliasweb/go-github-mock/src/mock" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -67,9 +66,9 @@ func Test_SearchRepositories(t *testing.T) { }{ { name: "successful repository search", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.GetSearchRepositories, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + GetSearchRepositories, expectQueryParams(t, map[string]string{ "q": "golang test", "sort": "stars", @@ -93,9 +92,9 @@ func Test_SearchRepositories(t *testing.T) { }, { name: "repository search with default pagination", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.GetSearchRepositories, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + GetSearchRepositories, expectQueryParams(t, map[string]string{ "q": "golang test", "page": "1", @@ -113,9 +112,9 @@ func Test_SearchRepositories(t *testing.T) { }, { name: "search fails", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.GetSearchRepositories, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + GetSearchRepositories, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusBadRequest) _, _ = w.Write([]byte(`{"message": "Invalid query"}`)) @@ -123,7 +122,7 @@ func Test_SearchRepositories(t *testing.T) { ), ), requestArgs: map[string]interface{}{ - "query": "invalid:query", + "query": "invalid query", }, expectError: true, expectedErrMsg: "failed to search repositories", @@ -194,9 +193,9 @@ func Test_SearchRepositories_FullOutput(t *testing.T) { }, } - mockedClient := mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.GetSearchRepositories, + mockedClient := NewMockedHTTPClient( + WithRequestMatchHandler( + GetSearchRepositories, expectQueryParams(t, map[string]string{ "q": "golang test", "page": "1", @@ -291,9 +290,9 @@ func Test_SearchCode(t *testing.T) { }{ { name: "successful code search with all parameters", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.GetSearchCode, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + GetSearchCode, expectQueryParams(t, map[string]string{ "q": "fmt.Println language:go", "sort": "indexed", @@ -317,9 +316,9 @@ func Test_SearchCode(t *testing.T) { }, { name: "code search with minimal parameters", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.GetSearchCode, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + GetSearchCode, expectQueryParams(t, map[string]string{ "q": "fmt.Println language:go", "page": "1", @@ -337,9 +336,9 @@ func Test_SearchCode(t *testing.T) { }, { name: "search code fails", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.GetSearchCode, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + GetSearchCode, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusBadRequest) _, _ = w.Write([]byte(`{"message": "Validation Failed"}`)) @@ -451,9 +450,9 @@ func Test_SearchUsers(t *testing.T) { }{ { name: "successful users search with all parameters", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.GetSearchUsers, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + GetSearchUsers, expectQueryParams(t, map[string]string{ "q": "type:user location:finland language:go", "sort": "followers", @@ -477,9 +476,9 @@ func Test_SearchUsers(t *testing.T) { }, { name: "users search with minimal parameters", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.GetSearchUsers, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + GetSearchUsers, expectQueryParams(t, map[string]string{ "q": "type:user location:finland language:go", "page": "1", @@ -497,9 +496,9 @@ func Test_SearchUsers(t *testing.T) { }, { name: "query with existing type:user filter - no duplication", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.GetSearchUsers, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + GetSearchUsers, expectQueryParams(t, map[string]string{ "q": "type:user location:seattle followers:>100", "page": "1", @@ -517,9 +516,9 @@ func Test_SearchUsers(t *testing.T) { }, { name: "complex query with existing type:user filter and OR operators", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.GetSearchUsers, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + GetSearchUsers, expectQueryParams(t, map[string]string{ "q": "type:user (location:seattle OR location:california) followers:>50", "page": "1", @@ -537,9 +536,9 @@ func Test_SearchUsers(t *testing.T) { }, { name: "search users fails", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.GetSearchUsers, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + GetSearchUsers, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusBadRequest) _, _ = w.Write([]byte(`{"message": "Validation Failed"}`)) @@ -652,9 +651,9 @@ func Test_SearchOrgs(t *testing.T) { }{ { name: "successful org search", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.GetSearchUsers, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + GetSearchUsers, expectQueryParams(t, map[string]string{ "q": "type:org github", "page": "1", @@ -672,9 +671,9 @@ func Test_SearchOrgs(t *testing.T) { }, { name: "query with existing type:org filter - no duplication", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.GetSearchUsers, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + GetSearchUsers, expectQueryParams(t, map[string]string{ "q": "type:org location:california followers:>1000", "page": "1", @@ -692,9 +691,9 @@ func Test_SearchOrgs(t *testing.T) { }, { name: "complex query with existing type:org filter and OR operators", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.GetSearchUsers, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + GetSearchUsers, expectQueryParams(t, map[string]string{ "q": "type:org (location:seattle OR location:california OR location:newyork) repos:>10", "page": "1", @@ -712,9 +711,9 @@ func Test_SearchOrgs(t *testing.T) { }, { name: "org search fails", - mockedClient: mock.NewMockedHTTPClient( - mock.WithRequestMatchHandler( - mock.GetSearchUsers, + mockedClient: NewMockedHTTPClient( + WithRequestMatchHandler( + GetSearchUsers, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusBadRequest) _, _ = w.Write([]byte(`{"message": "Validation Failed"}`))