package factory import ( "net/url" "os" "testing" "github.com/MakeNowJust/heredoc" "github.com/cli/cli/v2/git" "github.com/cli/cli/v2/internal/config" "github.com/stretchr/testify/assert" ) func Test_remoteResolver(t *testing.T) { orig_GH_HOST := os.Getenv("GH_HOST") t.Cleanup(func() { os.Setenv("GH_HOST", orig_GH_HOST) }) tests := []struct { name string remotes func() (git.RemoteSet, error) config func() (config.Config, error) override string output []string wantsErr bool }{ { name: "no authenticated hosts", remotes: func() (git.RemoteSet, error) { return git.RemoteSet{ git.NewRemote("origin", "https://github.com/owner/repo.git"), }, nil }, config: func() (config.Config, error) { return config.NewFromString(heredoc.Doc(`hosts:`)), nil }, wantsErr: true, }, { name: "no git remotes", remotes: func() (git.RemoteSet, error) { return git.RemoteSet{}, nil }, config: func() (config.Config, error) { return config.NewFromString(heredoc.Doc(` hosts: example.com: oauth_token: GHETOKEN `)), nil }, wantsErr: true, }, { name: "one authenticated host with no matching git remote and no fallback remotes", remotes: func() (git.RemoteSet, error) { return git.RemoteSet{ git.NewRemote("origin", "https://test.com/owner/repo.git"), }, nil }, config: func() (config.Config, error) { return config.NewFromString(heredoc.Doc(` hosts: example.com: oauth_token: GHETOKEN `)), nil }, wantsErr: true, }, { name: "one authenticated host with no matching git remote and fallback remotes", remotes: func() (git.RemoteSet, error) { return git.RemoteSet{ git.NewRemote("origin", "https://github.com/owner/repo.git"), }, nil }, config: func() (config.Config, error) { return config.NewFromString(heredoc.Doc(` hosts: example.com: oauth_token: GHETOKEN `)), nil }, output: []string{"origin"}, }, { name: "one authenticated host with matching git remote", remotes: func() (git.RemoteSet, error) { return git.RemoteSet{ git.NewRemote("upstream", "https://github.com/owner/repo.git"), git.NewRemote("origin", "https://example.com/owner/repo.git"), }, nil }, config: func() (config.Config, error) { return config.NewFromString(heredoc.Doc(` hosts: example.com: oauth_token: GHETOKEN `)), nil }, output: []string{"origin"}, }, { name: "one authenticated host with multiple matching git remotes", remotes: func() (git.RemoteSet, error) { return git.RemoteSet{ git.NewRemote("upstream", "https://example.com/owner/repo.git"), git.NewRemote("github", "https://example.com/owner/repo.git"), git.NewRemote("origin", "https://example.com/owner/repo.git"), git.NewRemote("fork", "https://example.com/owner/repo.git"), }, nil }, config: func() (config.Config, error) { return config.NewFromString(heredoc.Doc(` hosts: example.com: oauth_token: GHETOKEN `)), nil }, output: []string{"upstream", "github", "origin", "fork"}, }, { name: "multiple authenticated hosts with no matching git remote", remotes: func() (git.RemoteSet, error) { return git.RemoteSet{ git.NewRemote("origin", "https://test.com/owner/repo.git"), }, nil }, config: func() (config.Config, error) { return config.NewFromString(heredoc.Doc(` hosts: example.com: oauth_token: GHETOKEN github.com: oauth_token: GHTOKEN `)), nil }, wantsErr: true, }, { name: "multiple authenticated hosts with one matching git remote", remotes: func() (git.RemoteSet, error) { return git.RemoteSet{ git.NewRemote("upstream", "https://test.com/owner/repo.git"), git.NewRemote("origin", "https://example.com/owner/repo.git"), }, nil }, config: func() (config.Config, error) { return config.NewFromString(heredoc.Doc(` hosts: example.com: oauth_token: GHETOKEN github.com: oauth_token: GHTOKEN `)), nil }, output: []string{"origin"}, }, { name: "multiple authenticated hosts with multiple matching git remotes", remotes: func() (git.RemoteSet, error) { return git.RemoteSet{ git.NewRemote("upstream", "https://example.com/owner/repo.git"), git.NewRemote("github", "https://github.com/owner/repo.git"), git.NewRemote("origin", "https://example.com/owner/repo.git"), git.NewRemote("fork", "https://github.com/owner/repo.git"), git.NewRemote("test", "https://test.com/owner/repo.git"), }, nil }, config: func() (config.Config, error) { return config.NewFromString(heredoc.Doc(` hosts: example.com: oauth_token: GHETOKEN github.com: oauth_token: GHTOKEN `)), nil }, output: []string{"upstream", "github", "origin", "fork"}, }, { name: "override host with no matching git remotes", remotes: func() (git.RemoteSet, error) { return git.RemoteSet{ git.NewRemote("origin", "https://example.com/owner/repo.git"), }, nil }, config: func() (config.Config, error) { return config.InheritEnv(config.NewFromString(heredoc.Doc(` hosts: example.com: oauth_token: GHETOKEN `))), nil }, override: "test.com", wantsErr: true, }, { name: "override host with one matching git remote", remotes: func() (git.RemoteSet, error) { return git.RemoteSet{ git.NewRemote("upstream", "https://example.com/owner/repo.git"), git.NewRemote("origin", "https://test.com/owner/repo.git"), }, nil }, config: func() (config.Config, error) { return config.InheritEnv(config.NewFromString(heredoc.Doc(` hosts: example.com: oauth_token: GHETOKEN `))), nil }, override: "test.com", output: []string{"origin"}, }, { name: "override host with multiple matching git remotes", remotes: func() (git.RemoteSet, error) { return git.RemoteSet{ git.NewRemote("upstream", "https://test.com/owner/repo.git"), git.NewRemote("github", "https://example.com/owner/repo.git"), git.NewRemote("origin", "https://test.com/owner/repo.git"), }, nil }, config: func() (config.Config, error) { return config.InheritEnv(config.NewFromString(heredoc.Doc(` hosts: example.com: oauth_token: GHETOKEN `))), nil }, override: "test.com", output: []string{"upstream", "origin"}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if tt.override != "" { os.Setenv("GH_HOST", tt.override) } rr := &remoteResolver{ readRemotes: tt.remotes, getConfig: tt.config, urlTranslator: func(u *url.URL) *url.URL { return u }, } resolver := rr.Resolver() remotes, err := resolver() if tt.wantsErr { assert.Error(t, err) return } assert.NoError(t, err) names := []string{} for _, r := range remotes { names = append(names, r.Name) } assert.Equal(t, tt.output, names) }) } }