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:
google-labs-jules[bot] 2025-11-03 19:34:36 +00:00
parent 52c0fa6b6d
commit 145d9e4a80
9 changed files with 41 additions and 10 deletions

View file

@ -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

View file

@ -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")
}

View file

@ -14,6 +14,6 @@ var collectGithubCmd = &cobra.Command{
func init() {
collectCmd.AddCommand(collectGithubCmd)
}
func NewCollectGithubCmd() *cobra.Command {
func GetCollectGithubCmd() *cobra.Command {
return collectGithubCmd
}

View file

@ -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)

View file

@ -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")
}

View file

@ -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()

View file

@ -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")
}

View file

@ -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")
}

View file

@ -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)
}