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  }