@@ -18,15 +18,120 @@ import (
1818// GitHub API endpoint patterns for testing
1919// These constants define the URL patterns used in HTTP mocking for tests
2020const (
21+ // User endpoints
22+ GetUser = "GET /user"
23+ GetUserStarred = "GET /user/starred"
24+ GetUsersGistsByUsername = "GET /users/{username}/gists"
25+ GetUsersStarredByUsername = "GET /users/{username}/starred"
26+ PutUserStarredByOwnerByRepo = "PUT /user/starred/{owner}/{repo}"
27+ DeleteUserStarredByOwnerByRepo = "DELETE /user/starred/{owner}/{repo}"
28+
2129 // Repository endpoints
22- GetReposByOwnerByRepo = "GET /repos/{owner}/{repo}"
30+ GetReposByOwnerByRepo = "GET /repos/{owner}/{repo}"
31+ GetReposBranchesByOwnerByRepo = "GET /repos/{owner}/{repo}/branches"
32+ GetReposTagsByOwnerByRepo = "GET /repos/{owner}/{repo}/tags"
33+ GetReposCommitsByOwnerByRepo = "GET /repos/{owner}/{repo}/commits"
34+ GetReposCommitsByOwnerByRepoByRef = "GET /repos/{owner}/{repo}/commits/{ref}"
35+ GetReposContentsByOwnerByRepoByPath = "GET /repos/{owner}/{repo}/contents/{path}"
36+ PutReposContentsByOwnerByRepoByPath = "PUT /repos/{owner}/{repo}/contents/{path}"
37+ PostReposForksByOwnerByRepo = "POST /repos/{owner}/{repo}/forks"
38+ GetReposSubscriptionByOwnerByRepo = "GET /repos/{owner}/{repo}/subscription"
39+ PutReposSubscriptionByOwnerByRepo = "PUT /repos/{owner}/{repo}/subscription"
40+ DeleteReposSubscriptionByOwnerByRepo = "DELETE /repos/{owner}/{repo}/subscription"
2341
2442 // Git endpoints
25- GetReposGitTreesByOwnerByRepoByTree = "GET /repos/{owner}/{repo}/git/trees/{tree}"
43+ GetReposGitTreesByOwnerByRepoByTree = "GET /repos/{owner}/{repo}/git/trees/{tree}"
44+ GetReposGitRefByOwnerByRepoByRef = "GET /repos/{owner}/{repo}/git/ref/{ref}"
45+ PostReposGitRefsByOwnerByRepo = "POST /repos/{owner}/{repo}/git/refs"
46+ PatchReposGitRefsByOwnerByRepoByRef = "PATCH /repos/{owner}/{repo}/git/refs/{ref}"
47+ GetReposGitCommitsByOwnerByRepoByCommitSha = "GET /repos/{owner}/{repo}/git/commits/{commit_sha}"
48+ PostReposGitCommitsByOwnerByRepo = "POST /repos/{owner}/{repo}/git/commits"
49+ GetReposGitTagsByOwnerByRepoByTagSha = "GET /repos/{owner}/{repo}/git/tags/{tag_sha}"
50+ PostReposGitTreesByOwnerByRepo = "POST /repos/{owner}/{repo}/git/trees"
51+ GetReposCommitsStatusByOwnerByRepoByRef = "GET /repos/{owner}/{repo}/commits/{ref}/status"
52+ GetReposCommitsStatusesByOwnerByRepoByRef = "GET /repos/{owner}/{repo}/commits/{ref}/statuses"
53+
54+ // Issues endpoints
55+ GetReposIssuesByOwnerByRepoByIssueNumber = "GET /repos/{owner}/{repo}/issues/{issue_number}"
56+ GetReposIssuesCommentsByOwnerByRepoByIssueNumber = "GET /repos/{owner}/{repo}/issues/{issue_number}/comments"
57+ PostReposIssuesByOwnerByRepo = "POST /repos/{owner}/{repo}/issues"
58+ PostReposIssuesCommentsByOwnerByRepoByIssueNumber = "POST /repos/{owner}/{repo}/issues/{issue_number}/comments"
59+ PatchReposIssuesByOwnerByRepoByIssueNumber = "PATCH /repos/{owner}/{repo}/issues/{issue_number}"
60+ GetReposIssuesSubIssuesByOwnerByRepoByIssueNumber = "GET /repos/{owner}/{repo}/issues/{issue_number}/sub_issues"
61+ PostReposIssuesSubIssuesByOwnerByRepoByIssueNumber = "POST /repos/{owner}/{repo}/issues/{issue_number}/sub_issues"
62+ DeleteReposIssuesSubIssueByOwnerByRepoByIssueNumber = "DELETE /repos/{owner}/{repo}/issues/{issue_number}/sub_issues"
63+ PatchReposIssuesSubIssuesPriorityByOwnerByRepoByIssueNumber = "PATCH /repos/{owner}/{repo}/issues/{issue_number}/sub_issues/priority"
64+
65+ // Pull request endpoints
66+ GetReposPullsByOwnerByRepo = "GET /repos/{owner}/{repo}/pulls"
67+ GetReposPullsByOwnerByRepoByPullNumber = "GET /repos/{owner}/{repo}/pulls/{pull_number}"
68+ GetReposPullsFilesByOwnerByRepoByPullNumber = "GET /repos/{owner}/{repo}/pulls/{pull_number}/files"
69+ GetReposPullsReviewsByOwnerByRepoByPullNumber = "GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews"
70+ PostReposPullsByOwnerByRepo = "POST /repos/{owner}/{repo}/pulls"
71+ PatchReposPullsByOwnerByRepoByPullNumber = "PATCH /repos/{owner}/{repo}/pulls/{pull_number}"
72+ PutReposPullsMergeByOwnerByRepoByPullNumber = "PUT /repos/{owner}/{repo}/pulls/{pull_number}/merge"
73+ PutReposPullsUpdateBranchByOwnerByRepoByPullNumber = "PUT /repos/{owner}/{repo}/pulls/{pull_number}/update-branch"
74+ PostReposPullsRequestedReviewersByOwnerByRepoByPullNumber = "POST /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers"
75+
76+ // Notifications endpoints
77+ GetNotifications = "GET /notifications"
78+ PutNotifications = "PUT /notifications"
79+ GetReposNotificationsByOwnerByRepo = "GET /repos/{owner}/{repo}/notifications"
80+ PutReposNotificationsByOwnerByRepo = "PUT /repos/{owner}/{repo}/notifications"
81+ GetNotificationsThreadsByThreadId = "GET /notifications/threads/{thread_id}"
82+ PatchNotificationsThreadsByThreadId = "PATCH /notifications/threads/{thread_id}"
83+ DeleteNotificationsThreadsByThreadId = "DELETE /notifications/threads/{thread_id}"
84+ PutNotificationsThreadsSubscriptionByThreadId = "PUT /notifications/threads/{thread_id}/subscription"
85+ DeleteNotificationsThreadsSubscriptionByThreadId = "DELETE /notifications/threads/{thread_id}/subscription"
86+
87+ // Gists endpoints
88+ GetGists = "GET /gists"
89+ GetGistsByGistId = "GET /gists/{gist_id}"
90+ PostGists = "POST /gists"
91+ PatchGistsByGistId = "PATCH /gists/{gist_id}"
92+
93+ // Releases endpoints
94+ GetReposReleasesByOwnerByRepo = "GET /repos/{owner}/{repo}/releases"
95+ GetReposReleasesLatestByOwnerByRepo = "GET /repos/{owner}/{repo}/releases/latest"
96+ GetReposReleasesTagsByOwnerByRepoByTag = "GET /repos/{owner}/{repo}/releases/tags/{tag}"
2697
2798 // Code scanning endpoints
2899 GetReposCodeScanningAlertsByOwnerByRepo = "GET /repos/{owner}/{repo}/code-scanning/alerts"
29100 GetReposCodeScanningAlertsByOwnerByRepoByAlertNumber = "GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}"
101+
102+ // Secret scanning endpoints
103+ GetReposSecretScanningAlertsByOwnerByRepo = "GET /repos/{owner}/{repo}/secret-scanning/alerts"
104+ GetReposSecretScanningAlertsByOwnerByRepoByAlertNumber = "GET /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}"
105+
106+ // Dependabot endpoints
107+ GetReposDependabotAlertsByOwnerByRepo = "GET /repos/{owner}/{repo}/dependabot/alerts"
108+ GetReposDependabotAlertsByOwnerByRepoByAlertNumber = "GET /repos/{owner}/{repo}/dependabot/alerts/{alert_number}"
109+
110+ // Security advisories endpoints
111+ GetAdvisories = "GET /advisories"
112+ GetAdvisoriesByGhsaId = "GET /advisories/{ghsa_id}"
113+
114+ // Actions endpoints
115+ GetReposActionsWorkflowsByOwnerByRepo = "GET /repos/{owner}/{repo}/actions/workflows"
116+ PostReposActionsWorkflowsDispatchesByOwnerByRepoByWorkflowId = "POST /repos/{owner}/{repo}/actions/workflows/{workflow_id}/dispatches"
117+ GetReposActionsRunsJobsByOwnerByRepoByRunId = "GET /repos/{owner}/{repo}/actions/runs/{run_id}/jobs"
118+ GetReposActionsRunsArtifactsByOwnerByRepoByRunId = "GET /repos/{owner}/{repo}/actions/runs/{run_id}/artifacts"
119+ GetReposActionsRunsTimingByOwnerByRepoByRunId = "GET /repos/{owner}/{repo}/actions/runs/{run_id}/timing"
120+ GetReposActionsJobsLogsByOwnerByRepoByJobId = "GET /repos/{owner}/{repo}/actions/jobs/{job_id}/logs"
121+ DeleteReposActionsRunsLogsByOwnerByRepoByRunId = "DELETE /repos/{owner}/{repo}/actions/runs/{run_id}/logs"
122+
123+ // Search endpoints
124+ GetSearchCode = "GET /search/code"
125+ GetSearchIssues = "GET /search/issues"
126+ GetSearchRepositories = "GET /search/repositories"
127+ GetSearchUsers = "GET /search/users"
128+
129+ // Raw content endpoints (used for GitHub raw content API, not standard API)
130+ // These are used with the raw content client that interacts with raw.githubusercontent.com
131+ GetRawReposContentsByOwnerByRepoByPath = "GET /{owner}/{repo}/HEAD/{path}"
132+ GetRawReposContentsByOwnerByRepoByBranchByPath = "GET /{owner}/{repo}/refs/heads/{branch}/{path}"
133+ GetRawReposContentsByOwnerByRepoByTagByPath = "GET /{owner}/{repo}/refs/tags/{tag}/{path}"
134+ GetRawReposContentsByOwnerByRepoBySHAByPath = "GET /{owner}/{repo}/{sha}/{path}"
30135)
31136
32137type expectations struct {
@@ -382,6 +487,27 @@ func matchPath(pattern, path string) bool {
382487 patternParts := strings .Split (strings .Trim (pattern , "/" ), "/" )
383488 pathParts := strings .Split (strings .Trim (path , "/" ), "/" )
384489
490+ // Handle patterns with wildcard path like {path:.*}
491+ if len (patternParts ) > 0 {
492+ lastPart := patternParts [len (patternParts )- 1 ]
493+ if strings .HasPrefix (lastPart , "{" ) && strings .Contains (lastPart , ":" ) && strings .HasSuffix (lastPart , "}" ) {
494+ // This is a wildcard pattern like {path:.*}
495+ // Check if all parts before the wildcard match
496+ if len (pathParts ) < len (patternParts )- 1 {
497+ return false
498+ }
499+ for i := 0 ; i < len (patternParts )- 1 ; i ++ {
500+ if strings .HasPrefix (patternParts [i ], "{" ) && strings .HasSuffix (patternParts [i ], "}" ) {
501+ continue // Path parameter matches anything
502+ }
503+ if patternParts [i ] != pathParts [i ] {
504+ return false
505+ }
506+ }
507+ return true
508+ }
509+ }
510+
385511 if len (patternParts ) != len (pathParts ) {
386512 return false
387513 }
0 commit comments