| @@ -3,6 +3,8 @@ package control |
| 3 | 3 | import ( |
| 4 | 4 | "bytes" |
| 5 | 5 | "encoding/json" |
| 6 | "os" |
| 7 | "path/filepath" |
| 6 | 8 | "strconv" |
| 7 | 9 | "strings" |
| 8 | 10 | "testing" |
| @@ -177,3 +179,86 @@ func TestMREditSupersededByOnOpenMRRefused(t *testing.T) { |
| 177 | 179 | t.Fatalf("stderr = %q, want the closed-only refusal", errOut.String()) |
| 178 | 180 | } |
| 179 | 181 | } |
| 182 | |
| 183 | // mr show pluralizes multi-row section headings with counts. |
| 184 | func TestMRShowPluralizesMultiRowSections(t *testing.T) { |
| 185 | st, repo, uid := newQueueTestRepo(t) |
| 186 | owner := store.User{ID: uid, Username: "alice"} |
| 187 | |
| 188 | // Create git commits for the MR |
| 189 | git := gitRunner(t) |
| 190 | root := t.TempDir() |
| 191 | |
| 192 | // Create a temporary repository to set up commits |
| 193 | src := filepath.Join(root, "src") |
| 194 | os.MkdirAll(src, 0o755) |
| 195 | git(root, "init", "-q", "-b", "main", "src") |
| 196 | |
| 197 | // Create base commit on main |
| 198 | os.WriteFile(filepath.Join(src, "file.txt"), []byte("content"), 0o644) |
| 199 | git(src, "add", ".") |
| 200 | git(src, "commit", "-q", "-m", "initial") |
| 201 | |
| 202 | // Create feature branch with 2 commits |
| 203 | git(src, "checkout", "-q", "-b", "feature") |
| 204 | os.WriteFile(filepath.Join(src, "file.txt"), []byte("content1"), 0o644) |
| 205 | git(src, "add", ".") |
| 206 | git(src, "commit", "-q", "-m", "commit1") |
| 207 | |
| 208 | os.WriteFile(filepath.Join(src, "file.txt"), []byte("content2"), 0o644) |
| 209 | git(src, "add", ".") |
| 210 | git(src, "commit", "-q", "-m", "commit2") |
| 211 | headSHA := strings.TrimSpace(git(src, "rev-parse", "HEAD")) |
| 212 | |
| 213 | // Clone as a bare repository to the gitbay path |
| 214 | dir := RepoDir(root, repo.OwnerName, repo.Name) |
| 215 | os.MkdirAll(filepath.Dir(dir), 0o755) |
| 216 | git(root, "clone", "-q", "--bare", "src", dir) |
| 217 | |
| 218 | // Create the MR head ref in the bare repository |
| 219 | git(dir, "update-ref", "refs/merge-requests/1/head", headSHA) |
| 220 | |
| 221 | // Create an MR |
| 222 | _, err := st.CreateMR(repo.ID, uid, repo.ID, "feature", "main", "Feature", "", headSHA, "md", false) |
| 223 | if err != nil { |
| 224 | t.Fatalf("CreateMR: %v", err) |
| 225 | } |
| 226 | |
| 227 | // Add 2 checks |
| 228 | if err := st.SetCommitStatus(repo.ID, headSHA, "check1", "success", "", "", 0); err != nil { |
| 229 | t.Fatal(err) |
| 230 | } |
| 231 | if err := st.SetCommitStatus(repo.ID, headSHA, "check2", "success", "", "", 0); err != nil { |
| 232 | t.Fatal(err) |
| 233 | } |
| 234 | |
| 235 | // Add 2 reviews |
| 236 | bob, err := st.CreateUser("bob", false) |
| 237 | if err != nil { |
| 238 | t.Fatal(err) |
| 239 | } |
| 240 | if err := st.AddMRReview(1, bob, "approve", headSHA); err != nil { |
| 241 | t.Fatal(err) |
| 242 | } |
| 243 | charlie, err := st.CreateUser("charlie", false) |
| 244 | if err != nil { |
| 245 | t.Fatal(err) |
| 246 | } |
| 247 | if err := st.AddMRReview(1, charlie, "approve", headSHA); err != nil { |
| 248 | t.Fatal(err) |
| 249 | } |
| 250 | |
| 251 | // Call mr show in plain text mode |
| 252 | c, out, errOut := mrTestCtx(st, owner) |
| 253 | c.Cfg.Server.Root = root |
| 254 | if code := Dispatch(c, []string{"mr", "show", repo.Path(), "1"}); code != protocol.ExitOK { |
| 255 | t.Fatalf("mr show: exit %d, %s", code, errOut.String()) |
| 256 | } |
| 257 | |
| 258 | outStr := out.String() |
| 259 | for _, want := range []string{"commits (2):", "checks (2):", "reviews (2):"} { |
| 260 | if !strings.Contains(outStr, want) { |
| 261 | t.Errorf("missing %q in:\n%s", want, outStr) |
| 262 | } |
| 263 | } |
| 264 | } |