diff --git a/cmd/git.go b/cmd/git.go index c34e9ac..354f69e 100644 --- a/cmd/git.go +++ b/cmd/git.go @@ -40,7 +40,6 @@ func extractGitInfo(refreshGitInfo func() error, getProjectRemoteUrl func() (str return GitProjectInfo{}, fmt.Errorf("Could not get project Url: %v", err) } - // play with regex at: https://regex101.com/r/P2jSGh/1 /* This should match following formats: namespace: namespace, projectName: dummy-test-repo: diff --git a/cmd/git_test.go b/cmd/git_test.go new file mode 100644 index 0000000..99935d8 --- /dev/null +++ b/cmd/git_test.go @@ -0,0 +1,251 @@ +package main + +import ( + "errors" + "fmt" + "testing" +) + +func TestExtractGitInfo_Success(t *testing.T) { + getCurrentBranchName := func() (string, error) { + return "feature/abc", nil + } + refreshGitInfo := func() error { + return nil + } + testCases := []struct { + getProjectRemoteUrl func() (string, error) + expected GitProjectInfo + desc string + }{ + { + desc: "Project configured in SSH under a single folder", + getProjectRemoteUrl: func() (string, error) { + return "git@custom-gitlab.com:namespace-1/project-name.git", nil + }, + expected: GitProjectInfo{ + RemoteUrl: "git@custom-gitlab.com:namespace-1/project-name.git", + BranchName: "feature/abc", + ProjectName: "project-name", + Namespace: "namespace-1", + }, + }, + { + desc: "Project configured in SSH under a single folder without .git extension", + getProjectRemoteUrl: func() (string, error) { + return "git@custom-gitlab.com:namespace-1/project-name", nil + }, + expected: GitProjectInfo{ + RemoteUrl: "git@custom-gitlab.com:namespace-1/project-name", + BranchName: "feature/abc", + ProjectName: "project-name", + Namespace: "namespace-1", + }, + }, + { + desc: "Project configured in SSH under one nested folder", + getProjectRemoteUrl: func() (string, error) { + return "git@custom-gitlab.com:namespace-1/namespace-2/project-name.git", nil + }, + expected: GitProjectInfo{ + RemoteUrl: "git@custom-gitlab.com:namespace-1/namespace-2/project-name.git", + BranchName: "feature/abc", + ProjectName: "project-name", + Namespace: "namespace-1/namespace-2", + }, + }, + { + desc: "Project configured in SSH under two nested folders", + getProjectRemoteUrl: func() (string, error) { + return "git@custom-gitlab.com:namespace-1/namespace-2/namespace-3/project-name.git", nil + }, + expected: GitProjectInfo{ + RemoteUrl: "git@custom-gitlab.com:namespace-1/namespace-2/namespace-3/project-name.git", + BranchName: "feature/abc", + ProjectName: "project-name", + Namespace: "namespace-1/namespace-2/namespace-3", + }, + }, + { + desc: "Project configured in SSH:// under a single folder", + getProjectRemoteUrl: func() (string, error) { + return "ssh://custom-gitlab.com/namespace-1/project-name.git", nil + }, + expected: GitProjectInfo{ + RemoteUrl: "ssh://custom-gitlab.com/namespace-1/project-name.git", + BranchName: "feature/abc", + ProjectName: "project-name", + Namespace: "namespace-1", + }, + }, + { + desc: "Project configured in SSH:// under a single folder without .git extension", + getProjectRemoteUrl: func() (string, error) { + return "ssh://custom-gitlab.com/namespace-1/project-name", nil + }, + expected: GitProjectInfo{ + RemoteUrl: "ssh://custom-gitlab.com/namespace-1/project-name", + BranchName: "feature/abc", + ProjectName: "project-name", + Namespace: "namespace-1", + }, + }, + { + desc: "Project configured in SSH:// under two nested folders", + getProjectRemoteUrl: func() (string, error) { + return "ssh://custom-gitlab.com/namespace-1/namespace-2/namespace-3/project-name.git", nil + }, + expected: GitProjectInfo{ + RemoteUrl: "ssh://custom-gitlab.com/namespace-1/namespace-2/namespace-3/project-name.git", + BranchName: "feature/abc", + ProjectName: "project-name", + Namespace: "namespace-1/namespace-2/namespace-3", + }, + }, + { + desc: "Project configured in HTTP and under a single folder without .git extension", + getProjectRemoteUrl: func() (string, error) { + return "http://custom-gitlab.com/namespace-1/project-name", nil + }, + expected: GitProjectInfo{ + RemoteUrl: "http://custom-gitlab.com/namespace-1/project-name", + BranchName: "feature/abc", + ProjectName: "project-name", + Namespace: "namespace-1", + }, + }, + { + desc: "Project configured in HTTPS and under a single folder", + getProjectRemoteUrl: func() (string, error) { + return "https://custom-gitlab.com/namespace-1/project-name.git", nil + }, + expected: GitProjectInfo{ + RemoteUrl: "https://custom-gitlab.com/namespace-1/project-name.git", + BranchName: "feature/abc", + ProjectName: "project-name", + Namespace: "namespace-1", + }, + }, + { + desc: "Project configured in HTTPS and under a nested folder", + getProjectRemoteUrl: func() (string, error) { + return "https://custom-gitlab.com/namespace-1/namespace-2/project-name.git", nil + }, + expected: GitProjectInfo{ + RemoteUrl: "https://custom-gitlab.com/namespace-1/namespace-2/project-name.git", + BranchName: "feature/abc", + ProjectName: "project-name", + Namespace: "namespace-1/namespace-2", + }, + }, + { + desc: "Project configured in HTTPS and under two nested folders", + getProjectRemoteUrl: func() (string, error) { + return "https://custom-gitlab.com/namespace-1/namespace-2/namespace-3/project-name.git", nil + }, + expected: GitProjectInfo{ + RemoteUrl: "https://custom-gitlab.com/namespace-1/namespace-2/namespace-3/project-name.git", + BranchName: "feature/abc", + ProjectName: "project-name", + Namespace: "namespace-1/namespace-2/namespace-3", + }, + }, + } + for _, tC := range testCases { + t.Run(tC.desc, func(t *testing.T) { + actual, err := extractGitInfo(refreshGitInfo, tC.getProjectRemoteUrl, getCurrentBranchName) + if err != nil { + t.Errorf("No error was expected, got %s", err) + } + if actual != tC.expected { + t.Errorf("\nExpected: %s\nActual: %s", tC.expected, actual) + } + }) + } +} + +func TestExtractGitInfo_FailToGetProjectRemoteUrl(t *testing.T) { + getCurrentBranchName := func() (string, error) { + return "feature/abc", nil + } + refreshGitInfo := func() error { + return nil + } + testCases := []struct { + getProjectRemoteUrl func() (string, error) + expectedErrorMessage string + desc string + }{ + { + desc: "Error returned by function to get the project remote url", + getProjectRemoteUrl: func() (string, error) { + return "", errors.New("error when getting project remote url") + }, + expectedErrorMessage: "Could not get project Url: error when getting project remote url", + }, + { + desc: "Invalid project remote url", + getProjectRemoteUrl: func() (string, error) { + return "git@invalid", nil + }, + expectedErrorMessage: "Invalid Git URL format: git@invalid", + }, + } + for _, tC := range testCases { + t.Run(tC.desc, func(t *testing.T) { + _, actualErr := extractGitInfo(refreshGitInfo, tC.getProjectRemoteUrl, getCurrentBranchName) + if actualErr == nil { + t.Errorf("Expected an error, got none") + } + if actualErr.Error() != tC.expectedErrorMessage { + t.Errorf("\nExpected: %s\nActual: %s", tC.expectedErrorMessage, actualErr.Error()) + } + }) + } +} + +func TestExtractGitInfo_FailToGetCurrentBranchName(t *testing.T) { + expectedErrNestedMsg := "error when getting current branch name" + + refreshGitInfo := func() error { + return nil + } + _, actualErr := extractGitInfo(refreshGitInfo, + func() (string, error) { + return "git@custom-gitlab.com:namespace/project.git", nil + }, + func() (string, error) { + return "", errors.New(expectedErrNestedMsg) + }) + + if actualErr == nil { + t.Errorf("Expected an error, got none") + } + expectedErr := fmt.Errorf("Failed to get current branch: %s", expectedErrNestedMsg) + if actualErr.Error() != expectedErr.Error() { + t.Errorf("\nExpected: %s\nActual: %s", expectedErr, actualErr) + } +} + +func TestRefreshGitRemote_FailToRefreshRemote(t *testing.T) { + expectedErrNestedMsg := "error when fetching origin commits" + _, actualErr := extractGitInfo( + func() error { + return errors.New(expectedErrNestedMsg) + }, + func() (string, error) { + return "git@custom-gitlab.com:namespace/project.git", nil + }, + func() (string, error) { + return "feature/abc", nil + }, + ) + + if actualErr == nil { + t.Errorf("Expected an error, got none") + } + expectedErr := fmt.Errorf("Could not get latest information from remote: %s", expectedErrNestedMsg) + if actualErr.Error() != expectedErr.Error() { + t.Errorf("\nExpected: %s\nActual: %s", expectedErr, actualErr) + } +}