github.com/cli/cli@v1.14.1-0.20210902173923-1af6a669e342/pkg/cmd/release/download/download_test.go (about) 1 package download 2 3 import ( 4 "bytes" 5 "io/ioutil" 6 "net/http" 7 "os" 8 "path/filepath" 9 "testing" 10 11 "github.com/cli/cli/internal/ghrepo" 12 "github.com/cli/cli/pkg/cmdutil" 13 "github.com/cli/cli/pkg/httpmock" 14 "github.com/cli/cli/pkg/iostreams" 15 "github.com/google/shlex" 16 "github.com/stretchr/testify/assert" 17 "github.com/stretchr/testify/require" 18 ) 19 20 func Test_NewCmdDownload(t *testing.T) { 21 tests := []struct { 22 name string 23 args string 24 isTTY bool 25 want DownloadOptions 26 wantErr string 27 }{ 28 { 29 name: "version argument", 30 args: "v1.2.3", 31 isTTY: true, 32 want: DownloadOptions{ 33 TagName: "v1.2.3", 34 FilePatterns: []string(nil), 35 Destination: ".", 36 Concurrency: 5, 37 }, 38 }, 39 { 40 name: "version and file pattern", 41 args: "v1.2.3 -p *.tgz", 42 isTTY: true, 43 want: DownloadOptions{ 44 TagName: "v1.2.3", 45 FilePatterns: []string{"*.tgz"}, 46 Destination: ".", 47 Concurrency: 5, 48 }, 49 }, 50 { 51 name: "multiple file patterns", 52 args: "v1.2.3 -p 1 -p 2,3", 53 isTTY: true, 54 want: DownloadOptions{ 55 TagName: "v1.2.3", 56 FilePatterns: []string{"1", "2,3"}, 57 Destination: ".", 58 Concurrency: 5, 59 }, 60 }, 61 { 62 name: "version and destination", 63 args: "v1.2.3 -D tmp/assets", 64 isTTY: true, 65 want: DownloadOptions{ 66 TagName: "v1.2.3", 67 FilePatterns: []string(nil), 68 Destination: "tmp/assets", 69 Concurrency: 5, 70 }, 71 }, 72 { 73 name: "download latest", 74 args: "-p *", 75 isTTY: true, 76 want: DownloadOptions{ 77 TagName: "", 78 FilePatterns: []string{"*"}, 79 Destination: ".", 80 Concurrency: 5, 81 }, 82 }, 83 { 84 name: "no arguments", 85 args: "", 86 isTTY: true, 87 wantErr: "the '--pattern' flag is required when downloading the latest release", 88 }, 89 } 90 for _, tt := range tests { 91 t.Run(tt.name, func(t *testing.T) { 92 io, _, _, _ := iostreams.Test() 93 io.SetStdoutTTY(tt.isTTY) 94 io.SetStdinTTY(tt.isTTY) 95 io.SetStderrTTY(tt.isTTY) 96 97 f := &cmdutil.Factory{ 98 IOStreams: io, 99 } 100 101 var opts *DownloadOptions 102 cmd := NewCmdDownload(f, func(o *DownloadOptions) error { 103 opts = o 104 return nil 105 }) 106 cmd.PersistentFlags().StringP("repo", "R", "", "") 107 108 argv, err := shlex.Split(tt.args) 109 require.NoError(t, err) 110 cmd.SetArgs(argv) 111 112 cmd.SetIn(&bytes.Buffer{}) 113 cmd.SetOut(ioutil.Discard) 114 cmd.SetErr(ioutil.Discard) 115 116 _, err = cmd.ExecuteC() 117 if tt.wantErr != "" { 118 require.EqualError(t, err, tt.wantErr) 119 return 120 } else { 121 require.NoError(t, err) 122 } 123 124 assert.Equal(t, tt.want.TagName, opts.TagName) 125 assert.Equal(t, tt.want.FilePatterns, opts.FilePatterns) 126 assert.Equal(t, tt.want.Destination, opts.Destination) 127 assert.Equal(t, tt.want.Concurrency, opts.Concurrency) 128 }) 129 } 130 } 131 132 func Test_downloadRun(t *testing.T) { 133 tests := []struct { 134 name string 135 isTTY bool 136 opts DownloadOptions 137 wantErr string 138 wantStdout string 139 wantStderr string 140 wantFiles []string 141 }{ 142 { 143 name: "download all assets", 144 isTTY: true, 145 opts: DownloadOptions{ 146 TagName: "v1.2.3", 147 Destination: ".", 148 Concurrency: 2, 149 }, 150 wantStdout: ``, 151 wantStderr: ``, 152 wantFiles: []string{ 153 "linux.tgz", 154 "windows-32bit.zip", 155 "windows-64bit.zip", 156 }, 157 }, 158 { 159 name: "download assets matching pattern into destination directory", 160 isTTY: true, 161 opts: DownloadOptions{ 162 TagName: "v1.2.3", 163 FilePatterns: []string{"windows-*.zip"}, 164 Destination: "tmp/assets", 165 Concurrency: 2, 166 }, 167 wantStdout: ``, 168 wantStderr: ``, 169 wantFiles: []string{ 170 "tmp/assets/windows-32bit.zip", 171 "tmp/assets/windows-64bit.zip", 172 }, 173 }, 174 { 175 name: "no match for pattern", 176 isTTY: true, 177 opts: DownloadOptions{ 178 TagName: "v1.2.3", 179 FilePatterns: []string{"linux*.zip"}, 180 Destination: ".", 181 Concurrency: 2, 182 }, 183 wantStdout: ``, 184 wantStderr: ``, 185 wantErr: "no assets match the file pattern", 186 }, 187 } 188 for _, tt := range tests { 189 t.Run(tt.name, func(t *testing.T) { 190 tempDir := t.TempDir() 191 tt.opts.Destination = filepath.Join(tempDir, tt.opts.Destination) 192 193 io, _, stdout, stderr := iostreams.Test() 194 io.SetStdoutTTY(tt.isTTY) 195 io.SetStdinTTY(tt.isTTY) 196 io.SetStderrTTY(tt.isTTY) 197 198 fakeHTTP := &httpmock.Registry{} 199 fakeHTTP.Register(httpmock.REST("GET", "repos/OWNER/REPO/releases/tags/v1.2.3"), httpmock.StringResponse(`{ 200 "assets": [ 201 { "name": "windows-32bit.zip", "size": 12, 202 "url": "https://api.github.com/assets/1234" }, 203 { "name": "windows-64bit.zip", "size": 34, 204 "url": "https://api.github.com/assets/3456" }, 205 { "name": "linux.tgz", "size": 56, 206 "url": "https://api.github.com/assets/5678" } 207 ] 208 }`)) 209 fakeHTTP.Register(httpmock.REST("GET", "assets/1234"), httpmock.StringResponse(`1234`)) 210 fakeHTTP.Register(httpmock.REST("GET", "assets/3456"), httpmock.StringResponse(`3456`)) 211 fakeHTTP.Register(httpmock.REST("GET", "assets/5678"), httpmock.StringResponse(`5678`)) 212 213 tt.opts.IO = io 214 tt.opts.HttpClient = func() (*http.Client, error) { 215 return &http.Client{Transport: fakeHTTP}, nil 216 } 217 tt.opts.BaseRepo = func() (ghrepo.Interface, error) { 218 return ghrepo.FromFullName("OWNER/REPO") 219 } 220 221 err := downloadRun(&tt.opts) 222 if tt.wantErr != "" { 223 require.EqualError(t, err, tt.wantErr) 224 return 225 } else { 226 require.NoError(t, err) 227 } 228 229 assert.Equal(t, "application/octet-stream", fakeHTTP.Requests[1].Header.Get("Accept")) 230 231 assert.Equal(t, tt.wantStdout, stdout.String()) 232 assert.Equal(t, tt.wantStderr, stderr.String()) 233 234 downloadedFiles, err := listFiles(tempDir) 235 require.NoError(t, err) 236 assert.Equal(t, tt.wantFiles, downloadedFiles) 237 }) 238 } 239 } 240 241 func listFiles(dir string) ([]string, error) { 242 var files []string 243 err := filepath.Walk(dir, func(p string, f os.FileInfo, err error) error { 244 if !f.IsDir() { 245 rp, err := filepath.Rel(dir, p) 246 if err != nil { 247 return err 248 } 249 files = append(files, filepath.ToSlash(rp)) 250 } 251 return err 252 }) 253 return files, err 254 }