diff --git a/internal/git/git_test.go b/internal/git/git_test.go index df523a08c975c4e35e040d68c339617a66c6965b..fd5ee80a7b76409c4f99be8a55c4ee942af54876 100644 --- a/internal/git/git_test.go +++ b/internal/git/git_test.go @@ -3,10 +3,8 @@ import ( "path/filepath" "testing" - "time" "github.com/alecthomas/assert/v2" - "github.com/go-git/go-git/v5/plumbing/protocol/packp" "go.jolheiser.com/ugit/internal/git" ) @@ -45,232 +43,3 @@ repo, err = git.NewRepo(tmp, "test") assert.NoError(t, err, "should not error when getting existing repo") assert.False(t, repo.Meta.Private, "repo should be public after saving meta") } - -func TestPathExists(t *testing.T) { - tmp := t.TempDir() - exists, err := git.PathExists(tmp) - assert.NoError(t, err) - assert.True(t, exists) - - doesNotExist := filepath.Join(tmp, "does-not-exist") - exists, err = git.PathExists(doesNotExist) - assert.NoError(t, err) - assert.False(t, exists) -} - -func TestRepoMetaUpdate(t *testing.T) { - original := git.RepoMeta{ - Description: "Original description", - Private: true, - Tags: git.TagSet{"tag1": struct{}{}, "tag2": struct{}{}}, - } - - update := git.RepoMeta{ - Description: "Updated description", - Private: false, - Tags: git.TagSet{"tag3": struct{}{}}, - } - - err := original.Update(update) - assert.NoError(t, err) - - assert.Equal(t, "Updated description", original.Description) - assert.False(t, original.Private) - assert.Equal(t, []string{"tag1", "tag2", "tag3"}, original.Tags.Slice()) -} - -func TestFileInfoName(t *testing.T) { - testCases := []struct { - path string - expected string - }{ - {path: "file.txt", expected: "file.txt"}, - {path: "dir/file.txt", expected: "file.txt"}, - {path: "nested/path/to/file.go", expected: "file.go"}, - {path: "README.md", expected: "README.md"}, - } - - for _, tc := range testCases { - t.Run(tc.path, func(t *testing.T) { - fi := git.FileInfo{Path: tc.path} - assert.Equal(t, tc.expected, fi.Name()) - }) - } -} - -func TestCommitSummaryAndDetails(t *testing.T) { - testCases := []struct { - message string - expectedSummary string - expectedDetails string - }{ - { - message: "Simple commit message", - expectedSummary: "Simple commit message", - expectedDetails: "", - }, - { - message: "Add feature X\n\nThis commit adds feature X\nWith multiple details\nAcross multiple lines", - expectedSummary: "Add feature X", - expectedDetails: "\nThis commit adds feature X\nWith multiple details\nAcross multiple lines", - }, - { - message: "Fix bug\n\nDetailed explanation", - expectedSummary: "Fix bug", - expectedDetails: "\nDetailed explanation", - }, - } - - for _, tc := range testCases { - t.Run(tc.message, func(t *testing.T) { - commit := git.Commit{ - SHA: "abcdef1234567890", - Message: tc.message, - Signature: "", - Author: "Test User", - Email: "test@example.com", - When: time.Now(), - } - - assert.Equal(t, tc.expectedSummary, commit.Summary()) - assert.Equal(t, tc.expectedDetails, commit.Details()) - }) - } -} - -func TestCommitShort(t *testing.T) { - commit := git.Commit{ - SHA: "abcdef1234567890abcdef1234567890", - } - - assert.Equal(t, "abcdef12", commit.Short()) -} - -func TestCommitFilePath(t *testing.T) { - testCases := []struct { - name string - fromPath string - toPath string - expected string - }{ - { - name: "to path preferred", - fromPath: "old/path.txt", - toPath: "new/path.txt", - expected: "new/path.txt", - }, - { - name: "fallback to from path", - fromPath: "deleted/file.txt", - toPath: "", - expected: "deleted/file.txt", - }, - { - name: "both paths empty", - fromPath: "", - toPath: "", - expected: "", - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - cf := git.CommitFile{ - From: git.CommitFileEntry{Path: tc.fromPath}, - To: git.CommitFileEntry{Path: tc.toPath}, - } - assert.Equal(t, tc.expected, cf.Path()) - }) - } -} - -func TestRepoName(t *testing.T) { - tmp := t.TempDir() - - repoName := "testrepo" - err := git.EnsureRepo(tmp, repoName+".git") - assert.NoError(t, err) - - repo, err := git.NewRepo(tmp, repoName) - assert.NoError(t, err) - assert.Equal(t, repoName, repo.Name()) - - repoName2 := "test-repo-with-hyphens" - err = git.EnsureRepo(tmp, repoName2+".git") - assert.NoError(t, err) - - repo2, err := git.NewRepo(tmp, repoName2) - assert.NoError(t, err) - assert.Equal(t, repoName2, repo2.Name()) -} - -func TestHandlePushOptions(t *testing.T) { - tmp := t.TempDir() - err := git.EnsureRepo(tmp, "test.git") - assert.NoError(t, err) - - repo, err := git.NewRepo(tmp, "test") - assert.NoError(t, err) - - opts := []*packp.Option{ - {Key: "description", Value: "New description"}, - } - err = git.HandlePushOptions(repo, opts) - assert.NoError(t, err) - assert.Equal(t, "New description", repo.Meta.Description) - - opts = []*packp.Option{ - {Key: "private", Value: "false"}, - } - err = git.HandlePushOptions(repo, opts) - assert.NoError(t, err) - assert.False(t, repo.Meta.Private) - - repo.Meta.Private = true - opts = []*packp.Option{ - {Key: "private", Value: "invalid"}, - } - err = git.HandlePushOptions(repo, opts) - assert.NoError(t, err) - assert.True(t, repo.Meta.Private) - - opts = []*packp.Option{ - {Key: "tags", Value: "tag1,tag2"}, - } - err = git.HandlePushOptions(repo, opts) - assert.NoError(t, err) - - opts = []*packp.Option{ - {Key: "description", Value: "Combined update"}, - {Key: "private", Value: "true"}, - } - err = git.HandlePushOptions(repo, opts) - assert.NoError(t, err) - assert.Equal(t, "Combined update", repo.Meta.Description) - assert.True(t, repo.Meta.Private) -} - -func TestRepoPath(t *testing.T) { - tmp := t.TempDir() - err := git.EnsureRepo(tmp, "test.git") - assert.NoError(t, err) - - repo, err := git.NewRepo(tmp, "test") - assert.NoError(t, err) - - expected := filepath.Join(tmp, "test.git") - assert.Equal(t, expected, repo.Path()) -} - -func TestEnsureJSONFile(t *testing.T) { - tmp := t.TempDir() - err := git.EnsureRepo(tmp, "test.git") - assert.NoError(t, err) - - repo, err := git.NewRepo(tmp, "test") - assert.NoError(t, err) - - assert.True(t, repo.Meta.Private, "default repo should be private") - assert.Equal(t, "", repo.Meta.Description, "default description should be empty") - assert.Equal(t, 0, len(repo.Meta.Tags), "default tags should be empty") -} diff --git a/internal/git/repo.go b/internal/git/repo.go index 2b9eff873c1485cb06bc3f34438ef640fe913c33..1d19a4376ea628f1c944f83547b3f736eed30767 100644 --- a/internal/git/repo.go +++ b/internal/git/repo.go @@ -57,9 +57,6 @@ if err := json.NewDecoder(fi).Decode(&r.Meta); err != nil { return nil, err } - if r.Meta.Tags == nil { - r.Meta.Tags = make(TagSet) - } return r, nil } diff --git a/internal/http/httperr/httperr_test.go b/internal/http/httperr/httperr_test.go deleted file mode 100644 index 562e5643a58c5f4271a96ea2a5eb6e8e0d5612e7..0000000000000000000000000000000000000000 --- a/internal/http/httperr/httperr_test.go +++ /dev/null @@ -1,122 +0,0 @@ -package httperr_test - -import ( - "errors" - "net/http" - "net/http/httptest" - "testing" - - "github.com/alecthomas/assert/v2" - "go.jolheiser.com/ugit/internal/http/httperr" -) - -func successHandler(w http.ResponseWriter, r *http.Request) error { - w.WriteHeader(http.StatusOK) - return nil -} - -func errorHandler(w http.ResponseWriter, r *http.Request) error { - return errors.New("test error") -} - -func statusErrorHandler(status int) func(w http.ResponseWriter, r *http.Request) error { - return func(w http.ResponseWriter, r *http.Request) error { - return httperr.Status(errors.New("test error"), status) - } -} - -func TestHandler_Success(t *testing.T) { - handler := httperr.Handler(successHandler) - - req := httptest.NewRequest("GET", "/", nil) - recorder := httptest.NewRecorder() - - handler.ServeHTTP(recorder, req) - - assert.Equal(t, http.StatusOK, recorder.Code) -} - -func TestHandler_Error(t *testing.T) { - handler := httperr.Handler(errorHandler) - - req := httptest.NewRequest("GET", "/", nil) - recorder := httptest.NewRecorder() - - handler.ServeHTTP(recorder, req) - - assert.Equal(t, http.StatusInternalServerError, recorder.Code) -} - -func TestHandler_StatusError(t *testing.T) { - testCases := []struct { - name string - status int - expectedStatus int - }{ - { - name: "not found", - status: http.StatusNotFound, - expectedStatus: http.StatusNotFound, - }, - { - name: "bad request", - status: http.StatusBadRequest, - expectedStatus: http.StatusBadRequest, - }, - { - name: "unauthorized", - status: http.StatusUnauthorized, - expectedStatus: http.StatusUnauthorized, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - handler := httperr.Handler(statusErrorHandler(tc.status)) - - req := httptest.NewRequest("GET", "/", nil) - recorder := httptest.NewRecorder() - - handler.ServeHTTP(recorder, req) - - assert.Equal(t, tc.expectedStatus, recorder.Code) - }) - } -} - -type unwrapper interface { - Unwrap() error -} - -func TestError(t *testing.T) { - originalErr := errors.New("original error") - httpErr := httperr.Error(originalErr) - - assert.Equal(t, originalErr.Error(), httpErr.Error()) - - unwrapper, ok := any(httpErr).(unwrapper) - assert.True(t, ok) - assert.Equal(t, originalErr, unwrapper.Unwrap()) -} - -func TestStatus(t *testing.T) { - originalErr := errors.New("original error") - httpErr := httperr.Status(originalErr, http.StatusNotFound) - - assert.Equal(t, originalErr.Error(), httpErr.Error()) - - unwrapper, ok := any(httpErr).(unwrapper) - assert.True(t, ok) - assert.Equal(t, originalErr, unwrapper.Unwrap()) - - handler := httperr.Handler(func(w http.ResponseWriter, r *http.Request) error { - return httpErr - }) - - req := httptest.NewRequest("GET", "/", nil) - recorder := httptest.NewRecorder() - - handler.ServeHTTP(recorder, req) - - assert.Equal(t, http.StatusNotFound, recorder.Code) -}