github.com/secman-team/gh-api@v1.8.2/pkg/cmd/auth/status/status_test.go (about)

     1  package status
     2  
     3  import (
     4  	"bytes"
     5  	"net/http"
     6  	"regexp"
     7  	"testing"
     8  
     9  	"github.com/secman-team/gh-api/core/config"
    10  	"github.com/secman-team/gh-api/pkg/cmdutil"
    11  	"github.com/secman-team/gh-api/pkg/httpmock"
    12  	"github.com/secman-team/gh-api/pkg/iostreams"
    13  	"github.com/google/shlex"
    14  	"github.com/stretchr/testify/assert"
    15  )
    16  
    17  func Test_NewCmdStatus(t *testing.T) {
    18  	tests := []struct {
    19  		name  string
    20  		cli   string
    21  		wants StatusOptions
    22  	}{
    23  		{
    24  			name:  "no arguments",
    25  			cli:   "",
    26  			wants: StatusOptions{},
    27  		},
    28  		{
    29  			name: "hostname set",
    30  			cli:  "--hostname ellie.williams",
    31  			wants: StatusOptions{
    32  				Hostname: "ellie.williams",
    33  			},
    34  		},
    35  		{
    36  			name: "show token",
    37  			cli:  "--show-token",
    38  			wants: StatusOptions{
    39  				ShowToken: true,
    40  			},
    41  		},
    42  	}
    43  
    44  	for _, tt := range tests {
    45  		t.Run(tt.name, func(t *testing.T) {
    46  			f := &cmdutil.Factory{}
    47  
    48  			argv, err := shlex.Split(tt.cli)
    49  			assert.NoError(t, err)
    50  
    51  			var gotOpts *StatusOptions
    52  			cmd := NewCmdStatus(f, func(opts *StatusOptions) error {
    53  				gotOpts = opts
    54  				return nil
    55  			})
    56  
    57  			// TODO cobra hack-around
    58  			cmd.Flags().BoolP("help", "x", false, "")
    59  
    60  			cmd.SetArgs(argv)
    61  			cmd.SetIn(&bytes.Buffer{})
    62  			cmd.SetOut(&bytes.Buffer{})
    63  			cmd.SetErr(&bytes.Buffer{})
    64  
    65  			_, err = cmd.ExecuteC()
    66  			assert.NoError(t, err)
    67  
    68  			assert.Equal(t, tt.wants.Hostname, gotOpts.Hostname)
    69  		})
    70  	}
    71  }
    72  
    73  func Test_statusRun(t *testing.T) {
    74  	tests := []struct {
    75  		name       string
    76  		opts       *StatusOptions
    77  		httpStubs  func(*httpmock.Registry)
    78  		cfg        func(config.Config)
    79  		wantErr    string
    80  		wantErrOut *regexp.Regexp
    81  	}{
    82  		{
    83  			name: "hostname set",
    84  			opts: &StatusOptions{
    85  				Hostname: "joel.miller",
    86  			},
    87  			cfg: func(c config.Config) {
    88  				_ = c.Set("joel.miller", "oauth_token", "abc123")
    89  				_ = c.Set("github.com", "oauth_token", "abc123")
    90  			},
    91  			httpStubs: func(reg *httpmock.Registry) {
    92  				reg.Register(httpmock.REST("GET", "api/v3/"), httpmock.ScopesResponder("repo,read:org"))
    93  				reg.Register(
    94  					httpmock.GraphQL(`query UserCurrent\b`),
    95  					httpmock.StringResponse(`{"data":{"viewer":{"login":"tess"}}}`))
    96  			},
    97  			wantErrOut: regexp.MustCompile(`Logged in to joel.miller as.*tess`),
    98  		},
    99  		{
   100  			name: "missing scope",
   101  			opts: &StatusOptions{},
   102  			cfg: func(c config.Config) {
   103  				_ = c.Set("joel.miller", "oauth_token", "abc123")
   104  				_ = c.Set("github.com", "oauth_token", "abc123")
   105  			},
   106  			httpStubs: func(reg *httpmock.Registry) {
   107  				reg.Register(httpmock.REST("GET", "api/v3/"), httpmock.ScopesResponder("repo"))
   108  				reg.Register(httpmock.REST("GET", ""), httpmock.ScopesResponder("repo,read:org"))
   109  				reg.Register(
   110  					httpmock.GraphQL(`query UserCurrent\b`),
   111  					httpmock.StringResponse(`{"data":{"viewer":{"login":"tess"}}}`))
   112  			},
   113  			wantErrOut: regexp.MustCompile(`joel.miller: missing required.*Logged in to github.com as.*tess`),
   114  			wantErr:    "SilentError",
   115  		},
   116  		{
   117  			name: "bad token",
   118  			opts: &StatusOptions{},
   119  			cfg: func(c config.Config) {
   120  				_ = c.Set("joel.miller", "oauth_token", "abc123")
   121  				_ = c.Set("github.com", "oauth_token", "abc123")
   122  			},
   123  			httpStubs: func(reg *httpmock.Registry) {
   124  				reg.Register(httpmock.REST("GET", "api/v3/"), httpmock.StatusStringResponse(400, "no bueno"))
   125  				reg.Register(httpmock.REST("GET", ""), httpmock.ScopesResponder("repo,read:org"))
   126  				reg.Register(
   127  					httpmock.GraphQL(`query UserCurrent\b`),
   128  					httpmock.StringResponse(`{"data":{"viewer":{"login":"tess"}}}`))
   129  			},
   130  			wantErrOut: regexp.MustCompile(`joel.miller: authentication failed.*Logged in to github.com as.*tess`),
   131  			wantErr:    "SilentError",
   132  		},
   133  		{
   134  			name: "all good",
   135  			opts: &StatusOptions{},
   136  			cfg: func(c config.Config) {
   137  				_ = c.Set("joel.miller", "oauth_token", "abc123")
   138  				_ = c.Set("github.com", "oauth_token", "abc123")
   139  			},
   140  			httpStubs: func(reg *httpmock.Registry) {
   141  				reg.Register(httpmock.REST("GET", "api/v3/"), httpmock.ScopesResponder("repo,read:org"))
   142  				reg.Register(httpmock.REST("GET", ""), httpmock.ScopesResponder("repo,read:org"))
   143  				reg.Register(
   144  					httpmock.GraphQL(`query UserCurrent\b`),
   145  					httpmock.StringResponse(`{"data":{"viewer":{"login":"tess"}}}`))
   146  				reg.Register(
   147  					httpmock.GraphQL(`query UserCurrent\b`),
   148  					httpmock.StringResponse(`{"data":{"viewer":{"login":"tess"}}}`))
   149  			},
   150  			wantErrOut: regexp.MustCompile(`(?s)Logged in to github.com as.*tess.*Logged in to joel.miller as.*tess`),
   151  		},
   152  		{
   153  			name: "hide token",
   154  			opts: &StatusOptions{},
   155  			cfg: func(c config.Config) {
   156  				_ = c.Set("joel.miller", "oauth_token", "abc123")
   157  				_ = c.Set("github.com", "oauth_token", "xyz456")
   158  			},
   159  			httpStubs: func(reg *httpmock.Registry) {
   160  				reg.Register(httpmock.REST("GET", "api/v3/"), httpmock.ScopesResponder("repo,read:org"))
   161  				reg.Register(httpmock.REST("GET", ""), httpmock.ScopesResponder("repo,read:org"))
   162  				reg.Register(
   163  					httpmock.GraphQL(`query UserCurrent\b`),
   164  					httpmock.StringResponse(`{"data":{"viewer":{"login":"tess"}}}`))
   165  				reg.Register(
   166  					httpmock.GraphQL(`query UserCurrent\b`),
   167  					httpmock.StringResponse(`{"data":{"viewer":{"login":"tess"}}}`))
   168  			},
   169  			wantErrOut: regexp.MustCompile(`(?s)Token: \*{19}.*Token: \*{19}`),
   170  		},
   171  		{
   172  			name: "show token",
   173  			opts: &StatusOptions{
   174  				ShowToken: true,
   175  			},
   176  			cfg: func(c config.Config) {
   177  				_ = c.Set("joel.miller", "oauth_token", "abc123")
   178  				_ = c.Set("github.com", "oauth_token", "xyz456")
   179  			},
   180  			httpStubs: func(reg *httpmock.Registry) {
   181  				reg.Register(httpmock.REST("GET", "api/v3/"), httpmock.ScopesResponder("repo,read:org"))
   182  				reg.Register(httpmock.REST("GET", ""), httpmock.ScopesResponder("repo,read:org"))
   183  				reg.Register(
   184  					httpmock.GraphQL(`query UserCurrent\b`),
   185  					httpmock.StringResponse(`{"data":{"viewer":{"login":"tess"}}}`))
   186  				reg.Register(
   187  					httpmock.GraphQL(`query UserCurrent\b`),
   188  					httpmock.StringResponse(`{"data":{"viewer":{"login":"tess"}}}`))
   189  			},
   190  			wantErrOut: regexp.MustCompile(`(?s)Token: xyz456.*Token: abc123`),
   191  		}, {
   192  			name: "missing hostname",
   193  			opts: &StatusOptions{
   194  				Hostname: "github.example.com",
   195  			},
   196  			cfg: func(c config.Config) {
   197  				_ = c.Set("github.com", "oauth_token", "abc123")
   198  			},
   199  			httpStubs:  func(reg *httpmock.Registry) {},
   200  			wantErrOut: regexp.MustCompile(`(?s)Hostname "github.example.com" not found among authenticated GitHub hosts`),
   201  			wantErr:    "SilentError",
   202  		},
   203  	}
   204  
   205  	for _, tt := range tests {
   206  		t.Run(tt.name, func(t *testing.T) {
   207  			if tt.opts == nil {
   208  				tt.opts = &StatusOptions{}
   209  			}
   210  
   211  			io, _, _, stderr := iostreams.Test()
   212  
   213  			io.SetStdinTTY(true)
   214  			io.SetStderrTTY(true)
   215  			io.SetStdoutTTY(true)
   216  
   217  			tt.opts.IO = io
   218  
   219  			cfg := config.NewBlankConfig()
   220  
   221  			if tt.cfg != nil {
   222  				tt.cfg(cfg)
   223  			}
   224  			tt.opts.Config = func() (config.Config, error) {
   225  				return cfg, nil
   226  			}
   227  
   228  			reg := &httpmock.Registry{}
   229  			tt.opts.HttpClient = func() (*http.Client, error) {
   230  				return &http.Client{Transport: reg}, nil
   231  			}
   232  			if tt.httpStubs != nil {
   233  				tt.httpStubs(reg)
   234  			}
   235  			mainBuf := bytes.Buffer{}
   236  			hostsBuf := bytes.Buffer{}
   237  			defer config.StubWriteConfig(&mainBuf, &hostsBuf)()
   238  
   239  			err := statusRun(tt.opts)
   240  			if tt.wantErr != "" {
   241  				assert.EqualError(t, err, tt.wantErr)
   242  				return
   243  			} else {
   244  				assert.NoError(t, err)
   245  			}
   246  
   247  			if tt.wantErrOut == nil {
   248  				assert.Equal(t, "", stderr.String())
   249  			} else {
   250  				assert.True(t, tt.wantErrOut.MatchString(stderr.String()))
   251  			}
   252  
   253  			assert.Equal(t, "", mainBuf.String())
   254  			assert.Equal(t, "", hostsBuf.String())
   255  
   256  			reg.Verify(t)
   257  		})
   258  	}
   259  }