github.com/ActiveState/cli@v0.0.0-20240508170324-6801f60cd051/scripts/internal/workflow-helpers/github_test.go (about) 1 package workflow_helpers 2 3 import ( 4 "fmt" 5 "reflect" 6 "testing" 7 "time" 8 9 "github.com/ActiveState/cli/internal/errs" 10 "github.com/blang/semver" 11 "github.com/google/go-github/v45/github" 12 "github.com/stretchr/testify/require" 13 "github.com/thoas/go-funk" 14 ) 15 16 func TestParseJiraKey(t *testing.T) { 17 testCases := []struct { 18 name string 19 msg string 20 expected string 21 }{ 22 { 23 name: "empty", 24 msg: "", 25 expected: "", 26 }, 27 { 28 name: "no jira", 29 msg: "this is a commit message", 30 expected: "", 31 }, 32 { 33 name: "jira", 34 msg: "this is a commit message with a JIRA issue ID: DX-123", 35 expected: "DX-123", 36 }, 37 { 38 name: "jira with space", 39 msg: "this is a commit message with a JIRA issue ID: DX-123 and some other stuff", 40 expected: "DX-123", 41 }, 42 { 43 name: "jira with multiple", 44 msg: "this is a commit message with a JIRA issue ID: DX-123 and some other stuff and another JIRA issue ID: XYZ-456", 45 expected: "DX-123", 46 }, 47 } 48 49 for _, tc := range testCases { 50 t.Run(tc.name, func(t *testing.T) { 51 actual, err := ParseJiraKey(tc.msg) 52 if err != nil { 53 if tc.expected != "" { 54 t.Errorf("expected %s, got error: %s", tc.expected, errs.JoinMessage(err)) 55 } 56 return 57 } 58 if actual != tc.expected { 59 t.Errorf("Expected %s, got %s", tc.expected, actual) 60 } 61 }) 62 } 63 } 64 65 func TestFetchPRs(t *testing.T) { 66 t.Skip("For debugging purposes, comment this line out if you want to test this locally") 67 68 type args struct { 69 ghClient *github.Client 70 cutoff time.Time 71 opts *github.PullRequestListOptions 72 } 73 tests := []struct { 74 name string 75 args args 76 wantResults bool 77 }{ 78 { 79 name: "success", 80 args: args{ 81 ghClient: InitGHClient(), 82 cutoff: time.Now().AddDate(0, -1, 0), 83 opts: nil, 84 }, 85 wantResults: true, 86 }, 87 { 88 name: "empty", 89 args: args{ 90 ghClient: InitGHClient(), 91 cutoff: time.Now(), 92 opts: &github.PullRequestListOptions{}, 93 }, 94 wantResults: false, 95 }, 96 } 97 for _, tt := range tests { 98 t.Run(tt.name, func(t *testing.T) { 99 got, err := FetchPRs(tt.args.ghClient, tt.args.cutoff, tt.args.opts) 100 if err != nil { 101 t.Errorf("FetchPRs() error = %s", errs.JoinMessage(err)) 102 return 103 } 104 hasResults := len(got) > 0 105 if hasResults != tt.wantResults { 106 t.Errorf("FetchPRs has %d results, but wantResults is %v", len(got), tt.wantResults) 107 } 108 }) 109 } 110 } 111 112 func TestFetchCommitsByRef(t *testing.T) { 113 t.Skip("For debugging purposes, comment this line out if you want to test this locally") 114 115 type args struct { 116 ghClient *github.Client 117 ref string 118 stop func(commit *github.RepositoryCommit, count int) bool 119 } 120 tests := []struct { 121 name string 122 args args 123 wantSHAs []string 124 wantN int 125 }{ 126 { 127 name: "master ref", 128 args: args{ 129 ghClient: InitGHClient(), 130 ref: "master", 131 stop: func(commit *github.RepositoryCommit, count int) bool { return count > 0 }, 132 }, 133 wantN: 1, 134 }, 135 { 136 name: "sha ref", 137 args: args{ 138 ghClient: InitGHClient(), 139 ref: "f52d7fa6b87ca15b1f0a726c062fd6a99d92a287", 140 stop: func(commit *github.RepositoryCommit, count int) bool { return count > 0 }, 141 }, 142 wantSHAs: []string{"f52d7fa6b87ca15b1f0a726c062fd6a99d92a287"}, 143 wantN: 1, 144 }, 145 } 146 for _, tt := range tests { 147 t.Run(tt.name, func(t *testing.T) { 148 count := 0 149 got, err := FetchCommitsByRef(tt.args.ghClient, tt.args.ref, func(commit *github.RepositoryCommit) bool { 150 defer func() { count++ }() 151 return tt.args.stop(commit, count) 152 }) 153 if err != nil { 154 t.Errorf("FetchCommitsByRef() error = %s", errs.JoinMessage(err)) 155 return 156 } 157 validateCommits(t, got, tt.wantSHAs, tt.wantN) 158 }) 159 } 160 } 161 162 func TestSearchGithubIssues(t *testing.T) { 163 t.Skip("For debugging purposes, comment this line out if you want to test this locally") 164 165 type args struct { 166 client *github.Client 167 term string 168 } 169 tests := []struct { 170 name string 171 args args 172 want []string // issue titles 173 maxResults int // This guards against runaway page iterations, feel free to tweak so long as this stays relatively low 174 }{ 175 { 176 name: "Search for Go 1.18 PR", 177 args: args{ 178 client: InitGHClient(), 179 term: "is:pull-request Go 1.18", 180 }, 181 want: []string{"Go 1.18 compatibility"}, 182 maxResults: 20, 183 }, 184 { 185 name: "Readme issue", 186 args: args{ 187 client: InitGHClient(), 188 term: "is:issue readme", 189 }, 190 want: []string{"README.md Development section clarifications"}, 191 maxResults: 5, 192 }, 193 { 194 name: "Version Prefix", 195 args: args{ 196 client: InitGHClient(), 197 term: "is:pr " + VersionedPRPrefix, 198 }, 199 want: []string{"Version 0.34.0-RC1"}, 200 maxResults: 9999, 201 }, 202 } 203 for _, tt := range tests { 204 t.Run(tt.name, func(t *testing.T) { 205 got, err := SearchGithubIssues(tt.args.client, tt.args.term) 206 if err != nil { 207 t.Errorf("SearchGithubIssues() error = %s", errs.JoinMessage(err)) 208 return 209 } 210 for _, title := range tt.want { 211 found := false 212 for _, issue := range got { 213 if issue.GetTitle() == title { 214 found = true 215 break 216 } 217 } 218 if !found { 219 t.Errorf("SearchGithubIssues() did not return issue %s", title) 220 } 221 } 222 }) 223 } 224 } 225 226 func TestFetchPRByTitle(t *testing.T) { 227 t.Skip("For debugging purposes, comment this line out if you want to test this locally") 228 229 type args struct { 230 ghClient *github.Client 231 prName string 232 } 233 tests := []struct { 234 name string 235 args args 236 want string 237 }{ 238 { 239 name: "Go 1.18 compatibility", 240 args: args{ 241 ghClient: InitGHClient(), 242 prName: "Go 1.18 compatibility", 243 }, 244 want: "Go 1.18 compatibility", 245 }, 246 { 247 name: "Non-existant", 248 args: args{ 249 ghClient: InitGHClient(), 250 prName: "Non-existant", 251 }, 252 want: "", 253 }, 254 { 255 name: "Version 0.34.0-RC1", 256 args: args{ 257 ghClient: InitGHClient(), 258 prName: "Version 0.34.0-RC1", 259 }, 260 want: "Version 0.34.0-RC1", 261 }, 262 { 263 name: "Version 0.40.0-RC1", 264 args: args{ 265 ghClient: InitGHClient(), 266 prName: "Version 0.40.0-RC1", 267 }, 268 want: "Version 0.40.0-RC1", 269 }, 270 { 271 name: "Version 0.40.0-RC2", 272 args: args{ 273 ghClient: InitGHClient(), 274 prName: "Version 0.40.0-RC2", 275 }, 276 want: "Version 0.40.0-RC2", 277 }, 278 { 279 name: "Version 0.40.0-RC3", 280 args: args{ 281 ghClient: InitGHClient(), 282 prName: "Version 0.40.0-RC3", 283 }, 284 want: "Version 0.40.0-RC3", 285 }, 286 } 287 for _, tt := range tests { 288 t.Run(tt.name, func(t *testing.T) { 289 got, err := FetchPRByTitle(tt.args.ghClient, tt.args.prName) 290 if err != nil { 291 t.Errorf("FetchPRByTitle() error = %s", errs.JoinMessage(err)) 292 return 293 } 294 if got == nil { 295 if tt.want != "" { 296 t.Errorf("FetchPRByTitle() got = nil, but want %s", tt.want) 297 } 298 return 299 } 300 if got.GetTitle() != tt.want { 301 t.Errorf("FetchPRByTitle() got = %s, want %v", got.GetTitle(), tt.want) 302 } 303 }) 304 } 305 } 306 307 func TestActiveVersionsOnBranch(t *testing.T) { 308 t.Skip("For debugging purposes, comment this line out if you want to test this locally") 309 310 jiraClient, err := InitJiraClient() 311 require.NoError(t, err) 312 313 versions, err := ActiveVersionsOnBranch(InitGHClient(), jiraClient, MasterBranch, time.Now().AddDate(0, -6, 0)) 314 require.NoError(t, err, errs.JoinMessage(err)) 315 if len(versions) < 2 { 316 // Realistically we should have at least 2 versions in development in the past 6 months 317 t.Errorf("ActiveVersionsOnBranch() returned %d versions, want at least 2", len(versions)) 318 } 319 } 320 321 func TestFetchCommitsByShaRange(t *testing.T) { 322 t.Skip("For debugging purposes, comment this line out if you want to test this locally") 323 324 type args struct { 325 ghClient *github.Client 326 startSha string 327 stopSha string 328 } 329 tests := []struct { 330 name string 331 args args 332 wantSHAs []string 333 wantN int 334 }{ 335 { 336 name: "small range", 337 args: args{ 338 ghClient: InitGHClient(), 339 startSha: "97cc4d358ba249493222cd2e8928015714881000", 340 stopSha: "69bbdf1466135094efe0ef77108eae9953d76ac3", 341 }, 342 wantSHAs: []string{"a2fe40506b564ab00b1fe46e2bd170898c46244b"}, 343 wantN: -1, 344 }, 345 { 346 name: "large range", 347 args: args{ 348 ghClient: InitGHClient(), 349 startSha: "5d6e103384849ad2cb6f604da84c4dc9f2245c31", 350 stopSha: "69bbdf1466135094efe0ef77108eae9953d76ac3", 351 }, 352 wantSHAs: []string{"a2fe40506b564ab00b1fe46e2bd170898c46244b"}, 353 wantN: -1, 354 }, 355 } 356 for _, tt := range tests { 357 t.Run(tt.name, func(t *testing.T) { 358 got, err := FetchCommitsByShaRange(tt.args.ghClient, tt.args.startSha, tt.args.stopSha) 359 if err != nil { 360 t.Errorf("FetchCommitsByShaRange() error = %s", errs.JoinMessage(err)) 361 return 362 } 363 validateCommits(t, got, tt.wantSHAs, tt.wantN) 364 }) 365 } 366 } 367 368 func TestUpdatePRTargetBranch(t *testing.T) { 369 t.Skip("For debugging purposes, comment this line out if you want to test this locally") 370 371 err := UpdatePRTargetBranch(InitGHClient(), 1985, "version/0-40-0-RC2") 372 require.NoError(t, err, errs.JoinMessage(err)) 373 } 374 375 func TestCreateBranch(t *testing.T) { 376 t.Skip("For debugging purposes, comment this line out if you want to test this locally") 377 378 prefix := funk.RandomString(10, []rune("abcdefghijklmnopqrstuvwxyz0123456789")) 379 name := prefix + "/" + funk.RandomString(10, []rune("abcdefghijklmnopqrstuvwxyz0123456789")) 380 fmt.Printf("Creating branch %s\n", name) 381 err := CreateBranch(InitGHClient(), name, "f8a9465c572ed7a26145c7ebf961554da9367ec7") 382 require.NoError(t, err, errs.JoinMessage(err)) 383 } 384 385 func validateCommits(t *testing.T, commits []*github.RepositoryCommit, wantSHAs []string, wantN int) { 386 if wantN != -1 && len(commits) != wantN { 387 t.Errorf("FetchCommitsByRef() has %d results, want %d", len(commits), wantN) 388 } 389 for _, sha := range wantSHAs { 390 found := false 391 for _, commit := range commits { 392 if commit.GetSHA() == sha { 393 found = true 394 break 395 } 396 } 397 if !found { 398 t.Errorf("FetchCommitsByRef() did not return sha %s (got %d commits)", sha, len(commits)) 399 } 400 } 401 } 402 403 func TestBehindBy(t *testing.T) { 404 t.Skip("For debugging purposes, comment this line out if you want to test this locally") 405 406 type args struct { 407 client *github.Client 408 base string 409 head string 410 } 411 tests := []struct { 412 name string 413 args args 414 wantBehind bool 415 wantErr bool 416 }{ 417 { 418 "Should be behind", 419 args{ 420 InitGHClient(), 421 "version/0-39-0-RC2", 422 "version/0-39-0-RC1", 423 }, 424 true, 425 false, 426 }, 427 { 428 "Should not be behind", 429 args{ 430 InitGHClient(), 431 "version/0-39-0-RC1", 432 "version/0-39-0-RC2", 433 }, 434 false, 435 false, 436 }, 437 } 438 for _, tt := range tests { 439 t.Run(tt.name, func(t *testing.T) { 440 got, err := GetCommitsBehind(tt.args.client, tt.args.base, tt.args.head) 441 if (err != nil) != tt.wantErr { 442 t.Errorf("BehindBy() error = %v, wantErr %v", err, tt.wantErr) 443 return 444 } 445 if (len(got) > 0) != tt.wantBehind { 446 t.Errorf("BehindBy() got = %v, want %v", len(got), tt.wantBehind) 447 } 448 }) 449 } 450 } 451 452 func TestFetchVersionPR(t *testing.T) { 453 t.Skip("For debugging purposes, comment this line out if you want to test this locally") 454 455 type args struct { 456 ghClient *github.Client 457 assert Assertion 458 versionToCompare semver.Version 459 } 460 tests := []struct { 461 name string 462 args args 463 wantTitle string 464 wantErr bool 465 }{ 466 { 467 "Previous Version", 468 args{ 469 InitGHClient(), 470 AssertLT, 471 semver.MustParse("0.39.0-RC2"), 472 }, 473 "Version 0.39.0-RC1", 474 false, 475 }, 476 { 477 "Next Version", 478 args{ 479 InitGHClient(), 480 AssertGT, 481 semver.MustParse("0.39.0-RC1"), 482 }, 483 "Version 0.39.0-RC2", 484 false, 485 }, 486 } 487 for _, tt := range tests { 488 t.Run(tt.name, func(t *testing.T) { 489 got, err := FetchVersionPR(tt.args.ghClient, tt.args.assert, tt.args.versionToCompare) 490 if (err != nil) != tt.wantErr { 491 t.Errorf("FetchVersionPR() error = %v, wantErr %v", err, tt.wantErr) 492 return 493 } 494 if !reflect.DeepEqual(got.GetTitle(), tt.wantTitle) { 495 t.Errorf("FetchVersionPR() got = %v, want %v", got.GetTitle(), tt.wantTitle) 496 } 497 }) 498 } 499 }