github.com/pivotal-cf/go-pivnet/v6@v6.0.2/user_groups_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  
     8  	"github.com/onsi/gomega/ghttp"
     9  	"github.com/pivotal-cf/go-pivnet/v6"
    10  	"github.com/pivotal-cf/go-pivnet/v6/logger"
    11  	"github.com/pivotal-cf/go-pivnet/v6/logger/loggerfakes"
    12  
    13  	. "github.com/onsi/ginkgo"
    14  	. "github.com/onsi/gomega"
    15  )
    16  
    17  var _ = Describe("PivnetClient - user groups", func() {
    18  	var (
    19  		server     *ghttp.Server
    20  		client     pivnet.Client
    21  		apiAddress string
    22  		userAgent  string
    23  
    24  		newClientConfig        pivnet.ClientConfig
    25  		fakeLogger             logger.Logger
    26  		fakeAccessTokenService *gopivnetfakes.FakeAccessTokenService
    27  
    28  		response           interface{}
    29  		responseStatusCode int
    30  	)
    31  
    32  	BeforeEach(func() {
    33  		server = ghttp.NewServer()
    34  		apiAddress = server.URL()
    35  		userAgent = "pivnet-resource/0.1.0 (some-url)"
    36  
    37  		fakeLogger = &loggerfakes.FakeLogger{}
    38  		fakeAccessTokenService = &gopivnetfakes.FakeAccessTokenService{}
    39  		newClientConfig = pivnet.ClientConfig{
    40  			Host:      apiAddress,
    41  			UserAgent: userAgent,
    42  		}
    43  		client = pivnet.NewClient(fakeAccessTokenService, newClientConfig, fakeLogger)
    44  
    45  		responseStatusCode = http.StatusOK
    46  	})
    47  
    48  	AfterEach(func() {
    49  		server.Close()
    50  	})
    51  
    52  	Describe("List", func() {
    53  		It("returns all user groups", func() {
    54  			response := `{"user_groups": [{"id":2,"name":"group 1"},{"id": 3, "name": "group 2"}]}`
    55  
    56  			server.AppendHandlers(
    57  				ghttp.CombineHandlers(
    58  					ghttp.VerifyRequest("GET", fmt.Sprintf("%s/user_groups", apiPrefix)),
    59  					ghttp.RespondWith(http.StatusOK, response),
    60  				),
    61  			)
    62  
    63  			userGroups, err := client.UserGroups.List()
    64  			Expect(err).NotTo(HaveOccurred())
    65  
    66  			Expect(userGroups).To(HaveLen(2))
    67  			Expect(userGroups[0].ID).To(Equal(2))
    68  			Expect(userGroups[1].ID).To(Equal(3))
    69  		})
    70  
    71  		Context("when the server responds with a non-2XX status code", func() {
    72  			var (
    73  				body []byte
    74  			)
    75  
    76  			BeforeEach(func() {
    77  				body = []byte(`{"message":"foo message"}`)
    78  			})
    79  
    80  			It("returns an error", func() {
    81  				server.AppendHandlers(
    82  					ghttp.CombineHandlers(
    83  						ghttp.VerifyRequest("GET", fmt.Sprintf("%s/user_groups", apiPrefix)),
    84  						ghttp.RespondWith(http.StatusTeapot, body),
    85  					),
    86  				)
    87  
    88  				_, err := client.UserGroups.List()
    89  				Expect(err.Error()).To(ContainSubstring("foo message"))
    90  			})
    91  		})
    92  
    93  		Context("when the json unmarshalling fails with error", func() {
    94  			It("forwards the error", func() {
    95  				server.AppendHandlers(
    96  					ghttp.CombineHandlers(
    97  						ghttp.VerifyRequest("GET", fmt.Sprintf("%s/user_groups", apiPrefix)),
    98  						ghttp.RespondWith(http.StatusTeapot, "%%%"),
    99  					),
   100  				)
   101  
   102  				_, err := client.UserGroups.List()
   103  				Expect(err).To(HaveOccurred())
   104  
   105  				Expect(err.Error()).To(ContainSubstring("invalid character"))
   106  			})
   107  		})
   108  	})
   109  
   110  	Describe("List for release", func() {
   111  		var (
   112  			releaseID int
   113  		)
   114  
   115  		BeforeEach(func() {
   116  			releaseID = 1234
   117  		})
   118  
   119  		It("returns the user groups for the product slug", func() {
   120  			response := `{"user_groups": [{"id":2,"name":"group 1"},{"id": 3, "name": "group 2"}]}`
   121  
   122  			server.AppendHandlers(
   123  				ghttp.CombineHandlers(
   124  					ghttp.VerifyRequest("GET", fmt.Sprintf("%s/products/banana/releases/%d/user_groups", apiPrefix, releaseID)),
   125  					ghttp.RespondWith(http.StatusOK, response),
   126  				),
   127  			)
   128  
   129  			userGroups, err := client.UserGroups.ListForRelease("banana", releaseID)
   130  			Expect(err).NotTo(HaveOccurred())
   131  
   132  			Expect(userGroups).To(HaveLen(2))
   133  			Expect(userGroups[0].ID).To(Equal(2))
   134  			Expect(userGroups[1].ID).To(Equal(3))
   135  		})
   136  
   137  		Context("when the server responds with a non-2XX status code", func() {
   138  			var (
   139  				body []byte
   140  			)
   141  
   142  			BeforeEach(func() {
   143  				body = []byte(`{"message":"foo message"}`)
   144  			})
   145  
   146  			It("returns an error", func() {
   147  				server.AppendHandlers(
   148  					ghttp.CombineHandlers(
   149  						ghttp.VerifyRequest("GET", fmt.Sprintf("%s/products/banana/releases/%d/user_groups", apiPrefix, releaseID)),
   150  						ghttp.RespondWith(http.StatusTeapot, body),
   151  					),
   152  				)
   153  
   154  				_, err := client.UserGroups.ListForRelease("banana", releaseID)
   155  				Expect(err.Error()).To(ContainSubstring("foo message"))
   156  			})
   157  		})
   158  
   159  		Context("when the json unmarshalling fails with error", func() {
   160  			It("forwards the error", func() {
   161  				server.AppendHandlers(
   162  					ghttp.CombineHandlers(
   163  						ghttp.VerifyRequest("GET", fmt.Sprintf("%s/products/banana/releases/%d/user_groups", apiPrefix, releaseID)),
   164  						ghttp.RespondWith(http.StatusTeapot, "%%%"),
   165  					),
   166  				)
   167  
   168  				_, err := client.UserGroups.ListForRelease("banana", releaseID)
   169  				Expect(err).To(HaveOccurred())
   170  
   171  				Expect(err.Error()).To(ContainSubstring("invalid character"))
   172  			})
   173  		})
   174  	})
   175  
   176  	Describe("Add To Release", func() {
   177  		var (
   178  			productSlug = "banana-slug"
   179  			releaseID   = 2345
   180  			userGroupID = 3456
   181  
   182  			expectedRequestBody = `{"user_group":{"id":3456}}`
   183  		)
   184  
   185  		Context("when the server responds with a 204 status code", func() {
   186  			It("returns without error", func() {
   187  				server.AppendHandlers(
   188  					ghttp.CombineHandlers(
   189  						ghttp.VerifyRequest("PATCH", fmt.Sprintf(
   190  							"%s/products/%s/releases/%d/add_user_group",
   191  							apiPrefix,
   192  							productSlug,
   193  							releaseID,
   194  						)),
   195  						ghttp.VerifyJSON(expectedRequestBody),
   196  						ghttp.RespondWith(http.StatusNoContent, nil),
   197  					),
   198  				)
   199  
   200  				err := client.UserGroups.AddToRelease(productSlug, releaseID, userGroupID)
   201  				Expect(err).NotTo(HaveOccurred())
   202  			})
   203  		})
   204  
   205  		Context("when the server responds with a non-204 status code", func() {
   206  			var (
   207  				body []byte
   208  			)
   209  
   210  			BeforeEach(func() {
   211  				body = []byte(`{"message":"foo message"}`)
   212  			})
   213  
   214  			It("returns an error", func() {
   215  				server.AppendHandlers(
   216  					ghttp.CombineHandlers(
   217  						ghttp.VerifyRequest("PATCH", fmt.Sprintf(
   218  							"%s/products/%s/releases/%d/add_user_group",
   219  							apiPrefix,
   220  							productSlug,
   221  							releaseID,
   222  						)),
   223  						ghttp.RespondWith(http.StatusTeapot, body),
   224  					),
   225  				)
   226  
   227  				err := client.UserGroups.AddToRelease(productSlug, releaseID, userGroupID)
   228  				Expect(err.Error()).To(ContainSubstring("foo message"))
   229  			})
   230  		})
   231  
   232  		Context("when the json unmarshalling fails with error", func() {
   233  			It("forwards the error", func() {
   234  				server.AppendHandlers(
   235  					ghttp.CombineHandlers(
   236  						ghttp.VerifyRequest("PATCH", fmt.Sprintf(
   237  							"%s/products/%s/releases/%d/add_user_group",
   238  							apiPrefix,
   239  							productSlug,
   240  							releaseID,
   241  						)),
   242  						ghttp.RespondWith(http.StatusTeapot, "%%%"),
   243  					),
   244  				)
   245  
   246  				err := client.UserGroups.AddToRelease(productSlug, releaseID, userGroupID)
   247  				Expect(err).To(HaveOccurred())
   248  
   249  				Expect(err.Error()).To(ContainSubstring("invalid character"))
   250  			})
   251  		})
   252  	})
   253  
   254  	Describe("Remove From Release", func() {
   255  		var (
   256  			productSlug = "banana-slug"
   257  			releaseID   = 2345
   258  			userGroupID = 3456
   259  
   260  			expectedRequestBody = `{"user_group":{"id":3456}}`
   261  		)
   262  
   263  		Context("when the server responds with a 204 status code", func() {
   264  			It("returns without error", func() {
   265  				server.AppendHandlers(
   266  					ghttp.CombineHandlers(
   267  						ghttp.VerifyRequest("PATCH", fmt.Sprintf(
   268  							"%s/products/%s/releases/%d/remove_user_group",
   269  							apiPrefix,
   270  							productSlug,
   271  							releaseID,
   272  						)),
   273  						ghttp.VerifyJSON(expectedRequestBody),
   274  						ghttp.RespondWith(http.StatusNoContent, nil),
   275  					),
   276  				)
   277  
   278  				err := client.UserGroups.RemoveFromRelease(productSlug, releaseID, userGroupID)
   279  				Expect(err).NotTo(HaveOccurred())
   280  			})
   281  		})
   282  
   283  		Context("when the server responds with a non-204 status code", func() {
   284  			var (
   285  				body []byte
   286  			)
   287  
   288  			BeforeEach(func() {
   289  				body = []byte(`{"message":"foo message"}`)
   290  			})
   291  
   292  			It("returns an error", func() {
   293  				server.AppendHandlers(
   294  					ghttp.CombineHandlers(
   295  						ghttp.VerifyRequest("PATCH", fmt.Sprintf(
   296  							"%s/products/%s/releases/%d/remove_user_group",
   297  							apiPrefix,
   298  							productSlug,
   299  							releaseID,
   300  						)),
   301  						ghttp.RespondWith(http.StatusTeapot, body),
   302  					),
   303  				)
   304  
   305  				err := client.UserGroups.RemoveFromRelease(productSlug, releaseID, userGroupID)
   306  				Expect(err.Error()).To(ContainSubstring("foo message"))
   307  			})
   308  		})
   309  
   310  		Context("when the json unmarshalling fails with error", func() {
   311  			It("forwards the error", func() {
   312  				server.AppendHandlers(
   313  					ghttp.CombineHandlers(
   314  						ghttp.VerifyRequest("PATCH", fmt.Sprintf(
   315  							"%s/products/%s/releases/%d/remove_user_group",
   316  							apiPrefix,
   317  							productSlug,
   318  							releaseID,
   319  						)),
   320  						ghttp.RespondWith(http.StatusTeapot, "%%%"),
   321  					),
   322  				)
   323  
   324  				err := client.UserGroups.RemoveFromRelease(productSlug, releaseID, userGroupID)
   325  				Expect(err).To(HaveOccurred())
   326  
   327  				Expect(err.Error()).To(ContainSubstring("invalid character"))
   328  			})
   329  		})
   330  	})
   331  
   332  	Describe("Get User Group", func() {
   333  		var (
   334  			userGroupID int
   335  		)
   336  
   337  		BeforeEach(func() {
   338  			userGroupID = 1234
   339  
   340  			response = pivnet.UserGroup{
   341  				ID:   userGroupID,
   342  				Name: "something",
   343  			}
   344  		})
   345  
   346  		JustBeforeEach(func() {
   347  			server.AppendHandlers(
   348  				ghttp.CombineHandlers(
   349  					ghttp.VerifyRequest(
   350  						"GET",
   351  						fmt.Sprintf(
   352  							"%s/user_groups/%d",
   353  							apiPrefix,
   354  							userGroupID,
   355  						),
   356  					),
   357  					ghttp.RespondWithJSONEncoded(responseStatusCode, response),
   358  				),
   359  			)
   360  		})
   361  
   362  		It("returns the user group without error", func() {
   363  			userGroup, err := client.UserGroups.Get(
   364  				userGroupID,
   365  			)
   366  			Expect(err).NotTo(HaveOccurred())
   367  
   368  			Expect(userGroup.ID).To(Equal(userGroupID))
   369  			Expect(userGroup.Name).To(Equal("something"))
   370  		})
   371  
   372  		Context("when the server responds with a non-2XX status code", func() {
   373  			var (
   374  				body []byte
   375  			)
   376  
   377  			BeforeEach(func() {
   378  				response = pivnetErr{Message: "foo message"}
   379  				responseStatusCode = http.StatusTeapot
   380  			})
   381  
   382  			It("returns an error", func() {
   383  				server.AppendHandlers(
   384  					ghttp.CombineHandlers(
   385  						ghttp.VerifyRequest(
   386  							"GET",
   387  							fmt.Sprintf(
   388  								"%s/user_groups/%d",
   389  								apiPrefix,
   390  								userGroupID,
   391  							),
   392  						),
   393  						ghttp.RespondWith(responseStatusCode, body),
   394  					),
   395  				)
   396  
   397  				_, err := client.UserGroups.Get(
   398  					userGroupID,
   399  				)
   400  				Expect(err).To(HaveOccurred())
   401  
   402  				Expect(err.Error()).To(ContainSubstring("foo message"))
   403  			})
   404  		})
   405  
   406  		Context("when the json unmarshalling fails with error", func() {
   407  			BeforeEach(func() {
   408  				response = "%%%"
   409  			})
   410  
   411  			It("forwards the error", func() {
   412  				_, err := client.UserGroups.Get(userGroupID)
   413  				Expect(err).To(HaveOccurred())
   414  
   415  				Expect(err.Error()).To(ContainSubstring("json"))
   416  			})
   417  		})
   418  	})
   419  
   420  	Describe("Create", func() {
   421  		var (
   422  			name        string
   423  			description string
   424  			members     []string
   425  
   426  			expectedRequestBody string
   427  
   428  			returnedUserGroup pivnet.UserGroup
   429  		)
   430  
   431  		BeforeEach(func() {
   432  			name = "some name"
   433  			description = "some description"
   434  			members = []string{"some member"}
   435  
   436  			expectedRequestBody = fmt.Sprintf(
   437  				`{"user_group":{"name":"%s","description":"%s","members":["some member"]}}`,
   438  				name,
   439  				description,
   440  			)
   441  		})
   442  
   443  		JustBeforeEach(func() {
   444  			returnedUserGroup = pivnet.UserGroup{
   445  				ID:          1234,
   446  				Name:        name,
   447  				Description: description,
   448  				Members:     members,
   449  			}
   450  		})
   451  
   452  		It("creates new user group without error", func() {
   453  			server.AppendHandlers(
   454  				ghttp.CombineHandlers(
   455  					ghttp.VerifyRequest("POST", fmt.Sprintf(
   456  						"%s/user_groups",
   457  						apiPrefix,
   458  					)),
   459  					ghttp.VerifyJSON(expectedRequestBody),
   460  					ghttp.RespondWithJSONEncoded(http.StatusCreated, returnedUserGroup),
   461  				),
   462  			)
   463  
   464  			userGroup, err := client.UserGroups.Create(name, description, members)
   465  			Expect(err).NotTo(HaveOccurred())
   466  
   467  			Expect(userGroup.ID).To(Equal(returnedUserGroup.ID))
   468  			Expect(userGroup.Name).To(Equal(name))
   469  			Expect(userGroup.Description).To(Equal(description))
   470  		})
   471  
   472  		Context("when members is nil", func() {
   473  			BeforeEach(func() {
   474  				members = nil
   475  
   476  				expectedRequestBody = fmt.Sprintf(
   477  					`{"user_group":{"name":"%s","description":"%s","members":[]}}`,
   478  					name,
   479  					description,
   480  				)
   481  			})
   482  
   483  			It("successfully sends empty array in json body", func() {
   484  				server.AppendHandlers(
   485  					ghttp.CombineHandlers(
   486  						ghttp.VerifyRequest("POST", fmt.Sprintf(
   487  							"%s/user_groups",
   488  							apiPrefix,
   489  						)),
   490  						ghttp.VerifyJSON(expectedRequestBody),
   491  						ghttp.RespondWithJSONEncoded(http.StatusCreated, returnedUserGroup),
   492  					),
   493  				)
   494  
   495  				_, err := client.UserGroups.Create(name, description, members)
   496  				Expect(err).NotTo(HaveOccurred())
   497  			})
   498  		})
   499  
   500  		Context("when the server responds with a non-201 status code", func() {
   501  			var (
   502  				body []byte
   503  			)
   504  
   505  			BeforeEach(func() {
   506  				body = []byte(`{"message":"foo message"}`)
   507  			})
   508  
   509  			It("returns an error", func() {
   510  				server.AppendHandlers(
   511  					ghttp.CombineHandlers(
   512  						ghttp.VerifyRequest("POST", fmt.Sprintf(
   513  							"%s/user_groups",
   514  							apiPrefix,
   515  						)),
   516  						ghttp.RespondWith(http.StatusTeapot, body),
   517  					),
   518  				)
   519  
   520  				_, err := client.UserGroups.Create(name, description, members)
   521  
   522  				Expect(err.Error()).To(ContainSubstring("foo message"))
   523  			})
   524  		})
   525  
   526  		Context("when the json unmarshalling fails with error", func() {
   527  			It("forwards the error", func() {
   528  				server.AppendHandlers(
   529  					ghttp.CombineHandlers(
   530  						ghttp.VerifyRequest("POST", fmt.Sprintf(
   531  							"%s/user_groups",
   532  							apiPrefix,
   533  						)),
   534  						ghttp.RespondWith(http.StatusTeapot, "%%%"),
   535  					),
   536  				)
   537  
   538  				_, err := client.UserGroups.Create(name, description, members)
   539  				Expect(err).To(HaveOccurred())
   540  
   541  				Expect(err.Error()).To(ContainSubstring("invalid character"))
   542  			})
   543  		})
   544  	})
   545  
   546  	Describe("Update", func() {
   547  		var (
   548  			userGroup pivnet.UserGroup
   549  
   550  			expectedRequestBody string
   551  
   552  			response pivnet.UpdateUserGroupResponse
   553  		)
   554  
   555  		BeforeEach(func() {
   556  			userGroup = pivnet.UserGroup{
   557  				ID:          1234,
   558  				Name:        "some name",
   559  				Description: "some description",
   560  			}
   561  
   562  			expectedRequestBody = fmt.Sprintf(
   563  				`{"user_group":{"name":"%s","description":"%s"}}`,
   564  				userGroup.Name,
   565  				userGroup.Description,
   566  			)
   567  
   568  			response = pivnet.UpdateUserGroupResponse{userGroup}
   569  		})
   570  
   571  		It("returns without error", func() {
   572  			server.AppendHandlers(
   573  				ghttp.CombineHandlers(
   574  					ghttp.VerifyRequest("PATCH", fmt.Sprintf(
   575  						"%s/user_groups/%d",
   576  						apiPrefix,
   577  						userGroup.ID,
   578  					)),
   579  					ghttp.VerifyJSON(expectedRequestBody),
   580  					ghttp.RespondWithJSONEncoded(http.StatusOK, response),
   581  				),
   582  			)
   583  
   584  			returned, err := client.UserGroups.Update(userGroup)
   585  			Expect(err).NotTo(HaveOccurred())
   586  
   587  			Expect(returned.ID).To(Equal(userGroup.ID))
   588  			Expect(returned.Name).To(Equal(userGroup.Name))
   589  			Expect(returned.Description).To(Equal(userGroup.Description))
   590  		})
   591  
   592  		Context("when the server responds with a non-200 status code", func() {
   593  			var (
   594  				body []byte
   595  			)
   596  
   597  			BeforeEach(func() {
   598  				body = []byte(`{"message":"foo message"}`)
   599  			})
   600  
   601  			It("returns an error", func() {
   602  				server.AppendHandlers(
   603  					ghttp.CombineHandlers(
   604  						ghttp.VerifyRequest("PATCH", fmt.Sprintf(
   605  							"%s/user_groups/%d",
   606  							apiPrefix,
   607  							userGroup.ID,
   608  						)),
   609  						ghttp.RespondWith(http.StatusTeapot, body),
   610  					),
   611  				)
   612  
   613  				_, err := client.UserGroups.Update(userGroup)
   614  
   615  				Expect(err.Error()).To(ContainSubstring("foo message"))
   616  			})
   617  		})
   618  
   619  		Context("when the json unmarshalling fails with error", func() {
   620  			It("forwards the error", func() {
   621  				server.AppendHandlers(
   622  					ghttp.CombineHandlers(
   623  						ghttp.VerifyRequest("PATCH", fmt.Sprintf(
   624  							"%s/user_groups/%d",
   625  							apiPrefix,
   626  							userGroup.ID,
   627  						)),
   628  						ghttp.RespondWith(http.StatusTeapot, "%%%"),
   629  					),
   630  				)
   631  
   632  				_, err := client.UserGroups.Update(userGroup)
   633  				Expect(err).To(HaveOccurred())
   634  
   635  				Expect(err.Error()).To(ContainSubstring("invalid character"))
   636  			})
   637  		})
   638  	})
   639  
   640  	Describe("Delete", func() {
   641  		var (
   642  			userGroup pivnet.UserGroup
   643  		)
   644  
   645  		BeforeEach(func() {
   646  			userGroup = pivnet.UserGroup{
   647  				ID: 1234,
   648  			}
   649  		})
   650  
   651  		It("deletes the release", func() {
   652  			server.AppendHandlers(
   653  				ghttp.CombineHandlers(
   654  					ghttp.VerifyRequest("DELETE", fmt.Sprintf("%s/user_groups/%d", apiPrefix, userGroup.ID)),
   655  					ghttp.RespondWith(http.StatusNoContent, nil),
   656  				),
   657  			)
   658  
   659  			err := client.UserGroups.Delete(userGroup.ID)
   660  			Expect(err).NotTo(HaveOccurred())
   661  		})
   662  
   663  		Context("when the server responds with a non-204 status code", func() {
   664  			var (
   665  				body []byte
   666  			)
   667  
   668  			BeforeEach(func() {
   669  				body = []byte(`{"message":"foo message"}`)
   670  			})
   671  
   672  			It("returns an error", func() {
   673  				server.AppendHandlers(
   674  					ghttp.CombineHandlers(
   675  						ghttp.VerifyRequest("DELETE", fmt.Sprintf("%s/user_groups/%d", apiPrefix, userGroup.ID)),
   676  						ghttp.RespondWith(http.StatusTeapot, body),
   677  					),
   678  				)
   679  
   680  				err := client.UserGroups.Delete(userGroup.ID)
   681  				Expect(err.Error()).To(ContainSubstring("foo message"))
   682  			})
   683  		})
   684  
   685  		Context("when the json unmarshalling fails with error", func() {
   686  			It("forwards the error", func() {
   687  				server.AppendHandlers(
   688  					ghttp.CombineHandlers(
   689  						ghttp.VerifyRequest("DELETE", fmt.Sprintf("%s/user_groups/%d", apiPrefix, userGroup.ID)),
   690  						ghttp.RespondWith(http.StatusTeapot, "%%%"),
   691  					),
   692  				)
   693  
   694  				err := client.UserGroups.Delete(userGroup.ID)
   695  				Expect(err).To(HaveOccurred())
   696  
   697  				Expect(err.Error()).To(ContainSubstring("invalid character"))
   698  			})
   699  		})
   700  	})
   701  
   702  	Describe("AddMemberToGroup", func() {
   703  		var (
   704  			memberEmailAddress string
   705  			admin              bool
   706  			userGroup          pivnet.UserGroup
   707  
   708  			expectedRequestBody string
   709  
   710  			response pivnet.UpdateUserGroupResponse
   711  		)
   712  
   713  		BeforeEach(func() {
   714  			memberEmailAddress = "some email address"
   715  			admin = true
   716  
   717  			userGroup = pivnet.UserGroup{
   718  				ID:          1234,
   719  				Name:        "some name",
   720  				Description: "some description",
   721  			}
   722  
   723  			expectedRequestBody = fmt.Sprintf(
   724  				`{"member":{"email":"%s","admin":true}}`,
   725  				memberEmailAddress,
   726  			)
   727  
   728  			response = pivnet.UpdateUserGroupResponse{userGroup}
   729  		})
   730  
   731  		It("returns without error", func() {
   732  			server.AppendHandlers(
   733  				ghttp.CombineHandlers(
   734  					ghttp.VerifyRequest("PATCH", fmt.Sprintf(
   735  						"%s/user_groups/%d/add_member",
   736  						apiPrefix,
   737  						userGroup.ID,
   738  					)),
   739  					ghttp.VerifyJSON(expectedRequestBody),
   740  					ghttp.RespondWithJSONEncoded(http.StatusOK, response),
   741  				),
   742  			)
   743  
   744  			returned, err := client.UserGroups.AddMemberToGroup(
   745  				userGroup.ID,
   746  				memberEmailAddress,
   747  				admin,
   748  			)
   749  			Expect(err).NotTo(HaveOccurred())
   750  
   751  			Expect(returned.ID).To(Equal(userGroup.ID))
   752  			Expect(returned.Name).To(Equal(userGroup.Name))
   753  			Expect(returned.Description).To(Equal(userGroup.Description))
   754  		})
   755  
   756  		Context("when the server responds with a non-200 status code", func() {
   757  			var (
   758  				body []byte
   759  			)
   760  
   761  			BeforeEach(func() {
   762  				body = []byte(`{"message":"foo message"}`)
   763  			})
   764  
   765  			It("returns an error", func() {
   766  				server.AppendHandlers(
   767  					ghttp.CombineHandlers(
   768  						ghttp.VerifyRequest("PATCH", fmt.Sprintf(
   769  							"%s/user_groups/%d/add_member",
   770  							apiPrefix,
   771  							userGroup.ID,
   772  						)),
   773  						ghttp.RespondWith(http.StatusTeapot, body),
   774  					),
   775  				)
   776  
   777  				_, err := client.UserGroups.AddMemberToGroup(
   778  					userGroup.ID,
   779  					memberEmailAddress,
   780  					admin,
   781  				)
   782  
   783  				Expect(err.Error()).To(ContainSubstring("foo message"))
   784  			})
   785  		})
   786  
   787  		Context("when the json unmarshalling fails with error", func() {
   788  			It("forwards the error", func() {
   789  				server.AppendHandlers(
   790  					ghttp.CombineHandlers(
   791  						ghttp.VerifyRequest("PATCH", fmt.Sprintf(
   792  							"%s/user_groups/%d/add_member",
   793  							apiPrefix,
   794  							userGroup.ID,
   795  						)),
   796  						ghttp.RespondWith(http.StatusTeapot, "%%%"),
   797  					),
   798  				)
   799  
   800  				_, err := client.UserGroups.AddMemberToGroup(
   801  					userGroup.ID,
   802  					memberEmailAddress,
   803  					admin,
   804  				)
   805  				Expect(err).To(HaveOccurred())
   806  
   807  				Expect(err.Error()).To(ContainSubstring("invalid character"))
   808  			})
   809  		})
   810  	})
   811  
   812  	Describe("RemoveMemberFromGroup", func() {
   813  		var (
   814  			memberEmailAddress string
   815  			userGroup          pivnet.UserGroup
   816  
   817  			expectedRequestBody string
   818  
   819  			response pivnet.UpdateUserGroupResponse
   820  		)
   821  
   822  		BeforeEach(func() {
   823  			memberEmailAddress = "some email address"
   824  
   825  			userGroup = pivnet.UserGroup{
   826  				ID:          1234,
   827  				Name:        "some name",
   828  				Description: "some description",
   829  			}
   830  
   831  			expectedRequestBody = fmt.Sprintf(
   832  				`{"member":{"email":"%s"}}`,
   833  				memberEmailAddress,
   834  			)
   835  
   836  			response = pivnet.UpdateUserGroupResponse{userGroup}
   837  		})
   838  
   839  		It("returns without error", func() {
   840  			server.AppendHandlers(
   841  				ghttp.CombineHandlers(
   842  					ghttp.VerifyRequest("PATCH", fmt.Sprintf(
   843  						"%s/user_groups/%d/remove_member",
   844  						apiPrefix,
   845  						userGroup.ID,
   846  					)),
   847  					ghttp.VerifyJSON(expectedRequestBody),
   848  					ghttp.RespondWithJSONEncoded(http.StatusOK, response),
   849  				),
   850  			)
   851  
   852  			returned, err := client.UserGroups.RemoveMemberFromGroup(userGroup.ID, memberEmailAddress)
   853  			Expect(err).NotTo(HaveOccurred())
   854  
   855  			Expect(returned.ID).To(Equal(userGroup.ID))
   856  			Expect(returned.Name).To(Equal(userGroup.Name))
   857  			Expect(returned.Description).To(Equal(userGroup.Description))
   858  		})
   859  
   860  		Context("when the server responds with a non-200 status code", func() {
   861  			var (
   862  				body []byte
   863  			)
   864  
   865  			BeforeEach(func() {
   866  				body = []byte(`{"message":"foo message"}`)
   867  			})
   868  
   869  			It("returns an error", func() {
   870  				server.AppendHandlers(
   871  					ghttp.CombineHandlers(
   872  						ghttp.VerifyRequest("PATCH", fmt.Sprintf(
   873  							"%s/user_groups/%d/remove_member",
   874  							apiPrefix,
   875  							userGroup.ID,
   876  						)),
   877  						ghttp.RespondWith(http.StatusTeapot, body),
   878  					),
   879  				)
   880  
   881  				_, err := client.UserGroups.RemoveMemberFromGroup(userGroup.ID, memberEmailAddress)
   882  
   883  				Expect(err.Error()).To(ContainSubstring("foo message"))
   884  			})
   885  		})
   886  
   887  		Context("when the json unmarshalling fails with error", func() {
   888  			It("forwards the error", func() {
   889  				server.AppendHandlers(
   890  					ghttp.CombineHandlers(
   891  						ghttp.VerifyRequest("PATCH", fmt.Sprintf(
   892  							"%s/user_groups/%d/remove_member",
   893  							apiPrefix,
   894  							userGroup.ID,
   895  						)),
   896  						ghttp.RespondWith(http.StatusTeapot, "%%%"),
   897  					),
   898  				)
   899  
   900  				_, err := client.UserGroups.RemoveMemberFromGroup(userGroup.ID, memberEmailAddress)
   901  				Expect(err).To(HaveOccurred())
   902  
   903  				Expect(err.Error()).To(ContainSubstring("invalid character"))
   904  			})
   905  		})
   906  	})
   907  })