github.com/pivotal-cf/go-pivnet/v6@v6.0.2/releases_test.go (about) 1 package pivnet_test 2 3 import ( 4 "fmt" 5 "github.com/pivotal-cf/go-pivnet/v6/go-pivnetfakes" 6 "net/http" 7 "time" 8 9 "github.com/onsi/gomega/ghttp" 10 "github.com/pivotal-cf/go-pivnet/v6" 11 "github.com/pivotal-cf/go-pivnet/v6/logger" 12 "github.com/pivotal-cf/go-pivnet/v6/logger/loggerfakes" 13 14 . "github.com/onsi/ginkgo" 15 . "github.com/onsi/gomega" 16 ) 17 18 var _ = Describe("PivnetClient - product files", func() { 19 var ( 20 server *ghttp.Server 21 client pivnet.Client 22 apiAddress string 23 userAgent string 24 25 newClientConfig pivnet.ClientConfig 26 fakeLogger logger.Logger 27 fakeAccessTokenService *gopivnetfakes.FakeAccessTokenService 28 ) 29 30 BeforeEach(func() { 31 server = ghttp.NewServer() 32 apiAddress = server.URL() 33 userAgent = "pivnet-resource/0.1.0 (some-url)" 34 35 fakeLogger = &loggerfakes.FakeLogger{} 36 fakeAccessTokenService = &gopivnetfakes.FakeAccessTokenService{} 37 newClientConfig = pivnet.ClientConfig{ 38 Host: apiAddress, 39 UserAgent: userAgent, 40 } 41 client = pivnet.NewClient(fakeAccessTokenService, newClientConfig, fakeLogger) 42 }) 43 44 AfterEach(func() { 45 server.Close() 46 }) 47 48 Describe("List", func() { 49 It("returns the releases for the product slug", func() { 50 response := `{"releases": [{"id":2,"version":"1.2.3"},{"id": 3, "version": "3.2.1", "_links": {"product_files": {"href":"https://banana.org/cookies/download"}}}]}` 51 52 server.AppendHandlers( 53 ghttp.CombineHandlers( 54 ghttp.VerifyRequest("GET", apiPrefix+"/products/banana/releases"), 55 ghttp.RespondWith(http.StatusOK, response), 56 ), 57 ) 58 59 releases, err := client.Releases.List("banana") 60 Expect(err).NotTo(HaveOccurred()) 61 Expect(releases).To(HaveLen(2)) 62 Expect(releases[0].ID).To(Equal(2)) 63 Expect(releases[1].ID).To(Equal(3)) 64 }) 65 66 Context("when specifying a limit", func() { 67 It("passes the limit to the API endpoint in the form of query params", func() { 68 response := `{"releases": [{"id": 3, "version": "3.2.1", "_links": {"product_files": {"href":"https://banana.org/cookies/download"}}}]}` 69 server.AppendHandlers( 70 ghttp.CombineHandlers( 71 ghttp.VerifyRequest("GET", apiPrefix+"/products/banana/releases", "limit=1"), 72 ghttp.RespondWith(http.StatusOK, response), 73 ), 74 ) 75 76 releases, err := client.Releases.List("banana", pivnet.QueryParameter{"limit", "1"}) 77 Expect(err).NotTo(HaveOccurred()) 78 Expect(releases).To(HaveLen(1)) 79 Expect(releases[0].ID).To(Equal(3)) 80 }) 81 }) 82 83 Context("when the server responds with a non-2XX status code", func() { 84 var ( 85 body []byte 86 ) 87 88 BeforeEach(func() { 89 body = []byte(`{"message":"foo message"}`) 90 }) 91 92 It("returns an error", func() { 93 server.AppendHandlers( 94 ghttp.CombineHandlers( 95 ghttp.VerifyRequest("GET", apiPrefix+"/products/banana/releases"), 96 ghttp.RespondWith(http.StatusTeapot, body), 97 ), 98 ) 99 100 _, err := client.Releases.List("banana") 101 Expect(err.Error()).To(ContainSubstring("foo message")) 102 }) 103 }) 104 105 Context("when the json unmarshalling fails with error", func() { 106 It("forwards the error", func() { 107 server.AppendHandlers( 108 ghttp.CombineHandlers( 109 ghttp.VerifyRequest("GET", apiPrefix+"/products/banana/releases"), 110 ghttp.RespondWith(http.StatusTeapot, "%%%"), 111 ), 112 ) 113 114 _, err := client.Releases.List("banana") 115 Expect(err).To(HaveOccurred()) 116 117 Expect(err.Error()).To(ContainSubstring("invalid character")) 118 }) 119 }) 120 }) 121 122 Describe("Get", func() { 123 It("returns the release for the product slug and releaseID", func() { 124 response := `{"id": 3, "version": "3.2.1", "_links": {"product_files": {"href":"https://banana.org/cookies/download"}}}` 125 126 server.AppendHandlers( 127 ghttp.CombineHandlers( 128 ghttp.VerifyRequest("GET", apiPrefix+"/products/banana/releases/3"), 129 ghttp.RespondWith(http.StatusOK, response), 130 ), 131 ) 132 133 release, err := client.Releases.Get("banana", 3) 134 Expect(err).NotTo(HaveOccurred()) 135 Expect(release.ID).To(Equal(3)) 136 }) 137 138 Context("when the server responds with a non-2XX status code", func() { 139 var ( 140 body []byte 141 ) 142 143 BeforeEach(func() { 144 body = []byte(`{"message":"foo message"}`) 145 }) 146 147 It("returns an error", func() { 148 server.AppendHandlers( 149 ghttp.CombineHandlers( 150 ghttp.VerifyRequest("GET", apiPrefix+"/products/banana/releases/3"), 151 ghttp.RespondWith(http.StatusTeapot, body), 152 ), 153 ) 154 155 _, err := client.Releases.Get("banana", 3) 156 Expect(err.Error()).To(ContainSubstring("foo message")) 157 }) 158 }) 159 160 Context("when the json unmarshalling fails with error", func() { 161 It("forwards the error", func() { 162 server.AppendHandlers( 163 ghttp.CombineHandlers( 164 ghttp.VerifyRequest("GET", apiPrefix+"/products/banana/releases/3"), 165 ghttp.RespondWith(http.StatusTeapot, "%%%"), 166 ), 167 ) 168 169 _, err := client.Releases.Get("banana", 3) 170 Expect(err).To(HaveOccurred()) 171 172 Expect(err.Error()).To(ContainSubstring("invalid character")) 173 }) 174 }) 175 }) 176 177 Describe("Create", func() { 178 var ( 179 releaseVersion string 180 createReleaseConfig pivnet.CreateReleaseConfig 181 ) 182 183 BeforeEach(func() { 184 releaseVersion = "1.2.3.4" 185 186 createReleaseConfig = pivnet.CreateReleaseConfig{ 187 EULASlug: "some_eula", 188 ReleaseType: "Not a real release", 189 Version: releaseVersion, 190 ProductSlug: productSlug, 191 } 192 }) 193 194 Context("when the config is valid", func() { 195 type requestBody struct { 196 Release pivnet.Release `json:"release"` 197 CopyMetadata bool `json:"copy_metadata"` 198 } 199 200 var ( 201 expectedReleaseDate string 202 expectedRequestBody requestBody 203 204 validResponse string 205 ) 206 207 BeforeEach(func() { 208 expectedReleaseDate = time.Now().Format("2006-01-02") 209 210 expectedRequestBody = requestBody{ 211 Release: pivnet.Release{ 212 Availability: "Admins Only", 213 OSSCompliant: "confirm", 214 ReleaseDate: expectedReleaseDate, 215 ReleaseType: pivnet.ReleaseType(createReleaseConfig.ReleaseType), 216 EULA: &pivnet.EULA{ 217 Slug: createReleaseConfig.EULASlug, 218 }, 219 Version: createReleaseConfig.Version, 220 }, 221 CopyMetadata: createReleaseConfig.CopyMetadata, 222 } 223 224 validResponse = `{"release": {"id": 3, "version": "1.2.3.4"}}` 225 }) 226 227 It("creates the release with the minimum required fields", func() { 228 server.AppendHandlers( 229 ghttp.CombineHandlers( 230 ghttp.VerifyRequest("POST", apiPrefix+"/products/"+productSlug+"/releases"), 231 ghttp.VerifyJSONRepresenting(&expectedRequestBody), 232 ghttp.RespondWith(http.StatusCreated, validResponse), 233 ), 234 ) 235 236 release, err := client.Releases.Create(createReleaseConfig) 237 Expect(err).NotTo(HaveOccurred()) 238 Expect(release.Version).To(Equal(releaseVersion)) 239 }) 240 241 Context("when the optional release date is present", func() { 242 var ( 243 releaseDate string 244 ) 245 246 BeforeEach(func() { 247 releaseDate = "2015-12-24" 248 249 createReleaseConfig.ReleaseDate = releaseDate 250 expectedRequestBody.Release.ReleaseDate = releaseDate 251 }) 252 253 It("creates the release with the release date field", func() { 254 server.AppendHandlers( 255 ghttp.CombineHandlers( 256 ghttp.VerifyRequest("POST", apiPrefix+"/products/"+productSlug+"/releases"), 257 ghttp.VerifyJSONRepresenting(&expectedRequestBody), 258 ghttp.RespondWith(http.StatusCreated, validResponse), 259 ), 260 ) 261 262 release, err := client.Releases.Create(createReleaseConfig) 263 Expect(err).NotTo(HaveOccurred()) 264 Expect(release.Version).To(Equal(releaseVersion)) 265 }) 266 }) 267 268 Describe("optional description field", func() { 269 var ( 270 description string 271 ) 272 273 Context("when the optional description field is present", func() { 274 BeforeEach(func() { 275 description = "some description" 276 277 createReleaseConfig.Description = description 278 expectedRequestBody.Release.Description = description 279 }) 280 281 It("creates the release with the description field", func() { 282 server.AppendHandlers( 283 ghttp.CombineHandlers( 284 ghttp.VerifyRequest("POST", apiPrefix+"/products/"+productSlug+"/releases"), 285 ghttp.VerifyJSONRepresenting(&expectedRequestBody), 286 ghttp.RespondWith(http.StatusCreated, validResponse), 287 ), 288 ) 289 290 release, err := client.Releases.Create(createReleaseConfig) 291 Expect(err).NotTo(HaveOccurred()) 292 Expect(release.Version).To(Equal(releaseVersion)) 293 }) 294 }) 295 296 Context("when the optional description field is not present", func() { 297 BeforeEach(func() { 298 description = "" 299 300 createReleaseConfig.Description = description 301 expectedRequestBody.Release.Description = description 302 }) 303 304 It("creates the release with an empty description field", func() { 305 server.AppendHandlers( 306 ghttp.CombineHandlers( 307 ghttp.VerifyRequest("POST", apiPrefix+"/products/"+productSlug+"/releases"), 308 ghttp.VerifyJSONRepresenting(&expectedRequestBody), 309 ghttp.RespondWith(http.StatusCreated, validResponse), 310 ), 311 ) 312 313 release, err := client.Releases.Create(createReleaseConfig) 314 Expect(err).NotTo(HaveOccurred()) 315 Expect(release.Version).To(Equal(releaseVersion)) 316 }) 317 }) 318 }) 319 320 Describe("optional release notes URL field", func() { 321 var ( 322 releaseNotesURL string 323 ) 324 325 Context("when the optional release notes URL field is present", func() { 326 BeforeEach(func() { 327 releaseNotesURL = "some releaseNotesURL" 328 329 createReleaseConfig.ReleaseNotesURL = releaseNotesURL 330 expectedRequestBody.Release.ReleaseNotesURL = releaseNotesURL 331 }) 332 333 It("creates the release with the release notes URL field", func() { 334 server.AppendHandlers( 335 ghttp.CombineHandlers( 336 ghttp.VerifyRequest("POST", apiPrefix+"/products/"+productSlug+"/releases"), 337 ghttp.VerifyJSONRepresenting(&expectedRequestBody), 338 ghttp.RespondWith(http.StatusCreated, validResponse), 339 ), 340 ) 341 342 release, err := client.Releases.Create(createReleaseConfig) 343 Expect(err).NotTo(HaveOccurred()) 344 Expect(release.Version).To(Equal(releaseVersion)) 345 }) 346 }) 347 348 Context("when the optional release notes URL field is not present", func() { 349 BeforeEach(func() { 350 releaseNotesURL = "" 351 352 createReleaseConfig.ReleaseNotesURL = releaseNotesURL 353 expectedRequestBody.Release.ReleaseNotesURL = releaseNotesURL 354 }) 355 356 It("creates the release with an empty release notes URL field", func() { 357 server.AppendHandlers( 358 ghttp.CombineHandlers( 359 ghttp.VerifyRequest("POST", apiPrefix+"/products/"+productSlug+"/releases"), 360 ghttp.VerifyJSONRepresenting(&expectedRequestBody), 361 ghttp.RespondWith(http.StatusCreated, validResponse), 362 ), 363 ) 364 365 release, err := client.Releases.Create(createReleaseConfig) 366 Expect(err).NotTo(HaveOccurred()) 367 Expect(release.Version).To(Equal(releaseVersion)) 368 }) 369 }) 370 }) 371 372 Describe("optional copy metadata config", func() { 373 Context("when the copy metadata config is not present", func() { 374 It("creates the release without copying metadata", func() { 375 server.AppendHandlers( 376 ghttp.CombineHandlers( 377 ghttp.VerifyRequest("POST", apiPrefix+"/products/"+productSlug+"/releases"), 378 ghttp.VerifyJSONRepresenting(&expectedRequestBody), 379 ghttp.RespondWith(http.StatusCreated, validResponse), 380 ), 381 ) 382 383 release, err := client.Releases.Create(createReleaseConfig) 384 Expect(err).NotTo(HaveOccurred()) 385 Expect(release.Version).To(Equal(releaseVersion)) 386 }) 387 }) 388 389 Context("when the copy metadata config is true", func() { 390 BeforeEach(func() { 391 createReleaseConfig.CopyMetadata = true 392 expectedRequestBody.CopyMetadata = true 393 }) 394 395 It("creates the release and copies the metadata", func() { 396 server.AppendHandlers( 397 ghttp.CombineHandlers( 398 ghttp.VerifyRequest("POST", apiPrefix+"/products/"+productSlug+"/releases"), 399 ghttp.VerifyJSONRepresenting(&expectedRequestBody), 400 ghttp.RespondWith(http.StatusCreated, validResponse), 401 ), 402 ) 403 404 release, err := client.Releases.Create(createReleaseConfig) 405 Expect(err).NotTo(HaveOccurred()) 406 Expect(release.Version).To(Equal(releaseVersion)) 407 }) 408 }) 409 }) 410 }) 411 412 Context("when the server responds with a non-201 status code", func() { 413 var ( 414 body []byte 415 ) 416 417 BeforeEach(func() { 418 body = []byte(`{"message":"foo message"}`) 419 }) 420 421 It("returns an error", func() { 422 server.AppendHandlers( 423 ghttp.CombineHandlers( 424 ghttp.VerifyRequest("POST", apiPrefix+"/products/"+productSlug+"/releases"), 425 ghttp.RespondWith(http.StatusTeapot, body), 426 ), 427 ) 428 429 _, err := client.Releases.Create(createReleaseConfig) 430 Expect(err.Error()).To(ContainSubstring("foo message")) 431 }) 432 }) 433 434 Context("when the json unmarshalling fails with error", func() { 435 It("forwards the error", func() { 436 server.AppendHandlers( 437 ghttp.CombineHandlers( 438 ghttp.VerifyRequest("POST", apiPrefix+"/products/"+productSlug+"/releases"), 439 ghttp.RespondWith(http.StatusTeapot, "%%%"), 440 ), 441 ) 442 443 _, err := client.Releases.Create(createReleaseConfig) 444 Expect(err).To(HaveOccurred()) 445 446 Expect(err.Error()).To(ContainSubstring("invalid character")) 447 }) 448 }) 449 }) 450 451 Describe("Update", func() { 452 It("submits the updated values for a release with OSS compliance", func() { 453 release := pivnet.Release{ 454 ID: 42, 455 Version: "1.2.3.4", 456 EULA: &pivnet.EULA{ 457 Slug: "some-eula", 458 ID: 15, 459 }, 460 } 461 462 patchURL := fmt.Sprintf("%s/products/%s/releases/%d", apiPrefix, "banana-slug", release.ID) 463 464 response := `{"release": {"id": 42, "version": "1.2.3.4"}}` 465 server.AppendHandlers( 466 ghttp.CombineHandlers( 467 ghttp.VerifyRequest("PATCH", patchURL), 468 ghttp.VerifyJSON(`{"release":{"id": 42, "version": "1.2.3.4", "eula":{"slug":"some-eula","id":15}, "oss_compliant":"confirm"}, "copy_metadata": false}`), 469 ghttp.RespondWith(http.StatusOK, response), 470 ), 471 ) 472 473 release, err := client.Releases.Update("banana-slug", release) 474 Expect(err).NotTo(HaveOccurred()) 475 Expect(release.Version).To(Equal("1.2.3.4")) 476 }) 477 478 Context("when the server responds with a non-200 status code", func() { 479 var ( 480 body []byte 481 ) 482 483 BeforeEach(func() { 484 body = []byte(`{"message":"foo message"}`) 485 }) 486 487 It("returns the error", func() { 488 release := pivnet.Release{ID: 111} 489 patchURL := fmt.Sprintf("%s/products/%s/releases/%d", apiPrefix, "banana-slug", release.ID) 490 491 server.AppendHandlers( 492 ghttp.CombineHandlers( 493 ghttp.VerifyRequest("PATCH", patchURL), 494 ghttp.RespondWith(http.StatusTeapot, body), 495 ), 496 ) 497 498 _, err := client.Releases.Update("banana-slug", release) 499 Expect(err.Error()).To(ContainSubstring("foo message")) 500 }) 501 }) 502 503 Context("when the json unmarshalling fails with error", func() { 504 It("forwards the error", func() { 505 release := pivnet.Release{ID: 111} 506 507 server.AppendHandlers( 508 ghttp.CombineHandlers( 509 ghttp.VerifyRequest("PATCH", fmt.Sprintf( 510 "%s/products/%s/releases/%d", 511 apiPrefix, 512 "banana-slug", 513 release.ID, 514 )), 515 ghttp.RespondWith(http.StatusTeapot, "%%%"), 516 ), 517 ) 518 519 _, err := client.Releases.Update("banana-slug", release) 520 Expect(err).To(HaveOccurred()) 521 522 Expect(err.Error()).To(ContainSubstring("invalid character")) 523 }) 524 }) 525 }) 526 527 Describe("Delete", func() { 528 var ( 529 release pivnet.Release 530 ) 531 532 BeforeEach(func() { 533 release = pivnet.Release{ 534 ID: 1234, 535 } 536 }) 537 538 It("deletes the release", func() { 539 server.AppendHandlers( 540 ghttp.CombineHandlers( 541 ghttp.VerifyRequest("DELETE", fmt.Sprintf("%s/products/banana/releases/%d", apiPrefix, release.ID)), 542 ghttp.RespondWith(http.StatusNoContent, nil), 543 ), 544 ) 545 546 err := client.Releases.Delete("banana", release) 547 Expect(err).NotTo(HaveOccurred()) 548 }) 549 550 Context("when the server responds with a non-204 status code", func() { 551 var ( 552 body []byte 553 ) 554 555 BeforeEach(func() { 556 body = []byte(`{"message":"foo message"}`) 557 }) 558 559 It("returns an error", func() { 560 server.AppendHandlers( 561 ghttp.CombineHandlers( 562 ghttp.VerifyRequest("DELETE", fmt.Sprintf("%s/products/banana/releases/%d", apiPrefix, release.ID)), 563 ghttp.RespondWith(http.StatusTeapot, body), 564 ), 565 ) 566 567 err := client.Releases.Delete("banana", release) 568 Expect(err.Error()).To(ContainSubstring("foo message")) 569 }) 570 }) 571 572 Context("when the json unmarshalling fails with error", func() { 573 It("forwards the error", func() { 574 release := pivnet.Release{ID: 111} 575 576 server.AppendHandlers( 577 ghttp.CombineHandlers( 578 ghttp.VerifyRequest("DELETE", fmt.Sprintf("%s/products/banana/releases/%d", apiPrefix, release.ID)), 579 ghttp.RespondWith(http.StatusTeapot, "%%%"), 580 ), 581 ) 582 583 err := client.Releases.Delete("banana", release) 584 Expect(err).To(HaveOccurred()) 585 586 Expect(err.Error()).To(ContainSubstring("invalid character")) 587 }) 588 }) 589 }) 590 })