From abcc3dce8883aca1644268a02b6d87e15f4c1927 Mon Sep 17 00:00:00 2001 From: ayesha arshad Date: Tue, 16 Apr 2024 11:33:39 +0200 Subject: [PATCH] added more tests - Added new unit tests for Azure DevOps support. - Improved test coverage for parse payload functions. --- pkg/provider/azuredevops/azuredevops_test.go | 189 ++++++++++++++++++ pkg/provider/azuredevops/parse_payload.go | 2 +- .../azuredevops/parse_payload_test.go | 47 +++++ 3 files changed, 237 insertions(+), 1 deletion(-) create mode 100644 pkg/provider/azuredevops/azuredevops_test.go diff --git a/pkg/provider/azuredevops/azuredevops_test.go b/pkg/provider/azuredevops/azuredevops_test.go new file mode 100644 index 000000000..4d319f9e1 --- /dev/null +++ b/pkg/provider/azuredevops/azuredevops_test.go @@ -0,0 +1,189 @@ +package azuredevops + +import ( + "context" + "net/http" + "net/http/httptest" + "testing" + + "github.com/microsoft/azure-devops-go-api/azuredevops/v7/git" + "github.com/openshift-pipelines/pipelines-as-code/pkg/params" + "github.com/openshift-pipelines/pipelines-as-code/pkg/params/info" + statusOpts "github.com/openshift-pipelines/pipelines-as-code/pkg/provider" + + "github.com/openshift-pipelines/pipelines-as-code/pkg/params/settings" +) + +type MockGitClient struct { + git.Client // Embedding git.Client for future-proofing against new methods + createCommitStatus func(ctx context.Context, args git.CreateCommitStatusArgs) (*git.GitStatus, error) + getPullRequestStatuses func(ctx context.Context, args git.GetPullRequestStatusesArgs) (*[]git.GitPullRequestStatus, error) + updatePullRequestStatus func(ctx context.Context, args git.UpdatePullRequestStatusesArgs) error + createPullRequestStatus func(ctx context.Context, args git.CreatePullRequestStatusArgs) (*git.GitPullRequestStatus, error) + createAnnotatedTag func(ctx context.Context, args git.CreateAnnotatedTagArgs) (*git.GitAnnotatedTag, error) +} + +func (m *MockGitClient) CreateCommitStatus(ctx context.Context, args git.CreateCommitStatusArgs) (*git.GitStatus, error) { + return m.createCommitStatus(ctx, args) +} + +func (m *MockGitClient) GetPullRequestStatuses(ctx context.Context, args git.GetPullRequestStatusesArgs) (*[]git.GitPullRequestStatus, error) { + return m.getPullRequestStatuses(ctx, args) +} + +func (m *MockGitClient) UpdatePullRequestStatuses(ctx context.Context, args git.UpdatePullRequestStatusesArgs) error { + return m.updatePullRequestStatus(ctx, args) +} + +func (m *MockGitClient) CreatePullRequestStatus(ctx context.Context, args git.CreatePullRequestStatusArgs) (*git.GitPullRequestStatus, error) { + return m.createPullRequestStatus(ctx, args) +} + +func (m *MockGitClient) CreateAnnotatedTag(ctx context.Context, args git.CreateAnnotatedTagArgs) (*git.GitAnnotatedTag, error) { + if m.createAnnotatedTag != nil { + return m.createAnnotatedTag(ctx, args) + } + return nil, nil +} + +func Setup(t *testing.T) (*MockGitClient, *http.ServeMux, func()) { + mux := http.NewServeMux() + server := httptest.NewServer(mux) + tearDown := func() { + server.Close() + } + + mockClient := &MockGitClient{ + createCommitStatus: func(ctx context.Context, args git.CreateCommitStatusArgs) (*git.GitStatus, error) { + return &git.GitStatus{}, nil + }, + getPullRequestStatuses: func(ctx context.Context, args git.GetPullRequestStatusesArgs) (*[]git.GitPullRequestStatus, error) { + return &[]git.GitPullRequestStatus{}, nil + }, + updatePullRequestStatus: func(ctx context.Context, args git.UpdatePullRequestStatusesArgs) error { + return nil + }, + createPullRequestStatus: func(ctx context.Context, args git.CreatePullRequestStatusArgs) (*git.GitPullRequestStatus, error) { + return &git.GitPullRequestStatus{}, nil + }, + createAnnotatedTag: func(ctx context.Context, args git.CreateAnnotatedTagArgs) (*git.GitAnnotatedTag, error) { + return &git.GitAnnotatedTag{}, nil + }, + } + + return mockClient, mux, tearDown +} + +func getProvider(mockClient *MockGitClient) *Provider { + provider := &Provider{ + Client: mockClient, + run: ¶ms.Run{ + Info: info.Info{ + Pac: &info.PacOpts{ + Settings: &settings.Settings{ + ApplicationName: "Pipelines as Code CI", + }, + }, + }, + }, + } + return provider +} + +func TestCreateStatus(t *testing.T) { + mockClient, _, tearDown := Setup(t) + defer tearDown() + + ctx := context.Background() + + provider := getProvider(mockClient) + + testCases := []struct { + name string + event *info.Event + statusOpts statusOpts.StatusOpts + expectError bool + }{ + { + name: "Git Push - Success", + event: &info.Event{ + EventType: "git.push", + }, + + statusOpts: statusOpts.StatusOpts{ + Conclusion: "success", + }, + expectError: false, + }, + { + name: "Git Push - Failed", + event: &info.Event{ + EventType: "git.push", + }, + statusOpts: statusOpts.StatusOpts{ + Conclusion: "failure", + }, + expectError: false, + }, + { + name: "Git Push - Pending", + event: &info.Event{ + EventType: "git.push", + }, + statusOpts: statusOpts.StatusOpts{ + Conclusion: "pending", + Status: "in_progress", + }, + expectError: false, + }, + { + name: "Git Pull Request - Success", + event: &info.Event{ + EventType: "git.pullrequest.created", + }, + statusOpts: statusOpts.StatusOpts{ + Conclusion: "success", + }, + expectError: false, + }, + { + name: "Git Pull Request - Pending", + event: &info.Event{ + EventType: "git.pullrequest.created", + }, + statusOpts: statusOpts.StatusOpts{ + Conclusion: "pending", + }, + expectError: false, + }, + { + name: "Git Push - Unknown status", + event: &info.Event{ + EventType: "git.push", + }, + statusOpts: statusOpts.StatusOpts{ + Conclusion: "abc", + }, + expectError: false, + }, + { + name: "Non-existent Resource", + event: &info.Event{ + EventType: "git.push", + }, + statusOpts: statusOpts.StatusOpts{ + Conclusion: "error", + }, + expectError: false, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + err := provider.CreateStatus(ctx, tc.event, tc.statusOpts) + if (err != nil) != tc.expectError { + t.Errorf("Test %s expected error: %v, got: %v", tc.name, tc.expectError, err) + } + }) + } +} diff --git a/pkg/provider/azuredevops/parse_payload.go b/pkg/provider/azuredevops/parse_payload.go index 8e64f7ec8..f7aae9ff2 100644 --- a/pkg/provider/azuredevops/parse_payload.go +++ b/pkg/provider/azuredevops/parse_payload.go @@ -68,7 +68,7 @@ func (v *Provider) ParsePayload(_ context.Context, _ *params.Run, request *http. processedEvent.TriggerTarget = triggertype.Push // Assuming the repository URL can serve as both BaseURL and HeadURL for viewing purposes processedEvent.BaseURL = pushEvent.Repository.Url // or it could be remoteUrl or it could be other; need to verify - processedEvent.HeadURL = pushEvent.Repository.Url // or it could be remoteUrl or it could be othe; need to verify + processedEvent.HeadURL = pushEvent.Repository.Url // or it could be remoteUrl or it could be other; need to verify if len(pushEvent.RefUpdates) > 0 { branchName := ExtractBranchName(pushEvent.RefUpdates[0].Name) processedEvent.BaseBranch = branchName diff --git a/pkg/provider/azuredevops/parse_payload_test.go b/pkg/provider/azuredevops/parse_payload_test.go index 16c17e3e0..f019c5125 100644 --- a/pkg/provider/azuredevops/parse_payload_test.go +++ b/pkg/provider/azuredevops/parse_payload_test.go @@ -190,3 +190,50 @@ func TestParsePayload_Errors(t *testing.T) { }) } } + +func TestExtractBranchName(t *testing.T) { + tests := []struct { + name string + refName string + wantBranch string + }{ + {"Standard ref name", "refs/heads/master", "master"}, + {"Nested branch name", "refs/heads/feature/new-feature", "new-feature"}, + {"Non-standard format", "master", "master"}, + {"Empty ref name", "", ""}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := ExtractBranchName(tt.refName); got != tt.wantBranch { + t.Errorf("ExtractBranchName(%q) = %q, want %q", tt.refName, got, tt.wantBranch) + } + }) + } +} + +func TestExtractBaseURL(t *testing.T) { + tests := []struct { + name string + url string + wantBaseURL string + wantErr bool + }{ + {"Valid Azure URL", "https://dev.azure.com/exampleOrg/exampleProject", "https://dev.azure.com/exampleOrg", false}, + {"Invalid Azure URL", "https://dev.azure.com/", "", true}, + {"Non-Azure URL", "https://example.com", "", true}, + {"Empty URL", "", "", true}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := extractBaseURL(tt.url) + if (err != nil) != tt.wantErr { + t.Errorf("extractBaseURL(%q) expected error? %v, got error? %v", tt.url, tt.wantErr, err != nil) + } + if got != tt.wantBaseURL { + t.Errorf("extractBaseURL(%q) = %q, want %q", tt.url, got, tt.wantBaseURL) + } + }) + } +}