Mirror of https://git.jolheiser.com/ugit
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

a few more unit tests

+356
+231
internal/git/git_test.go
··· 3 3 import ( 4 4 "path/filepath" 5 5 "testing" 6 + "time" 6 7 7 8 "github.com/alecthomas/assert/v2" 9 + "github.com/go-git/go-git/v5/plumbing/protocol/packp" 8 10 "go.jolheiser.com/ugit/internal/git" 9 11 ) 10 12 ··· 43 45 assert.NoError(t, err, "should not error when getting existing repo") 44 46 assert.False(t, repo.Meta.Private, "repo should be public after saving meta") 45 47 } 48 + 49 + func TestPathExists(t *testing.T) { 50 + tmp := t.TempDir() 51 + exists, err := git.PathExists(tmp) 52 + assert.NoError(t, err) 53 + assert.True(t, exists) 54 + 55 + doesNotExist := filepath.Join(tmp, "does-not-exist") 56 + exists, err = git.PathExists(doesNotExist) 57 + assert.NoError(t, err) 58 + assert.False(t, exists) 59 + } 60 + 61 + func TestRepoMetaUpdate(t *testing.T) { 62 + original := git.RepoMeta{ 63 + Description: "Original description", 64 + Private: true, 65 + Tags: git.TagSet{"tag1": struct{}{}, "tag2": struct{}{}}, 66 + } 67 + 68 + update := git.RepoMeta{ 69 + Description: "Updated description", 70 + Private: false, 71 + Tags: git.TagSet{"tag3": struct{}{}}, 72 + } 73 + 74 + err := original.Update(update) 75 + assert.NoError(t, err) 76 + 77 + assert.Equal(t, "Updated description", original.Description) 78 + assert.False(t, original.Private) 79 + assert.Equal(t, []string{"tag1", "tag2", "tag3"}, original.Tags.Slice()) 80 + } 81 + 82 + func TestFileInfoName(t *testing.T) { 83 + testCases := []struct { 84 + path string 85 + expected string 86 + }{ 87 + {path: "file.txt", expected: "file.txt"}, 88 + {path: "dir/file.txt", expected: "file.txt"}, 89 + {path: "nested/path/to/file.go", expected: "file.go"}, 90 + {path: "README.md", expected: "README.md"}, 91 + } 92 + 93 + for _, tc := range testCases { 94 + t.Run(tc.path, func(t *testing.T) { 95 + fi := git.FileInfo{Path: tc.path} 96 + assert.Equal(t, tc.expected, fi.Name()) 97 + }) 98 + } 99 + } 100 + 101 + func TestCommitSummaryAndDetails(t *testing.T) { 102 + testCases := []struct { 103 + message string 104 + expectedSummary string 105 + expectedDetails string 106 + }{ 107 + { 108 + message: "Simple commit message", 109 + expectedSummary: "Simple commit message", 110 + expectedDetails: "", 111 + }, 112 + { 113 + message: "Add feature X\n\nThis commit adds feature X\nWith multiple details\nAcross multiple lines", 114 + expectedSummary: "Add feature X", 115 + expectedDetails: "\nThis commit adds feature X\nWith multiple details\nAcross multiple lines", 116 + }, 117 + { 118 + message: "Fix bug\n\nDetailed explanation", 119 + expectedSummary: "Fix bug", 120 + expectedDetails: "\nDetailed explanation", 121 + }, 122 + } 123 + 124 + for _, tc := range testCases { 125 + t.Run(tc.message, func(t *testing.T) { 126 + commit := git.Commit{ 127 + SHA: "abcdef1234567890", 128 + Message: tc.message, 129 + Signature: "", 130 + Author: "Test User", 131 + Email: "test@example.com", 132 + When: time.Now(), 133 + } 134 + 135 + assert.Equal(t, tc.expectedSummary, commit.Summary()) 136 + assert.Equal(t, tc.expectedDetails, commit.Details()) 137 + }) 138 + } 139 + } 140 + 141 + func TestCommitShort(t *testing.T) { 142 + commit := git.Commit{ 143 + SHA: "abcdef1234567890abcdef1234567890", 144 + } 145 + 146 + assert.Equal(t, "abcdef12", commit.Short()) 147 + } 148 + 149 + func TestCommitFilePath(t *testing.T) { 150 + testCases := []struct { 151 + name string 152 + fromPath string 153 + toPath string 154 + expected string 155 + }{ 156 + { 157 + name: "to path preferred", 158 + fromPath: "old/path.txt", 159 + toPath: "new/path.txt", 160 + expected: "new/path.txt", 161 + }, 162 + { 163 + name: "fallback to from path", 164 + fromPath: "deleted/file.txt", 165 + toPath: "", 166 + expected: "deleted/file.txt", 167 + }, 168 + { 169 + name: "both paths empty", 170 + fromPath: "", 171 + toPath: "", 172 + expected: "", 173 + }, 174 + } 175 + 176 + for _, tc := range testCases { 177 + t.Run(tc.name, func(t *testing.T) { 178 + cf := git.CommitFile{ 179 + From: git.CommitFileEntry{Path: tc.fromPath}, 180 + To: git.CommitFileEntry{Path: tc.toPath}, 181 + } 182 + assert.Equal(t, tc.expected, cf.Path()) 183 + }) 184 + } 185 + } 186 + 187 + func TestRepoName(t *testing.T) { 188 + tmp := t.TempDir() 189 + 190 + repoName := "testrepo" 191 + err := git.EnsureRepo(tmp, repoName+".git") 192 + assert.NoError(t, err) 193 + 194 + repo, err := git.NewRepo(tmp, repoName) 195 + assert.NoError(t, err) 196 + assert.Equal(t, repoName, repo.Name()) 197 + 198 + repoName2 := "test-repo-with-hyphens" 199 + err = git.EnsureRepo(tmp, repoName2+".git") 200 + assert.NoError(t, err) 201 + 202 + repo2, err := git.NewRepo(tmp, repoName2) 203 + assert.NoError(t, err) 204 + assert.Equal(t, repoName2, repo2.Name()) 205 + } 206 + 207 + func TestHandlePushOptions(t *testing.T) { 208 + tmp := t.TempDir() 209 + err := git.EnsureRepo(tmp, "test.git") 210 + assert.NoError(t, err) 211 + 212 + repo, err := git.NewRepo(tmp, "test") 213 + assert.NoError(t, err) 214 + 215 + opts := []*packp.Option{ 216 + {Key: "description", Value: "New description"}, 217 + } 218 + err = git.HandlePushOptions(repo, opts) 219 + assert.NoError(t, err) 220 + assert.Equal(t, "New description", repo.Meta.Description) 221 + 222 + opts = []*packp.Option{ 223 + {Key: "private", Value: "false"}, 224 + } 225 + err = git.HandlePushOptions(repo, opts) 226 + assert.NoError(t, err) 227 + assert.False(t, repo.Meta.Private) 228 + 229 + repo.Meta.Private = true 230 + opts = []*packp.Option{ 231 + {Key: "private", Value: "invalid"}, 232 + } 233 + err = git.HandlePushOptions(repo, opts) 234 + assert.NoError(t, err) 235 + assert.True(t, repo.Meta.Private) 236 + 237 + opts = []*packp.Option{ 238 + {Key: "tags", Value: "tag1,tag2"}, 239 + } 240 + err = git.HandlePushOptions(repo, opts) 241 + assert.NoError(t, err) 242 + 243 + opts = []*packp.Option{ 244 + {Key: "description", Value: "Combined update"}, 245 + {Key: "private", Value: "true"}, 246 + } 247 + err = git.HandlePushOptions(repo, opts) 248 + assert.NoError(t, err) 249 + assert.Equal(t, "Combined update", repo.Meta.Description) 250 + assert.True(t, repo.Meta.Private) 251 + } 252 + 253 + func TestRepoPath(t *testing.T) { 254 + tmp := t.TempDir() 255 + err := git.EnsureRepo(tmp, "test.git") 256 + assert.NoError(t, err) 257 + 258 + repo, err := git.NewRepo(tmp, "test") 259 + assert.NoError(t, err) 260 + 261 + expected := filepath.Join(tmp, "test.git") 262 + assert.Equal(t, expected, repo.Path()) 263 + } 264 + 265 + func TestEnsureJSONFile(t *testing.T) { 266 + tmp := t.TempDir() 267 + err := git.EnsureRepo(tmp, "test.git") 268 + assert.NoError(t, err) 269 + 270 + repo, err := git.NewRepo(tmp, "test") 271 + assert.NoError(t, err) 272 + 273 + assert.True(t, repo.Meta.Private, "default repo should be private") 274 + assert.Equal(t, "", repo.Meta.Description, "default description should be empty") 275 + assert.Equal(t, 0, len(repo.Meta.Tags), "default tags should be empty") 276 + }
+3
internal/git/repo.go
··· 57 57 if err := json.NewDecoder(fi).Decode(&r.Meta); err != nil { 58 58 return nil, err 59 59 } 60 + if r.Meta.Tags == nil { 61 + r.Meta.Tags = make(TagSet) 62 + } 60 63 61 64 return r, nil 62 65 }
+122
internal/http/httperr/httperr_test.go
··· 1 + package httperr_test 2 + 3 + import ( 4 + "errors" 5 + "net/http" 6 + "net/http/httptest" 7 + "testing" 8 + 9 + "github.com/alecthomas/assert/v2" 10 + "go.jolheiser.com/ugit/internal/http/httperr" 11 + ) 12 + 13 + func successHandler(w http.ResponseWriter, r *http.Request) error { 14 + w.WriteHeader(http.StatusOK) 15 + return nil 16 + } 17 + 18 + func errorHandler(w http.ResponseWriter, r *http.Request) error { 19 + return errors.New("test error") 20 + } 21 + 22 + func statusErrorHandler(status int) func(w http.ResponseWriter, r *http.Request) error { 23 + return func(w http.ResponseWriter, r *http.Request) error { 24 + return httperr.Status(errors.New("test error"), status) 25 + } 26 + } 27 + 28 + func TestHandler_Success(t *testing.T) { 29 + handler := httperr.Handler(successHandler) 30 + 31 + req := httptest.NewRequest("GET", "/", nil) 32 + recorder := httptest.NewRecorder() 33 + 34 + handler.ServeHTTP(recorder, req) 35 + 36 + assert.Equal(t, http.StatusOK, recorder.Code) 37 + } 38 + 39 + func TestHandler_Error(t *testing.T) { 40 + handler := httperr.Handler(errorHandler) 41 + 42 + req := httptest.NewRequest("GET", "/", nil) 43 + recorder := httptest.NewRecorder() 44 + 45 + handler.ServeHTTP(recorder, req) 46 + 47 + assert.Equal(t, http.StatusInternalServerError, recorder.Code) 48 + } 49 + 50 + func TestHandler_StatusError(t *testing.T) { 51 + testCases := []struct { 52 + name string 53 + status int 54 + expectedStatus int 55 + }{ 56 + { 57 + name: "not found", 58 + status: http.StatusNotFound, 59 + expectedStatus: http.StatusNotFound, 60 + }, 61 + { 62 + name: "bad request", 63 + status: http.StatusBadRequest, 64 + expectedStatus: http.StatusBadRequest, 65 + }, 66 + { 67 + name: "unauthorized", 68 + status: http.StatusUnauthorized, 69 + expectedStatus: http.StatusUnauthorized, 70 + }, 71 + } 72 + 73 + for _, tc := range testCases { 74 + t.Run(tc.name, func(t *testing.T) { 75 + handler := httperr.Handler(statusErrorHandler(tc.status)) 76 + 77 + req := httptest.NewRequest("GET", "/", nil) 78 + recorder := httptest.NewRecorder() 79 + 80 + handler.ServeHTTP(recorder, req) 81 + 82 + assert.Equal(t, tc.expectedStatus, recorder.Code) 83 + }) 84 + } 85 + } 86 + 87 + type unwrapper interface { 88 + Unwrap() error 89 + } 90 + 91 + func TestError(t *testing.T) { 92 + originalErr := errors.New("original error") 93 + httpErr := httperr.Error(originalErr) 94 + 95 + assert.Equal(t, originalErr.Error(), httpErr.Error()) 96 + 97 + unwrapper, ok := any(httpErr).(unwrapper) 98 + assert.True(t, ok) 99 + assert.Equal(t, originalErr, unwrapper.Unwrap()) 100 + } 101 + 102 + func TestStatus(t *testing.T) { 103 + originalErr := errors.New("original error") 104 + httpErr := httperr.Status(originalErr, http.StatusNotFound) 105 + 106 + assert.Equal(t, originalErr.Error(), httpErr.Error()) 107 + 108 + unwrapper, ok := any(httpErr).(unwrapper) 109 + assert.True(t, ok) 110 + assert.Equal(t, originalErr, unwrapper.Unwrap()) 111 + 112 + handler := httperr.Handler(func(w http.ResponseWriter, r *http.Request) error { 113 + return httpErr 114 + }) 115 + 116 + req := httptest.NewRequest("GET", "/", nil) 117 + recorder := httptest.NewRecorder() 118 + 119 + handler.ServeHTTP(recorder, req) 120 + 121 + assert.Equal(t, http.StatusNotFound, recorder.Code) 122 + }