github.com/secman-team/gh-api@v1.8.2/pkg/cmd/auth/refresh/refresh_test.go (about) 1 package refresh 2 3 import ( 4 "bytes" 5 "testing" 6 7 "github.com/secman-team/gh-api/core/config" 8 "github.com/secman-team/gh-api/pkg/cmdutil" 9 "github.com/secman-team/gh-api/pkg/httpmock" 10 "github.com/secman-team/gh-api/pkg/iostreams" 11 "github.com/secman-team/gh-api/pkg/prompt" 12 "github.com/google/shlex" 13 "github.com/stretchr/testify/assert" 14 ) 15 16 // TODO prompt cfg test 17 18 func Test_NewCmdRefresh(t *testing.T) { 19 tests := []struct { 20 name string 21 cli string 22 wants RefreshOptions 23 wantsErr bool 24 tty bool 25 neverPrompt bool 26 }{ 27 { 28 name: "tty no arguments", 29 tty: true, 30 wants: RefreshOptions{ 31 Hostname: "", 32 }, 33 }, 34 { 35 name: "nontty no arguments", 36 wantsErr: true, 37 }, 38 { 39 name: "nontty hostname", 40 cli: "-h aline.cedrac", 41 wants: RefreshOptions{ 42 Hostname: "aline.cedrac", 43 }, 44 }, 45 { 46 name: "tty hostname", 47 tty: true, 48 cli: "-h aline.cedrac", 49 wants: RefreshOptions{ 50 Hostname: "aline.cedrac", 51 }, 52 }, 53 { 54 name: "prompts disabled, no args", 55 tty: true, 56 cli: "", 57 neverPrompt: true, 58 wantsErr: true, 59 }, 60 { 61 name: "prompts disabled, hostname", 62 tty: true, 63 cli: "-h aline.cedrac", 64 neverPrompt: true, 65 wants: RefreshOptions{ 66 Hostname: "aline.cedrac", 67 }, 68 }, 69 { 70 name: "tty one scope", 71 tty: true, 72 cli: "--scopes repo:invite", 73 wants: RefreshOptions{ 74 Scopes: []string{"repo:invite"}, 75 }, 76 }, 77 { 78 name: "tty scopes", 79 tty: true, 80 cli: "--scopes repo:invite,read:public_key", 81 wants: RefreshOptions{ 82 Scopes: []string{"repo:invite", "read:public_key"}, 83 }, 84 }, 85 } 86 87 for _, tt := range tests { 88 t.Run(tt.name, func(t *testing.T) { 89 io, _, _, _ := iostreams.Test() 90 f := &cmdutil.Factory{ 91 IOStreams: io, 92 } 93 io.SetStdinTTY(tt.tty) 94 io.SetStdoutTTY(tt.tty) 95 io.SetNeverPrompt(tt.neverPrompt) 96 97 argv, err := shlex.Split(tt.cli) 98 assert.NoError(t, err) 99 100 var gotOpts *RefreshOptions 101 cmd := NewCmdRefresh(f, func(opts *RefreshOptions) error { 102 gotOpts = opts 103 return nil 104 }) 105 // TODO cobra hack-around 106 cmd.Flags().BoolP("help", "x", false, "") 107 108 cmd.SetArgs(argv) 109 cmd.SetIn(&bytes.Buffer{}) 110 cmd.SetOut(&bytes.Buffer{}) 111 cmd.SetErr(&bytes.Buffer{}) 112 113 _, err = cmd.ExecuteC() 114 if tt.wantsErr { 115 assert.Error(t, err) 116 return 117 } 118 assert.NoError(t, err) 119 assert.Equal(t, tt.wants.Hostname, gotOpts.Hostname) 120 assert.Equal(t, tt.wants.Scopes, gotOpts.Scopes) 121 }) 122 } 123 } 124 125 type authArgs struct { 126 hostname string 127 scopes []string 128 } 129 130 func Test_refreshRun(t *testing.T) { 131 tests := []struct { 132 name string 133 opts *RefreshOptions 134 askStubs func(*prompt.AskStubber) 135 cfgHosts []string 136 wantErr string 137 nontty bool 138 wantAuthArgs authArgs 139 }{ 140 { 141 name: "no hosts configured", 142 opts: &RefreshOptions{}, 143 wantErr: `not logged in to any hosts`, 144 }, 145 { 146 name: "hostname given but dne", 147 cfgHosts: []string{ 148 "github.com", 149 "aline.cedrac", 150 }, 151 opts: &RefreshOptions{ 152 Hostname: "obed.morton", 153 }, 154 wantErr: `not logged in to obed.morton`, 155 }, 156 { 157 name: "hostname provided and is configured", 158 cfgHosts: []string{ 159 "obed.morton", 160 "github.com", 161 }, 162 opts: &RefreshOptions{ 163 Hostname: "obed.morton", 164 }, 165 wantAuthArgs: authArgs{ 166 hostname: "obed.morton", 167 scopes: nil, 168 }, 169 }, 170 { 171 name: "no hostname, one host configured", 172 cfgHosts: []string{ 173 "github.com", 174 }, 175 opts: &RefreshOptions{ 176 Hostname: "", 177 }, 178 wantAuthArgs: authArgs{ 179 hostname: "github.com", 180 scopes: nil, 181 }, 182 }, 183 { 184 name: "no hostname, multiple hosts configured", 185 cfgHosts: []string{ 186 "github.com", 187 "aline.cedrac", 188 }, 189 opts: &RefreshOptions{ 190 Hostname: "", 191 }, 192 askStubs: func(as *prompt.AskStubber) { 193 as.StubOne("github.com") 194 }, 195 wantAuthArgs: authArgs{ 196 hostname: "github.com", 197 scopes: nil, 198 }, 199 }, 200 { 201 name: "scopes provided", 202 cfgHosts: []string{ 203 "github.com", 204 }, 205 opts: &RefreshOptions{ 206 Scopes: []string{"repo:invite", "public_key:read"}, 207 }, 208 wantAuthArgs: authArgs{ 209 hostname: "github.com", 210 scopes: []string{"repo:invite", "public_key:read"}, 211 }, 212 }, 213 } 214 for _, tt := range tests { 215 t.Run(tt.name, func(t *testing.T) { 216 aa := authArgs{} 217 tt.opts.AuthFlow = func(_ config.Config, _ *iostreams.IOStreams, hostname string, scopes []string) error { 218 aa.hostname = hostname 219 aa.scopes = scopes 220 return nil 221 } 222 223 io, _, _, _ := iostreams.Test() 224 225 io.SetStdinTTY(!tt.nontty) 226 io.SetStdoutTTY(!tt.nontty) 227 228 tt.opts.IO = io 229 cfg := config.NewBlankConfig() 230 tt.opts.Config = func() (config.Config, error) { 231 return cfg, nil 232 } 233 for _, hostname := range tt.cfgHosts { 234 _ = cfg.Set(hostname, "oauth_token", "abc123") 235 } 236 reg := &httpmock.Registry{} 237 reg.Register( 238 httpmock.GraphQL(`query UserCurrent\b`), 239 httpmock.StringResponse(`{"data":{"viewer":{"login":"cybilb"}}}`)) 240 241 mainBuf := bytes.Buffer{} 242 hostsBuf := bytes.Buffer{} 243 defer config.StubWriteConfig(&mainBuf, &hostsBuf)() 244 245 as, teardown := prompt.InitAskStubber() 246 defer teardown() 247 if tt.askStubs != nil { 248 tt.askStubs(as) 249 } 250 251 err := refreshRun(tt.opts) 252 if tt.wantErr != "" { 253 if assert.Error(t, err) { 254 assert.Contains(t, err.Error(), tt.wantErr) 255 } 256 } else { 257 assert.NoError(t, err) 258 } 259 260 assert.Equal(t, aa.hostname, tt.wantAuthArgs.hostname) 261 assert.Equal(t, aa.scopes, tt.wantAuthArgs.scopes) 262 }) 263 } 264 }