From f8ca4b8373ee4e7b9f9c0c0497117a52f09534bf Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Fri, 29 May 2026 11:03:15 +0300 Subject: fix(cli): stabilize public factory tests and nil guards (mq) --- internal/cli/repo_client_factory_injection_test.go | 61 +++++++++++++++++----- internal/cli/sync_handlers.go | 20 ++++++- 2 files changed, 67 insertions(+), 14 deletions(-) diff --git a/internal/cli/repo_client_factory_injection_test.go b/internal/cli/repo_client_factory_injection_test.go index 902eec1..fcebd7f 100644 --- a/internal/cli/repo_client_factory_injection_test.go +++ b/internal/cli/repo_client_factory_injection_test.go @@ -270,9 +270,6 @@ func TestCreateRepoHelpersWithFactory_UseInjectedCreateClients(t *testing.T) { func TestHandleSyncGitHubPublic_UsesInjectedFactoryClient(t *testing.T) { t.Parallel() - oldFactory := cliRepoClientFactory - t.Cleanup(func() { cliRepoClientFactory = oldFactory }) - factory := &stubRepoClientFactory{ githubPublicClient: &stubGitHubPublicRepoClient{ hasToken: true, @@ -281,7 +278,6 @@ func TestHandleSyncGitHubPublic_UsesInjectedFactoryClient(t *testing.T) { }, }, } - cliRepoClientFactory = factory cfg := &config.Config{ Organizations: []config.Organization{ @@ -293,8 +289,8 @@ func TestHandleSyncGitHubPublic_UsesInjectedFactoryClient(t *testing.T) { WorkDir: t.TempDir(), } - if got := HandleSyncGitHubPublic(cfg, flags); got != 0 { - t.Fatalf("HandleSyncGitHubPublic() = %d, want 0", got) + if got := handleSyncGitHubPublicWithFactory(cfg, flags, factory); got != 0 { + t.Fatalf("handleSyncGitHubPublicWithFactory() = %d, want 0", got) } if factory.githubPublicRepoCalls != 1 { t.Fatalf("expected exactly one injected GitHub public client creation, got %d", factory.githubPublicRepoCalls) @@ -307,9 +303,6 @@ func TestHandleSyncGitHubPublic_UsesInjectedFactoryClient(t *testing.T) { func TestHandleSyncCodebergPublic_UsesInjectedFactoryClient(t *testing.T) { t.Parallel() - oldFactory := cliRepoClientFactory - t.Cleanup(func() { cliRepoClientFactory = oldFactory }) - factory := &stubRepoClientFactory{ codebergPublicClient: &stubCodebergPublicRepoClient{ orgErr: errors.New("org lookup failed"), @@ -318,7 +311,6 @@ func TestHandleSyncCodebergPublic_UsesInjectedFactoryClient(t *testing.T) { }, }, } - cliRepoClientFactory = factory cfg := &config.Config{ Organizations: []config.Organization{ @@ -331,8 +323,8 @@ func TestHandleSyncCodebergPublic_UsesInjectedFactoryClient(t *testing.T) { WorkDir: t.TempDir(), } - if got := HandleSyncCodebergPublic(cfg, flags); got != 0 { - t.Fatalf("HandleSyncCodebergPublic() = %d, want 0", got) + if got := handleSyncCodebergPublicWithFactory(cfg, flags, factory); got != 0 { + t.Fatalf("handleSyncCodebergPublicWithFactory() = %d, want 0", got) } if factory.codebergPublicCalls != 1 { t.Fatalf("expected exactly one injected Codeberg public client creation, got %d", factory.codebergPublicCalls) @@ -342,6 +334,51 @@ func TestHandleSyncCodebergPublic_UsesInjectedFactoryClient(t *testing.T) { } } +func TestHandleSyncGitHubPublicWithFactory_ReturnsErrorWhenFactoryReturnsNilClient(t *testing.T) { + t.Parallel() + + factory := &stubRepoClientFactory{githubPublicClient: nil} + cfg := &config.Config{ + Organizations: []config.Organization{ + {Host: "git@github.com", Name: "acme", GitHubToken: "gh-token"}, + }, + } + flags := &Flags{ + DryRun: true, + WorkDir: t.TempDir(), + } + + if got := handleSyncGitHubPublicWithFactory(cfg, flags, factory); got != 1 { + t.Fatalf("handleSyncGitHubPublicWithFactory() = %d, want 1", got) + } + if factory.githubPublicRepoCalls != 1 { + t.Fatalf("expected one GitHub public client factory call, got %d", factory.githubPublicRepoCalls) + } +} + +func TestHandleSyncCodebergPublicWithFactory_ReturnsErrorWhenFactoryReturnsNilClient(t *testing.T) { + t.Parallel() + + factory := &stubRepoClientFactory{codebergPublicClient: nil} + cfg := &config.Config{ + Organizations: []config.Organization{ + {Host: "git@codeberg.org", Name: "acme", CodebergToken: "cb-token"}, + }, + } + flags := &Flags{ + DryRun: true, + SyncGitHubPublic: false, + WorkDir: t.TempDir(), + } + + if got := handleSyncCodebergPublicWithFactory(cfg, flags, factory); got != 1 { + t.Fatalf("handleSyncCodebergPublicWithFactory() = %d, want 1", got) + } + if factory.codebergPublicCalls != 1 { + t.Fatalf("expected one Codeberg public client factory call, got %d", factory.codebergPublicCalls) + } +} + func TestInitGitHubClientWithFactory_Branches(t *testing.T) { t.Parallel() diff --git a/internal/cli/sync_handlers.go b/internal/cli/sync_handlers.go index dd08af6..8c362ce 100644 --- a/internal/cli/sync_handlers.go +++ b/internal/cli/sync_handlers.go @@ -181,6 +181,10 @@ func HandleSyncAll(cfg *config.Config, flags *Flags) int { // HandleSyncCodebergPublic handles syncing all public Codeberg repositories func HandleSyncCodebergPublic(cfg *config.Config, flags *Flags) int { + return handleSyncCodebergPublicWithFactory(cfg, flags, cliRepoClientFactory) +} + +func handleSyncCodebergPublicWithFactory(cfg *config.Config, flags *Flags, factory repoClientFactory) int { codebergOrg := cfg.FindCodebergOrg() if codebergOrg == nil { fmt.Println("No Codeberg organization found in configuration") @@ -189,7 +193,11 @@ func HandleSyncCodebergPublic(cfg *config.Config, flags *Flags) int { fmt.Printf("Fetching public repositories from Codeberg user/org: %s...\n", codebergOrg.Name) - client := cliRepoClientFactory.NewCodebergPublicRepoClient(codebergOrg.CodebergToken, codebergOrg.Name) + client := factory.NewCodebergPublicRepoClient(codebergOrg.CodebergToken, codebergOrg.Name) + if client == nil { + fmt.Println("ERROR: Failed to initialize Codeberg public repository client") + return 1 + } // Try fetching as organization first, then as user repos, err := client.ListPublicRepos() @@ -238,6 +246,10 @@ func HandleSyncCodebergPublic(cfg *config.Config, flags *Flags) int { // HandleSyncGitHubPublic handles syncing all public GitHub repositories func HandleSyncGitHubPublic(cfg *config.Config, flags *Flags) int { + return handleSyncGitHubPublicWithFactory(cfg, flags, cliRepoClientFactory) +} + +func handleSyncGitHubPublicWithFactory(cfg *config.Config, flags *Flags, factory repoClientFactory) int { githubOrg := cfg.FindGitHubOrg() if githubOrg == nil { fmt.Println("No GitHub organization found in configuration") @@ -246,7 +258,11 @@ func HandleSyncGitHubPublic(cfg *config.Config, flags *Flags) int { fmt.Printf("Fetching public repositories from GitHub user/org: %s...\n", githubOrg.Name) - client := cliRepoClientFactory.NewGitHubPublicRepoClient(githubOrg.GitHubToken, githubOrg.Name) + client := factory.NewGitHubPublicRepoClient(githubOrg.GitHubToken, githubOrg.Name) + if client == nil { + fmt.Println("ERROR: Failed to initialize GitHub public repository client") + return 1 + } if !client.HasToken() { fmt.Println("ERROR: GitHub token required to list repositories") fmt.Println("Set GITHUB_TOKEN env var or create ~/.gitsyncer_github_token file") -- cgit v1.2.3