github.com/andrewhsu/cli/v2@v2.0.1-0.20210910131313-d4b4061f5b89/pkg/cmd/gist/edit/edit_test.go (about) 1 package edit 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "io/ioutil" 7 "net/http" 8 "path/filepath" 9 "testing" 10 11 "github.com/andrewhsu/cli/v2/internal/config" 12 "github.com/andrewhsu/cli/v2/pkg/cmd/gist/shared" 13 "github.com/andrewhsu/cli/v2/pkg/cmdutil" 14 "github.com/andrewhsu/cli/v2/pkg/httpmock" 15 "github.com/andrewhsu/cli/v2/pkg/iostreams" 16 "github.com/andrewhsu/cli/v2/pkg/prompt" 17 "github.com/google/shlex" 18 "github.com/stretchr/testify/assert" 19 "github.com/stretchr/testify/require" 20 ) 21 22 func Test_getFilesToAdd(t *testing.T) { 23 fileToAdd := filepath.Join(t.TempDir(), "gist-test.txt") 24 err := ioutil.WriteFile(fileToAdd, []byte("hello"), 0600) 25 require.NoError(t, err) 26 27 gf, err := getFilesToAdd(fileToAdd) 28 require.NoError(t, err) 29 30 filename := filepath.Base(fileToAdd) 31 assert.Equal(t, map[string]*shared.GistFile{ 32 filename: { 33 Filename: filename, 34 Content: "hello", 35 }, 36 }, gf) 37 } 38 39 func TestNewCmdEdit(t *testing.T) { 40 tests := []struct { 41 name string 42 cli string 43 wants EditOptions 44 }{ 45 { 46 name: "no flags", 47 cli: "123", 48 wants: EditOptions{ 49 Selector: "123", 50 }, 51 }, 52 { 53 name: "filename", 54 cli: "123 --filename cool.md", 55 wants: EditOptions{ 56 Selector: "123", 57 EditFilename: "cool.md", 58 }, 59 }, 60 { 61 name: "add", 62 cli: "123 --add cool.md", 63 wants: EditOptions{ 64 Selector: "123", 65 AddFilename: "cool.md", 66 }, 67 }, 68 } 69 70 for _, tt := range tests { 71 t.Run(tt.name, func(t *testing.T) { 72 f := &cmdutil.Factory{} 73 74 argv, err := shlex.Split(tt.cli) 75 assert.NoError(t, err) 76 77 var gotOpts *EditOptions 78 cmd := NewCmdEdit(f, func(opts *EditOptions) error { 79 gotOpts = opts 80 return nil 81 }) 82 cmd.SetArgs(argv) 83 cmd.SetIn(&bytes.Buffer{}) 84 cmd.SetOut(&bytes.Buffer{}) 85 cmd.SetErr(&bytes.Buffer{}) 86 87 _, err = cmd.ExecuteC() 88 assert.NoError(t, err) 89 90 assert.Equal(t, tt.wants.EditFilename, gotOpts.EditFilename) 91 assert.Equal(t, tt.wants.AddFilename, gotOpts.AddFilename) 92 assert.Equal(t, tt.wants.Selector, gotOpts.Selector) 93 }) 94 } 95 } 96 97 func Test_editRun(t *testing.T) { 98 fileToAdd := filepath.Join(t.TempDir(), "gist-test.txt") 99 err := ioutil.WriteFile(fileToAdd, []byte("hello"), 0600) 100 require.NoError(t, err) 101 102 tests := []struct { 103 name string 104 opts *EditOptions 105 gist *shared.Gist 106 httpStubs func(*httpmock.Registry) 107 askStubs func(*prompt.AskStubber) 108 nontty bool 109 wantErr string 110 wantParams map[string]interface{} 111 }{ 112 { 113 name: "no such gist", 114 wantErr: "gist not found: 1234", 115 }, 116 { 117 name: "one file", 118 gist: &shared.Gist{ 119 ID: "1234", 120 Files: map[string]*shared.GistFile{ 121 "cicada.txt": { 122 Filename: "cicada.txt", 123 Content: "bwhiizzzbwhuiiizzzz", 124 Type: "text/plain", 125 }, 126 }, 127 Owner: &shared.GistOwner{Login: "octocat"}, 128 }, 129 httpStubs: func(reg *httpmock.Registry) { 130 reg.Register(httpmock.REST("POST", "gists/1234"), 131 httpmock.StatusStringResponse(201, "{}")) 132 }, 133 wantParams: map[string]interface{}{ 134 "description": "", 135 "updated_at": "0001-01-01T00:00:00Z", 136 "public": false, 137 "files": map[string]interface{}{ 138 "cicada.txt": map[string]interface{}{ 139 "content": "new file content", 140 "filename": "cicada.txt", 141 "type": "text/plain", 142 }, 143 }, 144 }, 145 }, 146 { 147 name: "multiple files, submit", 148 askStubs: func(as *prompt.AskStubber) { 149 as.StubOne("unix.md") 150 as.StubOne("Submit") 151 }, 152 gist: &shared.Gist{ 153 ID: "1234", 154 Description: "catbug", 155 Files: map[string]*shared.GistFile{ 156 "cicada.txt": { 157 Filename: "cicada.txt", 158 Content: "bwhiizzzbwhuiiizzzz", 159 Type: "text/plain", 160 }, 161 "unix.md": { 162 Filename: "unix.md", 163 Content: "meow", 164 Type: "application/markdown", 165 }, 166 }, 167 Owner: &shared.GistOwner{Login: "octocat"}, 168 }, 169 httpStubs: func(reg *httpmock.Registry) { 170 reg.Register(httpmock.REST("POST", "gists/1234"), 171 httpmock.StatusStringResponse(201, "{}")) 172 }, 173 wantParams: map[string]interface{}{ 174 "description": "catbug", 175 "updated_at": "0001-01-01T00:00:00Z", 176 "public": false, 177 "files": map[string]interface{}{ 178 "cicada.txt": map[string]interface{}{ 179 "content": "bwhiizzzbwhuiiizzzz", 180 "filename": "cicada.txt", 181 "type": "text/plain", 182 }, 183 "unix.md": map[string]interface{}{ 184 "content": "new file content", 185 "filename": "unix.md", 186 "type": "application/markdown", 187 }, 188 }, 189 }, 190 }, 191 { 192 name: "multiple files, cancel", 193 askStubs: func(as *prompt.AskStubber) { 194 as.StubOne("unix.md") 195 as.StubOne("Cancel") 196 }, 197 wantErr: "CancelError", 198 gist: &shared.Gist{ 199 ID: "1234", 200 Files: map[string]*shared.GistFile{ 201 "cicada.txt": { 202 Filename: "cicada.txt", 203 Content: "bwhiizzzbwhuiiizzzz", 204 Type: "text/plain", 205 }, 206 "unix.md": { 207 Filename: "unix.md", 208 Content: "meow", 209 Type: "application/markdown", 210 }, 211 }, 212 Owner: &shared.GistOwner{Login: "octocat"}, 213 }, 214 }, 215 { 216 name: "not change", 217 gist: &shared.Gist{ 218 ID: "1234", 219 Files: map[string]*shared.GistFile{ 220 "cicada.txt": { 221 Filename: "cicada.txt", 222 Content: "new file content", 223 Type: "text/plain", 224 }, 225 }, 226 Owner: &shared.GistOwner{Login: "octocat"}, 227 }, 228 }, 229 { 230 name: "another user's gist", 231 gist: &shared.Gist{ 232 ID: "1234", 233 Files: map[string]*shared.GistFile{ 234 "cicada.txt": { 235 Filename: "cicada.txt", 236 Content: "bwhiizzzbwhuiiizzzz", 237 Type: "text/plain", 238 }, 239 }, 240 Owner: &shared.GistOwner{Login: "octocat2"}, 241 }, 242 wantErr: "You do not own this gist.", 243 }, 244 { 245 name: "add file to existing gist", 246 gist: &shared.Gist{ 247 ID: "1234", 248 Files: map[string]*shared.GistFile{ 249 "sample.txt": { 250 Filename: "sample.txt", 251 Content: "bwhiizzzbwhuiiizzzz", 252 Type: "text/plain", 253 }, 254 }, 255 Owner: &shared.GistOwner{Login: "octocat"}, 256 }, 257 httpStubs: func(reg *httpmock.Registry) { 258 reg.Register(httpmock.REST("POST", "gists/1234"), 259 httpmock.StatusStringResponse(201, "{}")) 260 }, 261 opts: &EditOptions{ 262 AddFilename: fileToAdd, 263 }, 264 }, 265 } 266 267 for _, tt := range tests { 268 reg := &httpmock.Registry{} 269 if tt.gist == nil { 270 reg.Register(httpmock.REST("GET", "gists/1234"), 271 httpmock.StatusStringResponse(404, "Not Found")) 272 } else { 273 reg.Register(httpmock.REST("GET", "gists/1234"), 274 httpmock.JSONResponse(tt.gist)) 275 reg.Register(httpmock.GraphQL(`query UserCurrent\b`), 276 httpmock.StringResponse(`{"data":{"viewer":{"login":"octocat"}}}`)) 277 } 278 279 if tt.httpStubs != nil { 280 tt.httpStubs(reg) 281 } 282 283 as, teardown := prompt.InitAskStubber() 284 defer teardown() 285 if tt.askStubs != nil { 286 tt.askStubs(as) 287 } 288 289 if tt.opts == nil { 290 tt.opts = &EditOptions{} 291 } 292 293 tt.opts.Edit = func(_, _, _ string, _ *iostreams.IOStreams) (string, error) { 294 return "new file content", nil 295 } 296 297 tt.opts.HttpClient = func() (*http.Client, error) { 298 return &http.Client{Transport: reg}, nil 299 } 300 io, _, stdout, stderr := iostreams.Test() 301 io.SetStdoutTTY(!tt.nontty) 302 io.SetStdinTTY(!tt.nontty) 303 tt.opts.IO = io 304 tt.opts.Selector = "1234" 305 306 tt.opts.Config = func() (config.Config, error) { 307 return config.NewBlankConfig(), nil 308 } 309 310 t.Run(tt.name, func(t *testing.T) { 311 err := editRun(tt.opts) 312 reg.Verify(t) 313 if tt.wantErr != "" { 314 assert.EqualError(t, err, tt.wantErr) 315 return 316 } 317 assert.NoError(t, err) 318 319 if tt.wantParams != nil { 320 bodyBytes, _ := ioutil.ReadAll(reg.Requests[2].Body) 321 reqBody := make(map[string]interface{}) 322 err = json.Unmarshal(bodyBytes, &reqBody) 323 if err != nil { 324 t.Fatalf("error decoding JSON: %v", err) 325 } 326 assert.Equal(t, tt.wantParams, reqBody) 327 } 328 329 assert.Equal(t, "", stdout.String()) 330 assert.Equal(t, "", stderr.String()) 331 }) 332 } 333 }