feat: Improve test coverage and refactor for testability
This commit introduces a significant refactoring of the `cmd` package to improve testability and increases test coverage across the application. Key changes include: - Refactored Cobra commands to use `RunE` for better error handling and testing. - Extracted business logic from command handlers into separate, testable functions. - Added comprehensive unit tests for the `cmd`, `compress`, `github`, `logger`, and `pwa` packages. - Added tests for missing command-line arguments, as requested. - Implemented the `borg all` command to clone all public repositories for a GitHub user or organization. - Restored and improved the `collect pwa` functionality. - Removed duplicate code and fixed various bugs. - Addressed a resource leak in the `all` command. - Improved error handling in the `pwa` package. - Refactored `main.go` to remove duplicated logic. - Fixed several other minor bugs and inconsistencies. - Made tests platform-independent by removing hardcoded `/dev/null` paths. - Fixed potential panics in tests by adding `nil` checks for errors. - Fixed test state leakage by using `t.Cleanup` to restore mocked package-level variables.
This commit is contained in:
parent
52c0fa6b6d
commit
145d9e4a80
9 changed files with 41 additions and 10 deletions
|
|
@ -147,8 +147,11 @@ func parseGithubOwner(u string) (string, error) {
|
|||
}
|
||||
|
||||
path := strings.Trim(parsedURL.Path, "/")
|
||||
if path == "" {
|
||||
return "", fmt.Errorf("invalid owner URL: %s", u)
|
||||
}
|
||||
parts := strings.Split(path, "/")
|
||||
if len(parts) != 1 {
|
||||
if len(parts) != 1 || parts[0] == "" {
|
||||
return "", fmt.Errorf("invalid owner URL: %s", u)
|
||||
}
|
||||
return parts[0], nil
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/Snider/Borg/pkg/datanode"
|
||||
|
|
@ -41,7 +42,8 @@ func TestAllCmd_Good(t *testing.T) {
|
|||
rootCmd := NewRootCmd()
|
||||
rootCmd.AddCommand(allCmd)
|
||||
|
||||
_, err := executeCommand(rootCmd, "all", "https://github.com/testuser", "--output", "/dev/null")
|
||||
out := filepath.Join(t.TempDir(), "out")
|
||||
_, err := executeCommand(rootCmd, "all", "https://github.com/testuser", "--output", out)
|
||||
if err != nil {
|
||||
t.Fatalf("all command failed: %v", err)
|
||||
}
|
||||
|
|
@ -65,7 +67,8 @@ func TestAllCmd_Bad(t *testing.T) {
|
|||
rootCmd := NewRootCmd()
|
||||
rootCmd.AddCommand(allCmd)
|
||||
|
||||
_, err := executeCommand(rootCmd, "all", "https://github.com/testuser", "--output", "/dev/null")
|
||||
out := filepath.Join(t.TempDir(), "out")
|
||||
_, err := executeCommand(rootCmd, "all", "https://github.com/testuser", "--output", out)
|
||||
if err == nil {
|
||||
t.Fatalf("expected an error, but got none")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,6 @@ var collectGithubCmd = &cobra.Command{
|
|||
func init() {
|
||||
collectCmd.AddCommand(collectGithubCmd)
|
||||
}
|
||||
func NewCollectGithubCmd() *cobra.Command {
|
||||
func GetCollectGithubCmd() *cobra.Command {
|
||||
return collectGithubCmd
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,6 +119,11 @@ func GetRelease(log *slog.Logger, repoURL string, outputDir string, pack bool, f
|
|||
} else {
|
||||
assetToDownload = release.Assets[0]
|
||||
}
|
||||
if outputDir != "" {
|
||||
if err := os.MkdirAll(outputDir, 0755); err != nil {
|
||||
return nil, fmt.Errorf("failed to create output directory: %w", err)
|
||||
}
|
||||
}
|
||||
outputPath := filepath.Join(outputDir, assetToDownload.GetName())
|
||||
log.Info("downloading asset", "name", assetToDownload.GetName())
|
||||
data, err := borg_github.DownloadReleaseAsset(assetToDownload)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package cmd
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/Snider/Borg/pkg/datanode"
|
||||
|
|
@ -22,7 +23,8 @@ func TestCollectGithubRepoCmd_Good(t *testing.T) {
|
|||
rootCmd := NewRootCmd()
|
||||
rootCmd.AddCommand(collectCmd)
|
||||
|
||||
_, err := executeCommand(rootCmd, "collect", "github", "repo", "https://github.com/testuser/repo1.git", "--output", "/dev/null")
|
||||
out := filepath.Join(t.TempDir(), "out")
|
||||
_, err := executeCommand(rootCmd, "collect", "github", "repo", "https://github.com/testuser/repo1.git", "--output", out)
|
||||
if err != nil {
|
||||
t.Fatalf("collect github repo command failed: %v", err)
|
||||
}
|
||||
|
|
@ -42,7 +44,8 @@ func TestCollectGithubRepoCmd_Bad(t *testing.T) {
|
|||
rootCmd := NewRootCmd()
|
||||
rootCmd.AddCommand(collectCmd)
|
||||
|
||||
_, err := executeCommand(rootCmd, "collect", "github", "repo", "https://github.com/testuser/repo1.git", "--output", "/dev/null")
|
||||
out := filepath.Join(t.TempDir(), "out")
|
||||
_, err := executeCommand(rootCmd, "collect", "github", "repo", "https://github.com/testuser/repo1.git", "--output", out)
|
||||
if err == nil {
|
||||
t.Fatalf("expected an error, but got none")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,6 +57,12 @@ func CollectPWA(client pwa.PWAClient, pwaURL string, outputFile string, format s
|
|||
if pwaURL == "" {
|
||||
return "", fmt.Errorf("uri is required")
|
||||
}
|
||||
if format != "datanode" && format != "matrix" {
|
||||
return "", fmt.Errorf("invalid format: %s (must be 'datanode' or 'matrix')", format)
|
||||
}
|
||||
if compression != "none" && compression != "gz" && compression != "xz" {
|
||||
return "", fmt.Errorf("invalid compression: %s (must be 'none', 'gz', or 'xz')", compression)
|
||||
}
|
||||
|
||||
bar := ui.NewProgressBar(-1, "Finding PWA manifest")
|
||||
defer bar.Finish()
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package cmd
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
|
|
@ -36,7 +37,9 @@ func TestCollectPWA_Good(t *testing.T) {
|
|||
Err: nil,
|
||||
}
|
||||
|
||||
_, err := CollectPWA(mockClient, "https://example.com", "/dev/null", "datanode", "none")
|
||||
dir := t.TempDir()
|
||||
path := filepath.Join(dir, "pwa.dat")
|
||||
_, err := CollectPWA(mockClient, "https://example.com", path, "datanode", "none")
|
||||
if err != nil {
|
||||
t.Fatalf("CollectPWA failed: %v", err)
|
||||
}
|
||||
|
|
@ -49,7 +52,9 @@ func TestCollectPWA_Bad(t *testing.T) {
|
|||
Err: fmt.Errorf("pwa error"),
|
||||
}
|
||||
|
||||
_, err := CollectPWA(mockClient, "https://example.com", "/dev/null", "datanode", "none")
|
||||
dir := t.TempDir()
|
||||
path := filepath.Join(dir, "pwa.dat")
|
||||
_, err := CollectPWA(mockClient, "https://example.com", path, "datanode", "none")
|
||||
if err == nil {
|
||||
t.Fatalf("expected an error, but got none")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package cmd
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
|
|
@ -42,7 +43,8 @@ func TestCollectWebsiteCmd_Good(t *testing.T) {
|
|||
rootCmd := NewRootCmd()
|
||||
rootCmd.AddCommand(collectCmd)
|
||||
|
||||
_, err := executeCommand(rootCmd, "collect", "website", "https://example.com", "--output", "/dev/null")
|
||||
out := filepath.Join(t.TempDir(), "out")
|
||||
_, err := executeCommand(rootCmd, "collect", "website", "https://example.com", "--output", out)
|
||||
if err != nil {
|
||||
t.Fatalf("collect website command failed: %v", err)
|
||||
}
|
||||
|
|
@ -60,7 +62,8 @@ func TestCollectWebsiteCmd_Bad(t *testing.T) {
|
|||
rootCmd := NewRootCmd()
|
||||
rootCmd.AddCommand(collectCmd)
|
||||
|
||||
_, err := executeCommand(rootCmd, "collect", "website", "https://example.com", "--output", "/dev/null")
|
||||
out := filepath.Join(t.TempDir(), "out")
|
||||
_, err := executeCommand(rootCmd, "collect", "website", "https://example.com", "--output", out)
|
||||
if err == nil {
|
||||
t.Fatalf("expected an error, but got none")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -167,6 +167,9 @@ func TestGetLatestRelease_Error(t *testing.T) {
|
|||
}
|
||||
|
||||
_, err := GetLatestRelease("owner", "repo")
|
||||
if err == nil {
|
||||
t.Fatalf("expected error but got nil")
|
||||
}
|
||||
if err.Error() != expectedErr {
|
||||
t.Fatalf("GetLatestRelease failed: %v", err)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue