github.com/ungtb10d/cli/v2@v2.0.0-20221110210412-98537dd9d6a1/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/ungtb10d/cli/v2/internal/config"
    10  	"github.com/ungtb10d/cli/v2/pkg/cmdutil"
    11  	"github.com/ungtb10d/cli/v2/pkg/httpmock"
    12  	"github.com/ungtb10d/cli/v2/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  	readConfigs := config.StubWriteConfig(t)
    75  
    76  	tests := []struct {
    77  		name       string
    78  		opts       *StatusOptions
    79  		httpStubs  func(*httpmock.Registry)
    80  		cfgStubs   func(*config.ConfigMock)
    81  		wantErr    string
    82  		wantErrOut *regexp.Regexp
    83  	}{
    84  		{
    85  			name: "hostname set",
    86  			opts: &StatusOptions{
    87  				Hostname: "joel.miller",
    88  			},
    89  			cfgStubs: func(c *config.ConfigMock) {
    90  				c.Set("joel.miller", "oauth_token", "abc123")
    91  				c.Set("github.com", "oauth_token", "abc123")
    92  			},
    93  			httpStubs: func(reg *httpmock.Registry) {
    94  				reg.Register(httpmock.REST("GET", "api/v3/"), httpmock.ScopesResponder("repo,read:org"))
    95  				reg.Register(
    96  					httpmock.GraphQL(`query UserCurrent\b`),
    97  					httpmock.StringResponse(`{"data":{"viewer":{"login":"tess"}}}`))
    98  			},
    99  			wantErrOut: regexp.MustCompile(`Logged in to joel.miller as.*tess`),
   100  		},
   101  		{
   102  			name: "missing scope",
   103  			opts: &StatusOptions{},
   104  			cfgStubs: func(c *config.ConfigMock) {
   105  				c.Set("joel.miller", "oauth_token", "abc123")
   106  				c.Set("github.com", "oauth_token", "abc123")
   107  			},
   108  			httpStubs: func(reg *httpmock.Registry) {
   109  				reg.Register(httpmock.REST("GET", "api/v3/"), httpmock.ScopesResponder("repo"))
   110  				reg.Register(httpmock.REST("GET", ""), httpmock.ScopesResponder("repo,read:org"))
   111  				reg.Register(
   112  					httpmock.GraphQL(`query UserCurrent\b`),
   113  					httpmock.StringResponse(`{"data":{"viewer":{"login":"tess"}}}`))
   114  			},
   115  			wantErrOut: regexp.MustCompile(`joel.miller: missing required.*Logged in to github.com as.*tess`),
   116  			wantErr:    "SilentError",
   117  		},
   118  		{
   119  			name: "bad token",
   120  			opts: &StatusOptions{},
   121  			cfgStubs: func(c *config.ConfigMock) {
   122  				c.Set("joel.miller", "oauth_token", "abc123")
   123  				c.Set("github.com", "oauth_token", "abc123")
   124  			},
   125  			httpStubs: func(reg *httpmock.Registry) {
   126  				reg.Register(httpmock.REST("GET", "api/v3/"), httpmock.StatusStringResponse(400, "no bueno"))
   127  				reg.Register(httpmock.REST("GET", ""), httpmock.ScopesResponder("repo,read:org"))
   128  				reg.Register(
   129  					httpmock.GraphQL(`query UserCurrent\b`),
   130  					httpmock.StringResponse(`{"data":{"viewer":{"login":"tess"}}}`))
   131  			},
   132  			wantErrOut: regexp.MustCompile(`joel.miller: authentication failed.*Logged in to github.com as.*tess`),
   133  			wantErr:    "SilentError",
   134  		},
   135  		{
   136  			name: "all good",
   137  			opts: &StatusOptions{},
   138  			cfgStubs: func(c *config.ConfigMock) {
   139  				c.Set("github.com", "oauth_token", "abc123")
   140  				c.Set("joel.miller", "oauth_token", "abc123")
   141  			},
   142  			httpStubs: func(reg *httpmock.Registry) {
   143  				reg.Register(httpmock.REST("GET", "api/v3/"), httpmock.ScopesResponder("repo,read:org"))
   144  				reg.Register(httpmock.REST("GET", ""), httpmock.ScopesResponder("repo,read:org"))
   145  				reg.Register(
   146  					httpmock.GraphQL(`query UserCurrent\b`),
   147  					httpmock.StringResponse(`{"data":{"viewer":{"login":"tess"}}}`))
   148  				reg.Register(
   149  					httpmock.GraphQL(`query UserCurrent\b`),
   150  					httpmock.StringResponse(`{"data":{"viewer":{"login":"tess"}}}`))
   151  			},
   152  			wantErrOut: regexp.MustCompile(`(?s)Logged in to github.com as.*tess.*Logged in to joel.miller as.*tess`),
   153  		},
   154  		{
   155  			name: "hide token",
   156  			opts: &StatusOptions{},
   157  			cfgStubs: func(c *config.ConfigMock) {
   158  				c.Set("joel.miller", "oauth_token", "abc123")
   159  				c.Set("github.com", "oauth_token", "xyz456")
   160  			},
   161  			httpStubs: func(reg *httpmock.Registry) {
   162  				reg.Register(httpmock.REST("GET", "api/v3/"), httpmock.ScopesResponder("repo,read:org"))
   163  				reg.Register(httpmock.REST("GET", ""), httpmock.ScopesResponder("repo,read:org"))
   164  				reg.Register(
   165  					httpmock.GraphQL(`query UserCurrent\b`),
   166  					httpmock.StringResponse(`{"data":{"viewer":{"login":"tess"}}}`))
   167  				reg.Register(
   168  					httpmock.GraphQL(`query UserCurrent\b`),
   169  					httpmock.StringResponse(`{"data":{"viewer":{"login":"tess"}}}`))
   170  			},
   171  			wantErrOut: regexp.MustCompile(`(?s)Token: \*{19}.*Token: \*{19}`),
   172  		},
   173  		{
   174  			name: "show token",
   175  			opts: &StatusOptions{
   176  				ShowToken: true,
   177  			},
   178  			cfgStubs: func(c *config.ConfigMock) {
   179  				c.Set("github.com", "oauth_token", "xyz456")
   180  				c.Set("joel.miller", "oauth_token", "abc123")
   181  			},
   182  			httpStubs: func(reg *httpmock.Registry) {
   183  				reg.Register(httpmock.REST("GET", "api/v3/"), httpmock.ScopesResponder("repo,read:org"))
   184  				reg.Register(httpmock.REST("GET", ""), httpmock.ScopesResponder("repo,read:org"))
   185  				reg.Register(
   186  					httpmock.GraphQL(`query UserCurrent\b`),
   187  					httpmock.StringResponse(`{"data":{"viewer":{"login":"tess"}}}`))
   188  				reg.Register(
   189  					httpmock.GraphQL(`query UserCurrent\b`),
   190  					httpmock.StringResponse(`{"data":{"viewer":{"login":"tess"}}}`))
   191  			},
   192  			wantErrOut: regexp.MustCompile(`(?s)Token: xyz456.*Token: abc123`),
   193  		},
   194  		{
   195  			name: "missing hostname",
   196  			opts: &StatusOptions{
   197  				Hostname: "github.example.com",
   198  			},
   199  			cfgStubs: func(c *config.ConfigMock) {
   200  				c.Set("github.com", "oauth_token", "abc123")
   201  			},
   202  			httpStubs:  func(reg *httpmock.Registry) {},
   203  			wantErrOut: regexp.MustCompile(`(?s)Hostname "github.example.com" not found among authenticated GitHub hosts`),
   204  			wantErr:    "SilentError",
   205  		},
   206  	}
   207  
   208  	for _, tt := range tests {
   209  		t.Run(tt.name, func(t *testing.T) {
   210  			if tt.opts == nil {
   211  				tt.opts = &StatusOptions{}
   212  			}
   213  
   214  			ios, _, _, stderr := iostreams.Test()
   215  
   216  			ios.SetStdinTTY(true)
   217  			ios.SetStderrTTY(true)
   218  			ios.SetStdoutTTY(true)
   219  			tt.opts.IO = ios
   220  
   221  			cfg := config.NewFromString("")
   222  			if tt.cfgStubs != nil {
   223  				tt.cfgStubs(cfg)
   224  			}
   225  			tt.opts.Config = func() (config.Config, error) {
   226  				return cfg, nil
   227  			}
   228  
   229  			reg := &httpmock.Registry{}
   230  			tt.opts.HttpClient = func() (*http.Client, error) {
   231  				return &http.Client{Transport: reg}, nil
   232  			}
   233  			if tt.httpStubs != nil {
   234  				tt.httpStubs(reg)
   235  			}
   236  
   237  			err := statusRun(tt.opts)
   238  			if tt.wantErr != "" {
   239  				assert.EqualError(t, err, tt.wantErr)
   240  				return
   241  			} else {
   242  				assert.NoError(t, err)
   243  			}
   244  
   245  			if tt.wantErrOut == nil {
   246  				assert.Equal(t, "", stderr.String())
   247  			} else {
   248  				assert.True(t, tt.wantErrOut.MatchString(stderr.String()))
   249  			}
   250  
   251  			mainBuf := bytes.Buffer{}
   252  			hostsBuf := bytes.Buffer{}
   253  			readConfigs(&mainBuf, &hostsBuf)
   254  
   255  			assert.Equal(t, "", mainBuf.String())
   256  			assert.Equal(t, "", hostsBuf.String())
   257  
   258  			reg.Verify(t)
   259  		})
   260  	}
   261  }