diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index a366c2b7..3aa19874 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -4,6 +4,14 @@ **Completed: 8/14 files (57%)** +**Next Priority Files:** +1. notifications_test.go (801 lines) - **Easiest** - only 4 simple WithRequestMatch patterns +2. search_test.go (776 lines) - 16 WithRequestMatchHandler (all with expectQueryParams) +3. projects_test.go (1,711 lines) - 31 WithRequestMatchHandler +4. pullrequests_test.go (3,355 lines) - Mixed patterns +5. repositories_test.go (3,532 lines) - Mixed patterns +6. issues_test.go (3,755 lines) - **Largest** - mixed patterns + ### ✅ Migrated Files 1. pkg/raw/raw_test.go 2. pkg/github/actions_test.go (1,428 lines) @@ -110,6 +118,40 @@ Replace old mock constants with new ones (note ID vs Id): All endpoint constants are defined in `pkg/github/helper_test.go`. +## Special Cases + +### Case 1: With expectQueryParams and andThen + +When the handler uses `expectQueryParams(...).andThen(...)`, the structure must be carefully closed: + +```go +// CORRECT: +MockHTTPClientWithHandlers(map[string]http.HandlerFunc{ + GetSearchRepositories: expectQueryParams(t, map[string]string{ + "q": "test", + }).andThen( + mockResponse(t, http.StatusOK, data), + ), // <- Close andThen with ), +}), // <- Close map with }), + +// INCORRECT (missing map close): +MockHTTPClientWithHandlers(map[string]http.HandlerFunc{ + GetSearchRepositories: expectQueryParams(t, map[string]string{ + "q": "test", + }).andThen( + mockResponse(t, http.StatusOK, data), + ), // <- Only closes andThen, missing }), +``` + +### Case 2: Multiple Endpoints in One Mock + +```go +MockHTTPClientWithHandlers(map[string]http.HandlerFunc{ + GetReposPullsByOwnerByRepoByPullNumber: mockResponse(t, http.StatusOK, mockPR), + GetRawReposContentsByOwnerByRepoBySHAByPath: mockResponse(t, http.StatusOK, mockContent), +}), +``` + ## Common Issues and Solutions ### Issue 1: Extra Closing Braces diff --git a/complete_migration.sh b/complete_migration.sh new file mode 100755 index 00000000..39c3aca8 --- /dev/null +++ b/complete_migration.sh @@ -0,0 +1,94 @@ +#!/bin/bash +# Script to complete the go-github-mock to testify migration +# Usage: ./complete_migration.sh + +set -e + +echo "=== Completing go-github-mock Migration ===" +echo "" +echo "This script will:" +echo "1. Migrate remaining 6 test files" +echo "2. Remove go-github-mock dependency" +echo "3. Remove raw_mock.go" +echo "4. Run tests and linter" +echo "" + +# Files to migrate +FILES=( + "pkg/github/notifications_test.go" + "pkg/github/search_test.go" + "pkg/github/projects_test.go" + "pkg/github/pullrequests_test.go" + "pkg/github/repositories_test.go" + "pkg/github/issues_test.go" +) + +echo "Files to migrate:" +for f in "${FILES[@]}"; do + lines=$(wc -l < "$f") + echo " - $f ($lines lines)" +done +echo "" + +read -p "Continue with migration? (y/n) " -n 1 -r +echo +if [[ ! $REPLY =~ ^[Yy]$ ]]; then + echo "Migration cancelled" + exit 1 +fi + +# Backup files +echo "Creating backups..." +for f in "${FILES[@]}"; do + cp "$f" "$f.backup" +done + +# Migration function +migrate_file() { + local file=$1 + echo "Migrating $file..." + + # Remove mock import + sed -i '/github\.com\/migueleliasweb\/go-github-mock\/src\/mock/d' "$file" + + # Fix ID naming + sed -i 's/ThreadId/ThreadID/g; s/GistId/GistID/g; s/GhsaId/GhsaID/g' "$file" + sed -i 's/WorkflowId/WorkflowID/g; s/RunId/RunID/g; s/JobId/JobID/g' "$file" + + # Replace empty mocks + sed -i 's/mock\.NewMockedHTTPClient()/MockHTTPClientWithHandlers(map[string]http.HandlerFunc{})/g' "$file" + + echo " Basic patterns applied. Manual review needed for:" + echo " - mock.WithRequestMatch patterns" + echo " - mock.WithRequestMatchHandler patterns" + echo " - Closing braces for maps" +} + +# Migrate each file +for f in "${FILES[@]}"; do + migrate_file "$f" +done + +echo "" +echo "=== Migration Step 1 Complete ===" +echo "" +echo "NEXT STEPS (Manual):" +echo "1. For each file, replace mock.NewMockedHTTPClient patterns:" +echo " - Find: mock.NewMockedHTTPClient(mock.WithRequestMatch(mock.GetX, data),)" +echo " - Replace with: MockHTTPClientWithHandlers(map[string]http.HandlerFunc{GetX: mockResponse(t, http.StatusOK, data),})" +echo "" +echo "2. For mock.WithRequestMatchHandler patterns:" +echo " - Find: mock.NewMockedHTTPClient(mock.WithRequestMatchHandler(mock.GetX, handler),)" +echo " - Replace with: MockHTTPClientWithHandlers(map[string]http.HandlerFunc{GetX: handler,})" +echo "" +echo "3. Test each file: go test ./pkg/github -run TestName -v" +echo "" +echo "4. When all files pass tests:" +echo " - Remove: go.mod entry for migueleliasweb/go-github-mock" +echo " - Remove: pkg/raw/raw_mock.go" +echo " - Run: go mod tidy" +echo " - Run: script/licenses" +echo " - Run: script/test" +echo " - Run: script/lint" +echo "" +echo "Backups saved as *.backup in case you need to revert." diff --git a/pkg/github/gists_test.go b/pkg/github/gists_test.go index ef95899f..0dd112af 100644 --- a/pkg/github/gists_test.go +++ b/pkg/github/gists_test.go @@ -128,9 +128,9 @@ func Test_ListGists(t *testing.T) { name: "list gists fails with error", mockedClient: MockHTTPClientWithHandlers(map[string]http.HandlerFunc{ GetGists: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.WriteHeader(http.StatusUnauthorized) - _, _ = w.Write([]byte(`{"message": "Requires authentication"}`)) - }), + w.WriteHeader(http.StatusUnauthorized) + _, _ = w.Write([]byte(`{"message": "Requires authentication"}`)) + }), }), requestArgs: map[string]interface{}{}, expectError: true, @@ -239,9 +239,9 @@ func Test_GetGist(t *testing.T) { name: "gist_id parameter missing", mockedClient: MockHTTPClientWithHandlers(map[string]http.HandlerFunc{ GetGistsByGistID: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.WriteHeader(http.StatusUnprocessableEntity) - _, _ = w.Write([]byte(`{"message": "Invalid Request"}`)) - }), + w.WriteHeader(http.StatusUnprocessableEntity) + _, _ = w.Write([]byte(`{"message": "Invalid Request"}`)) + }), }), requestArgs: map[string]interface{}{}, expectError: true, @@ -375,9 +375,9 @@ func Test_CreateGist(t *testing.T) { name: "api returns error", mockedClient: MockHTTPClientWithHandlers(map[string]http.HandlerFunc{ PostGists: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.WriteHeader(http.StatusUnauthorized) - _, _ = w.Write([]byte(`{"message": "Requires authentication"}`)) - }), + w.WriteHeader(http.StatusUnauthorized) + _, _ = w.Write([]byte(`{"message": "Requires authentication"}`)) + }), }), requestArgs: map[string]interface{}{ "filename": "test.go", @@ -527,9 +527,9 @@ func Test_UpdateGist(t *testing.T) { name: "api returns error", mockedClient: MockHTTPClientWithHandlers(map[string]http.HandlerFunc{ PatchGistsByGistID: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - w.WriteHeader(http.StatusNotFound) - _, _ = w.Write([]byte(`{"message": "Not Found"}`)) - }), + w.WriteHeader(http.StatusNotFound) + _, _ = w.Write([]byte(`{"message": "Not Found"}`)) + }), }), requestArgs: map[string]interface{}{ "gist_id": "nonexistent-gist-id",