Repository: nukosuke/go-zendesk (go)

Issue:
Add support for brand CRUD
https://developer.zendesk.com/rest_api/docs/support/brands

- [x] Create #62 
- [x] Read
- [x] Update
- [x] Delete

Pull request description:
Add support for brand Get/Update/Delete
Close #61 
- [x] Impl get/update/delete
- [x] test
- [x] Regenerate mock client

Patch:
diff --git a/fixture/GET/brand.json b/fixture/GET/brand.json
new file mode 100644
index 0000000..2a8e9ac
--- /dev/null
+++ b/fixture/GET/brand.json
@@ -0,0 +1,53 @@
+{
+  "brand":
+  {
+    "url": "https://example.zendesk.com/api/v2/brands/360002143133.json",
+    "id": 360002143133,
+    "name": "brand2",
+    "brand_url": "https://example-brand2.zendesk.com",
+    "subdomain": "example-brand2",
+    "has_help_center": false,
+    "help_center_state": "disabled",
+    "active": true,
+    "default": false,
+    "is_deleted": false,
+    "logo": {
+      "url": "https://example.zendesk.com/api/v2/attachments/360000142813.json",
+      "id": 360000142813,
+      "file_name": "zendesk_logo.jpeg",
+      "content_url": "https://example.zendesk.com/system/brands/3600/0014/2813/zendesk_logo.jpeg",
+      "mapped_content_url": "https://example.zendesk.com/system/brands/3600/0014/2813/zendesk_logo.jpeg",
+      "content_type": "image/jpeg",
+      "size": 4060,
+      "width": 80,
+      "height": 80,
+      "inline": false,
+      "thumbnails": [
+        {
+          "url": "https://example.zendesk.com/api/v2/attachments/360000142833.json",
+          "id": 360000142833,
+          "file_name": "zendesk_logo_thumb.jpeg",
+          "content_url": "https://example.zendesk.com/system/brands/3600/0014/2813/zendesk_logo_thumb.jpeg",
+          "mapped_content_url": "https://example.zendesk.com/system/brands/3600/0014/2813/zendesk_logo_thumb.jpeg",
+          "content_type": "image/jpeg",
+          "size": 2040,
+          "width": 32,
+          "height": 32,
+          "inline": false
+        },
+        {
+          "url": "https://example.zendesk.com/api/v2/attachments/360000142853.json",
+          "id": 360000142853,
+          "file_name": "zendesk_logo_small.jpeg",
+          "content_url": "https://example.zendesk.com/system/brands/3600/0014/2813/zendesk_logo_small.jpeg",
+          "mapped_content_url": "https://example.zendesk.com/system/brands/3600/0014/2813/zendesk_logo_small.jpeg",
+          "content_type": "image/jpeg",
+          "size": 1322,
+          "width": 24,
+          "height": 24,
+          "inline": false
+        }
+      ]
+    }
+  }
+}
diff --git a/fixture/PUT/brands.json b/fixture/PUT/brands.json
new file mode 100644
index 0000000..2a8e9ac
--- /dev/null
+++ b/fixture/PUT/brands.json
@@ -0,0 +1,53 @@
+{
+  "brand":
+  {
+    "url": "https://example.zendesk.com/api/v2/brands/360002143133.json",
+    "id": 360002143133,
+    "name": "brand2",
+    "brand_url": "https://example-brand2.zendesk.com",
+    "subdomain": "example-brand2",
+    "has_help_center": false,
+    "help_center_state": "disabled",
+    "active": true,
+    "default": false,
+    "is_deleted": false,
+    "logo": {
+      "url": "https://example.zendesk.com/api/v2/attachments/360000142813.json",
+      "id": 360000142813,
+      "file_name": "zendesk_logo.jpeg",
+      "content_url": "https://example.zendesk.com/system/brands/3600/0014/2813/zendesk_logo.jpeg",
+      "mapped_content_url": "https://example.zendesk.com/system/brands/3600/0014/2813/zendesk_logo.jpeg",
+      "content_type": "image/jpeg",
+      "size": 4060,
+      "width": 80,
+      "height": 80,
+      "inline": false,
+      "thumbnails": [
+        {
+          "url": "https://example.zendesk.com/api/v2/attachments/360000142833.json",
+          "id": 360000142833,
+          "file_name": "zendesk_logo_thumb.jpeg",
+          "content_url": "https://example.zendesk.com/system/brands/3600/0014/2813/zendesk_logo_thumb.jpeg",
+          "mapped_content_url": "https://example.zendesk.com/system/brands/3600/0014/2813/zendesk_logo_thumb.jpeg",
+          "content_type": "image/jpeg",
+          "size": 2040,
+          "width": 32,
+          "height": 32,
+          "inline": false
+        },
+        {
+          "url": "https://example.zendesk.com/api/v2/attachments/360000142853.json",
+          "id": 360000142853,
+          "file_name": "zendesk_logo_small.jpeg",
+          "content_url": "https://example.zendesk.com/system/brands/3600/0014/2813/zendesk_logo_small.jpeg",
+          "mapped_content_url": "https://example.zendesk.com/system/brands/3600/0014/2813/zendesk_logo_small.jpeg",
+          "content_type": "image/jpeg",
+          "size": 1322,
+          "width": 24,
+          "height": 24,
+          "inline": false
+        }
+      ]
+    }
+  }
+}
diff --git a/zendesk/brand.go b/zendesk/brand.go
index b74c54b..1e05afe 100644
--- a/zendesk/brand.go
+++ b/zendesk/brand.go
@@ -2,6 +2,7 @@ package zendesk
 
 import (
 	"encoding/json"
+	"fmt"
 	"time"
 )
 
