github.com/loggregator/cli@v6.33.1-0.20180224010324-82334f081791+incompatible/cf/commands/curl_test.go (about) 1 package commands_test 2 3 import ( 4 "io/ioutil" 5 "os" 6 "path/filepath" 7 8 "code.cloudfoundry.org/cli/cf/api/apifakes" 9 "code.cloudfoundry.org/cli/cf/configuration/coreconfig" 10 "code.cloudfoundry.org/cli/cf/errors" 11 "code.cloudfoundry.org/cli/cf/requirements" 12 "code.cloudfoundry.org/cli/cf/requirements/requirementsfakes" 13 testcmd "code.cloudfoundry.org/cli/util/testhelpers/commands" 14 testconfig "code.cloudfoundry.org/cli/util/testhelpers/configuration" 15 testterm "code.cloudfoundry.org/cli/util/testhelpers/terminal" 16 "code.cloudfoundry.org/gofileutils/fileutils" 17 18 "code.cloudfoundry.org/cli/cf/commandregistry" 19 "code.cloudfoundry.org/cli/cf/trace" 20 . "code.cloudfoundry.org/cli/util/testhelpers/matchers" 21 . "github.com/onsi/ginkgo" 22 . "github.com/onsi/gomega" 23 ) 24 25 var _ = Describe("curl command", func() { 26 var ( 27 ui *testterm.FakeUI 28 config coreconfig.Repository 29 requirementsFactory *requirementsfakes.FakeFactory 30 curlRepo *apifakes.OldFakeCurlRepository 31 deps commandregistry.Dependency 32 ) 33 34 updateCommandDependency := func(pluginCall bool) { 35 deps.UI = ui 36 deps.RepoLocator = deps.RepoLocator.SetCurlRepository(curlRepo) 37 deps.Config = config 38 commandregistry.Commands.SetCommand(commandregistry.Commands.FindCommand("curl").SetDependency(deps, pluginCall)) 39 } 40 41 BeforeEach(func() { 42 ui = &testterm.FakeUI{} 43 config = testconfig.NewRepository() 44 requirementsFactory = new(requirementsfakes.FakeFactory) 45 requirementsFactory.NewAPIEndpointRequirementReturns(requirements.Passing{}) 46 curlRepo = new(apifakes.OldFakeCurlRepository) 47 48 trace.LoggingToStdout = false 49 }) 50 51 runCurlWithInputs := func(args []string) bool { 52 return testcmd.RunCLICommand("curl", args, requirementsFactory, updateCommandDependency, false, ui) 53 } 54 55 runCurlAsPluginWithInputs := func(args []string) bool { 56 return testcmd.RunCLICommand("curl", args, requirementsFactory, updateCommandDependency, true, ui) 57 } 58 59 It("fails with usage when not given enough input", func() { 60 runCurlWithInputs([]string{}) 61 Expect(ui.Outputs()).To(ContainSubstrings( 62 []string{"Incorrect Usage", "An argument is missing or not correctly enclosed"}, 63 )) 64 }) 65 66 Context("requirements", func() { 67 Context("when no api is set", func() { 68 BeforeEach(func() { 69 requirementsFactory.NewAPIEndpointRequirementReturns(requirements.Failing{Message: "no api set"}) 70 }) 71 72 It("fails", func() { 73 Expect(runCurlWithInputs([]string{"/foo"})).To(BeFalse()) 74 }) 75 }) 76 77 Context("when api is set", func() { 78 BeforeEach(func() { 79 requirementsFactory.NewAPIEndpointRequirementReturns(requirements.Passing{}) 80 }) 81 82 It("passes", func() { 83 Expect(runCurlWithInputs([]string{"/foo"})).To(BeTrue()) 84 }) 85 }) 86 }) 87 88 It("makes a get request given an endpoint", func() { 89 curlRepo.ResponseHeader = "Content-Size:1024" 90 curlRepo.ResponseBody = "response for get" 91 runCurlWithInputs([]string{"/foo"}) 92 93 Expect(curlRepo.Method).To(Equal("")) 94 Expect(curlRepo.Path).To(Equal("/foo")) 95 Expect(ui.Outputs()).To(ContainSubstrings([]string{"response for get"})) 96 Expect(ui.Outputs()).ToNot(ContainSubstrings( 97 []string{"FAILED"}, 98 []string{"Content-Size:1024"}, 99 )) 100 }) 101 102 Context("when the --output flag is provided", func() { 103 It("saves the body of the response to the given filepath if it exists", func() { 104 fileutils.TempFile("poor-mans-pipe", func(tempFile *os.File, err error) { 105 Expect(err).ToNot(HaveOccurred()) 106 curlRepo.ResponseBody = "hai" 107 108 runCurlWithInputs([]string{"--output", tempFile.Name(), "/foo"}) 109 contents, err := ioutil.ReadAll(tempFile) 110 Expect(err).ToNot(HaveOccurred()) 111 Expect(string(contents)).To(Equal("hai")) 112 }) 113 }) 114 115 It("saves the body of the response to the given filepath if it doesn't exists", func() { 116 fileutils.TempDir("poor-mans-dir", func(tmpDir string, err error) { 117 Expect(err).ToNot(HaveOccurred()) 118 curlRepo.ResponseBody = "hai" 119 120 filePath := filepath.Join(tmpDir, "subdir1", "banana.txt") 121 runCurlWithInputs([]string{"--output", filePath, "/foo"}) 122 123 file, err := os.Open(filePath) 124 Expect(err).ToNot(HaveOccurred()) 125 126 contents, err := ioutil.ReadAll(file) 127 Expect(err).ToNot(HaveOccurred()) 128 Expect(string(contents)).To(Equal("hai")) 129 }) 130 }) 131 }) 132 133 It("makes a post request given -X", func() { 134 runCurlWithInputs([]string{"-X", "post", "/foo"}) 135 136 Expect(curlRepo.Method).To(Equal("post")) 137 Expect(ui.Outputs()).ToNot(ContainSubstrings([]string{"FAILED"})) 138 }) 139 140 It("sends headers given -H", func() { 141 runCurlWithInputs([]string{"-H", "Content-Type:cat", "/foo"}) 142 143 Expect(curlRepo.Header).To(Equal("Content-Type:cat")) 144 Expect(ui.Outputs()).ToNot(ContainSubstrings([]string{"FAILED"})) 145 }) 146 147 It("sends multiple headers given multiple -H flags", func() { 148 runCurlWithInputs([]string{"-H", "Content-Type:cat", "-H", "Content-Length:12", "/foo"}) 149 150 Expect(curlRepo.Header).To(Equal("Content-Type:cat\nContent-Length:12")) 151 Expect(ui.Outputs()).ToNot(ContainSubstrings([]string{"FAILED"})) 152 }) 153 154 It("prints out the response headers given -i", func() { 155 curlRepo.ResponseHeader = "Content-Size:1024" 156 curlRepo.ResponseBody = "response for get" 157 runCurlWithInputs([]string{"-i", "/foo"}) 158 159 Expect(ui.Outputs()).To(ContainSubstrings( 160 []string{"Content-Size:1024"}, 161 []string{"response for get"}, 162 )) 163 Expect(ui.Outputs()).ToNot(ContainSubstrings([]string{"FAILED"})) 164 }) 165 166 Context("when -d is provided", func() { 167 It("sets the request body", func() { 168 runCurlWithInputs([]string{"-d", "body content to upload", "/foo"}) 169 170 Expect(curlRepo.Body).To(Equal("body content to upload")) 171 Expect(ui.Outputs()).ToNot(ContainSubstrings([]string{"FAILED"})) 172 }) 173 174 It("does not fail with empty string", func() { 175 runCurlWithInputs([]string{"/foo", "-d", ""}) 176 177 Expect(curlRepo.Body).To(Equal("")) 178 Expect(curlRepo.Method).To(Equal("POST")) 179 Expect(ui.Outputs()).NotTo(ContainSubstrings([]string{"FAILED"})) 180 }) 181 182 It("uses given http verb if -X is also provided", func() { 183 runCurlWithInputs([]string{"/foo", "-d", "some body", "-X", "PUT"}) 184 185 Expect(curlRepo.Body).To(Equal("some body")) 186 Expect(curlRepo.Method).To(Equal("PUT")) 187 Expect(ui.Outputs()).NotTo(ContainSubstrings([]string{"FAILED"})) 188 }) 189 190 It("sets the request body with an @-prefixed file", func() { 191 tempfile, err := ioutil.TempFile("", "get-data-test") 192 Expect(err).NotTo(HaveOccurred()) 193 defer os.RemoveAll(tempfile.Name()) 194 jsonData := `{"some":"json"}` 195 ioutil.WriteFile(tempfile.Name(), []byte(jsonData), os.ModePerm) 196 197 runCurlWithInputs([]string{"-d", "@" + tempfile.Name(), "/foo"}) 198 199 Expect(curlRepo.Body).To(Equal(`{"some":"json"}`)) 200 Expect(ui.Outputs()).ToNot(ContainSubstrings([]string{"FAILED"})) 201 }) 202 }) 203 204 It("does not print the response when verbose output is enabled", func() { 205 // This is to prevent the response from being printed twice 206 207 trace.LoggingToStdout = true 208 209 curlRepo.ResponseHeader = "Content-Size:1024" 210 curlRepo.ResponseBody = "response for get" 211 212 runCurlWithInputs([]string{"/foo"}) 213 214 Expect(ui.Outputs()).ToNot(ContainSubstrings([]string{"response for get"})) 215 }) 216 217 It("prints the response even when verbose output is enabled if in a plugin call", func() { 218 trace.LoggingToStdout = true 219 220 curlRepo.ResponseHeader = "Content-Size:1024" 221 curlRepo.ResponseBody = "response for get" 222 223 runCurlAsPluginWithInputs([]string{"/foo"}) 224 225 Expect(ui.Outputs()).To(ContainSubstrings([]string{"response for get"})) 226 }) 227 228 It("prints a failure message when the response is not success", func() { 229 curlRepo.Error = errors.New("ooops") 230 runCurlWithInputs([]string{"/foo"}) 231 232 Expect(ui.Outputs()).To(ContainSubstrings( 233 []string{"FAILED"}, 234 []string{"ooops"}, 235 )) 236 }) 237 238 Context("Whent the content type is JSON", func() { 239 BeforeEach(func() { 240 curlRepo.ResponseHeader = "Content-Type: application/json;charset=utf-8" 241 curlRepo.ResponseBody = `{"total_results":0,"total_pages":1,"prev_url":null,"next_url":null,"resources":[]}` 242 }) 243 244 It("pretty-prints the response body", func() { 245 runCurlWithInputs([]string{"/ugly-printed-json-endpoint"}) 246 247 Expect(ui.Outputs()).To(ContainSubstrings( 248 []string{"{"}, 249 []string{" \"total_results", "0"}, 250 []string{" \"total_pages", "1"}, 251 []string{" \"prev_url", "null"}, 252 []string{" \"next_url", "null"}, 253 []string{" \"resources", "[]"}, 254 []string{"}"}, 255 )) 256 }) 257 258 Context("But the body is not JSON", func() { 259 BeforeEach(func() { 260 curlRepo.ResponseBody = "FAIL: crumpets need MOAR butterz" 261 }) 262 263 It("regular-prints the response body", func() { 264 runCurlWithInputs([]string{"/whateverz"}) 265 266 Expect(ui.Outputs()).To(Equal([]string{"FAIL: crumpets need MOAR butterz"})) 267 }) 268 }) 269 }) 270 })