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  })