@@ -28,6 +29,9 @@ type Brand struct {
 // BrandAPI an interface containing all methods associated with zendesk brands
 type BrandAPI interface {
 	CreateBrand(brand Brand) (Brand, error)
+	GetBrand(brandID int64) (Brand, error)
+	UpdateBrand(brandID int64, brand Brand) (Brand, error)
+	DeleteBrand(brandID int64) error
 }
 
 // CreateBrand creates new brand
@@ -49,3 +53,59 @@ func (z *Client) CreateBrand(brand Brand) (Brand, error) {
 	}
 	return result.Brand, nil
 }
+
+// GetBrand gets a specified brand
+// ref: https://developer.zendesk.com/rest_api/docs/support/brands#show-brand
+func (z *Client) GetBrand(brandID int64) (Brand, error) {
+	var result struct {
+		Brand Brand `json:"brand"`
+	}
+
+	body, err := z.Get(fmt.Sprintf("/brands/%d.json", brandID))
+
+	if err != nil {
+		return Brand{}, err
+	}
+
+	err = json.Unmarshal(body, &result)
+	if err != nil {
+		return Brand{}, err
+	}
+
+	return result.Brand, err
+}
+
+// UpdateBrand updates a brand with the specified brand
+// ref: https://developer.zendesk.com/rest_api/docs/support/brands#update-brand
+func (z *Client) UpdateBrand(brandID int64, brand Brand) (Brand, error) {
+	var result, data struct {
+		Brand Brand `json:"brand"`
+	}
+
+	data.Brand = brand
+
+	body, err := z.Put(fmt.Sprintf("/brands/%d.json", brandID), data)
+
+	if err != nil {
+		return Brand{}, err
+	}
+
+	err = json.Unmarshal(body, &result)
+	if err != nil {
+		return Brand{}, err
+	}
+
+	return result.Brand, err
+}
+
+// DeleteBrand deletes the specified brand
+// ref: https://developer.zendesk.com/rest_api/docs/support/brands#delete-brand
+func (z *Client) DeleteBrand(brandID int64) error {
+	err := z.Delete(fmt.Sprintf("/brands/%d.json", brandID))
+
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
diff --git a/zendesk/mock/client.go b/zendesk/mock/client.go
index 4772661..94973f2 100644
--- a/zendesk/mock/client.go
+++ b/zendesk/mock/client.go
@@ -123,6 +123,20 @@ func (mr *ClientMockRecorder) CreateUser(arg0 interface{}) *gomock.Call {
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateUser", reflect.TypeOf((*Client)(nil).CreateUser), arg0)
 }
 
+// DeleteBrand mocks base method
+func (m *Client) DeleteBrand(arg0 int64) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DeleteBrand", arg0)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// DeleteBrand indicates an expected call of DeleteBrand
+func (mr *ClientMockRecorder) DeleteBrand(arg0 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteBrand", reflect.TypeOf((*Client)(nil).DeleteBrand), arg0)
+}
+
 // DeleteGroup mocks base method
 func (m *Client) DeleteGroup(arg0 int64) error {
 	m.ctrl.T.Helper()
@@ -151,6 +165,21 @@ func (mr *ClientMockRecorder) DeleteTicketField(arg0 interface{}) *gomock.Call {
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteTicketField", reflect.TypeOf((*Client)(nil).DeleteTicketField), arg0)
 }
 
+// GetBrand mocks base method
+func (m *Client) GetBrand(arg0 int64) (zendesk.Brand, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "GetBrand", arg0)
+	ret0, _ := ret[0].(zendesk.Brand)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// GetBrand indicates an expected call of GetBrand
+func (mr *ClientMockRecorder) GetBrand(arg0 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBrand", reflect.TypeOf((*Client)(nil).GetBrand), arg0)
+}
+
 // GetGroup mocks base method
 func (m *Client) GetGroup(arg0 int64) (zendesk.Group, error) {
 	m.ctrl.T.Helper()
@@ -276,6 +305,21 @@ func (mr *ClientMockRecorder) GetUsers() *gomock.Call {
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUsers", reflect.TypeOf((*Client)(nil).GetUsers))
 }
 
+// UpdateBrand mocks base method
+func (m *Client) UpdateBrand(arg0 int64, arg1 zendesk.Brand) (zendesk.Brand, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "UpdateBrand", arg0, arg1)
+	ret0, _ := ret[0].(zendesk.Brand)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// UpdateBrand indicates an expected call of UpdateBrand
+func (mr *ClientMockRecorder) UpdateBrand(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateBrand", reflect.TypeOf((*Client)(nil).UpdateBrand), arg0, arg1)
+}
+
 // UpdateGroup mocks base method
 func (m *Client) UpdateGroup(arg0 int64, arg1 zendesk.Group) (zendesk.Group, error) {
 	m.ctrl.T.Helper()


Test patch:
diff --git a/zendesk/brand_test.go b/zendesk/brand_test.go
index b3bcdcd..387d537 100644
--- a/zendesk/brand_test.go
+++ b/zendesk/brand_test.go
@@ -2,6 +2,7 @@ package zendesk
 
 import (
 	"net/http"
+	"net/http/httptest"
 	"testing"
 )
 
@@ -15,3 +16,48 @@ func TestCreateBrand(t *testing.T) {
 		t.Fatalf("Failed to send request to create brand: %s", err)
 	}
 }
+
+func TestGetBrand(t *testing.T) {
+	mockAPI := newMockAPI(http.MethodGet, "brand.json")
+	client := newTestClient(mockAPI)
+	defer mockAPI.Close()
+
+	brand, err := client.GetBrand(123)
+	if err != nil {
+		t.Fatalf("Failed to get brand: %s", err)
+	}
+
+	expectedID := int64(360002143133)
+	if brand.ID != expectedID {
+		t.Fatalf("Returned brand does not have the expected ID %d. Brand ID is %d", expectedID, brand.ID)
+	}
+}
+
+func TestUpdateBrand(t *testing.T) {
+	mockAPI := newMockAPIWithStatus(http.MethodPut, "brands.json", http.StatusOK)
+	client := newTestClient(mockAPI)
+	defer mockAPI.Close()
+
+	updatedBrand, err := client.UpdateBrand(int64(1234), Brand{})
+	if err != nil {
+		t.Fatalf("Failed to send request to create brand: %s", err)
+	}
+
+	expectedID := int64(360002143133)
+	if updatedBrand.ID != expectedID {
+		t.Fatalf("Updated brand %v did not have expected id %d", updatedBrand, expectedID)
+	}
+}
+
+func TestDeleteBrand(t *testing.T) {
+	mockAPI := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		w.WriteHeader(http.StatusNoContent)
+		w.Write(nil)
+	}))
+
+	c := newTestClient(mockAPI)
+	err := c.DeleteBrand(1234)
+	if err != nil {
+		t.Fatalf("Failed to delete brand: %s", err)
+	}
+}