Repository: nukosuke/go-zendesk (go)

Issue:
Add support for trigger
API reference: https://developer.zendesk.com/rest_api/docs/support/triggers

- [x] Create
- [x] Read
- [x] Update
- [x] Delete

Pull request description:
RUD Trigger
close #86 
last feature for v0.2.0

Patch:
diff --git a/fixture/GET/trigger.json b/fixture/GET/trigger.json
new file mode 100644
index 0000000..d33acf8
--- /dev/null
+++ b/fixture/GET/trigger.json
@@ -0,0 +1,43 @@
+{
+  "trigger": {
+    "url": "https://example.zendesk.com/api/v2/triggers/360056295714.json",
+    "id": 360056295714,
+    "title": "Notify requester of received request",
+    "active": true,
+    "updated_at": "2018-11-23T16:05:14Z",
+    "created_at": "2018-11-23T16:05:12Z",
+    "actions": [
+      {
+        "field": "notification_user",
+        "value": [
+          "requester_id",
+          "[Request received]",
+          "Your request ({{ticket.id}}) has been received and is being reviewed by our support staff.\n\nTo add additional comments, reply to this email."
+        ]
+      }
+    ],
+    "conditions": {
+      "all": [
+        {
+          "field": "update_type",
+          "operator": "is",
+          "value": "Create"
+        },
+        {
+          "field": "status",
+          "operator": "is_not",
+          "value": "solved"
+        },
+        {
+          "field": "ticket_is_public",
+          "operator": "is",
+          "value": "public"
+        }
+      ],
+      "any": []
+    },
+    "description": null,
+    "position": 0,
+    "raw_title": "Notify requester of received request"
+  }
+}
diff --git a/fixture/PUT/triggers.json b/fixture/PUT/triggers.json
new file mode 100644
index 0000000..d33acf8
--- /dev/null
+++ b/fixture/PUT/triggers.json
@@ -0,0 +1,43 @@
+{
+  "trigger": {
+    "url": "https://example.zendesk.com/api/v2/triggers/360056295714.json",
+    "id": 360056295714,
+    "title": "Notify requester of received request",
+    "active": true,
+    "updated_at": "2018-11-23T16:05:14Z",
+    "created_at": "2018-11-23T16:05:12Z",
+    "actions": [
+      {
+        "field": "notification_user",
+        "value": [
+          "requester_id",
+          "[Request received]",
+          "Your request ({{ticket.id}}) has been received and is being reviewed by our support staff.\n\nTo add additional comments, reply to this email."
+        ]
+      }
+    ],
+    "conditions": {
+      "all": [
+        {
+          "field": "update_type",
+          "operator": "is",
+          "value": "Create"
+        },
+        {
+          "field": "status",
+          "operator": "is_not",
+          "value": "solved"
+        },
+        {
+          "field": "ticket_is_public",
+          "operator": "is",
+          "value": "public"
+        }
+      ],
+      "any": []
+    },
+    "description": null,
+    "position": 0,
+    "raw_title": "Notify requester of received request"
+  }
+}
diff --git a/zendesk/mock/client.go b/zendesk/mock/client.go
index ad09fcb..f68381d 100644
--- a/zendesk/mock/client.go
+++ b/zendesk/mock/client.go
@@ -179,6 +179,20 @@ func (mr *ClientMockRecorder) DeleteTicketForm(arg0 interface{}) *gomock.Call {
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteTicketForm", reflect.TypeOf((*Client)(nil).DeleteTicketForm), arg0)
 }
 
+// DeleteTrigger mocks base method
+func (m *Client) DeleteTrigger(arg0 int64) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DeleteTrigger", arg0)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// DeleteTrigger indicates an expected call of DeleteTrigger
+func (mr *ClientMockRecorder) DeleteTrigger(arg0 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteTrigger", reflect.TypeOf((*Client)(nil).DeleteTrigger), arg0)
+}
+
 // DeleteUpload mocks base method
 func (m *Client) DeleteUpload(arg0 string) error {
 	m.ctrl.T.Helper()
@@ -331,6 +345,21 @@ func (mr *ClientMockRecorder) GetTicketForms() *gomock.Call {
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTicketForms", reflect.TypeOf((*Client)(nil).GetTicketForms))
 }
 
+// GetTrigger mocks base method
+func (m *Client) GetTrigger(arg0 int64) (zendesk.Trigger, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "GetTrigger", arg0)
+	ret0, _ := ret[0].(zendesk.Trigger)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// GetTrigger indicates an expected call of GetTrigger
+func (mr *ClientMockRecorder) GetTrigger(arg0 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTrigger", reflect.TypeOf((*Client)(nil).GetTrigger), arg0)
+}
+
 // GetTriggers mocks base method
 func (m *Client) GetTriggers() ([]zendesk.Trigger, zendesk.Page, error) {
 	m.ctrl.T.Helper()
@@ -423,6 +452,21 @@ func (mr *ClientMockRecorder) UpdateTicketForm(arg0, arg1 interface{}) *gomock.C
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateTicketForm", reflect.TypeOf((*Client)(nil).UpdateTicketForm), arg0, arg1)
 }
 
+// UpdateTrigger mocks base method
+func (m *Client) UpdateTrigger(arg0 int64, arg1 zendesk.Trigger) (zendesk.Trigger, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "UpdateTrigger", arg0, arg1)
+	ret0, _ := ret[0].(zendesk.Trigger)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// UpdateTrigger indicates an expected call of UpdateTrigger
+func (mr *ClientMockRecorder) UpdateTrigger(arg0, arg1 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateTrigger", reflect.TypeOf((*Client)(nil).UpdateTrigger), arg0, arg1)
+}
+
 // UploadAttachment mocks base method
 func (m *Client) UploadAttachment(arg0, arg1 string) zendesk.UploadWriter {
 	m.ctrl.T.Helper()
diff --git a/zendesk/trigger.go b/zendesk/trigger.go
index d7f3eef..cd4b1e3 100644
--- a/zendesk/trigger.go
+++ b/zendesk/trigger.go
@@ -2,6 +2,7 @@ package zendesk
 
 import (
 	"encoding/json"
+	"fmt"
 	"time"
 )
 
@@ -41,9 +42,13 @@ type Trigger struct {
 type TriggerAPI interface {
 	GetTriggers() ([]Trigger, Page, error)
 	CreateTrigger(trigger Trigger) (Trigger, error)
+	GetTrigger(id int64) (Trigger, error)
+	UpdateTrigger(id int64, trigger Trigger) (Trigger, error)
+	DeleteTrigger(id int64) error
 }
 
 // GetTriggers fetch trigger list
+// ref: https://developer.zendesk.com/rest_api/docs/support/triggers#getting-triggers
 func (z *Client) GetTriggers() ([]Trigger, Page, error) {
 	var data struct {
 		Triggers []Trigger `json:"triggers"`
@@ -63,7 +68,7 @@ func (z *Client) GetTriggers() ([]Trigger, Page, error) {
 }
 
 // CreateTrigger creates new trigger
-// ref: https://developer.zendesk.com/rest_api/docs/core/triggers#create-trigger
+// ref: https://developer.zendesk.com/rest_api/docs/support/triggers#create-trigger
 func (z *Client) CreateTrigger(trigger Trigger) (Trigger, error) {
 	var data, result struct {
 		Trigger Trigger `json:"trigger"`
@@ -81,3 +86,54 @@ func (z *Client) CreateTrigger(trigger Trigger) (Trigger, error) {
 	}
 	return result.Trigger, nil
 }
+
+// GetTrigger returns the specified trigger
+// ref: https://developer.zendesk.com/rest_api/docs/support/triggers#getting-triggers
+func (z *Client) GetTrigger(id int64) (Trigger, error) {
+	var result struct {
+		Trigger Trigger `json:"trigger"`
+	}
+
+	body, err := z.Get(fmt.Sprintf("/triggers/%d.json", id))
+	if err != nil {
+		return Trigger{}, err
+	}
+
+	err = json.Unmarshal(body, &result)
+	if err != nil {
+		return Trigger{}, err
+	}
+	return result.Trigger, nil
+}
+
+// UpdateTrigger updates the specified trigger and returns the updated one
+// ref: https://developer.zendesk.com/rest_api/docs/support/triggers#update-trigger
+func (z *Client) UpdateTrigger(id int64, trigger Trigger) (Trigger, error) {
+	var data, result struct {
+		Trigger Trigger `json:"trigger"`
+	}
+
+	data.Trigger = trigger
+	body, err := z.Put(fmt.Sprintf("/triggers/%d.json", id), data)
+	if err != nil {
+		return Trigger{}, err
+	}
+
+	err = json.Unmarshal(body, &result)
+	if err != nil {
+		return Trigger{}, err
+	}
+
+	return result.Trigger, nil
+}
+
+// DeleteTrigger deletes the specified trigger
+// ref: https://developer.zendesk.com/rest_api/docs/support/triggers#delete-trigger
+func (z *Client) DeleteTrigger(id int64) error {
+	err := z.Delete(fmt.Sprintf("/triggers/%d.json", id))
+	if err != nil {
+		return err
+	}
+
+	return nil
+}


Test patch:
diff --git a/zendesk/trigger_test.go b/zendesk/trigger_test.go
index d4205af..9a64367 100644
--- a/zendesk/trigger_test.go
+++ b/zendesk/trigger_test.go
@@ -2,6 +2,7 @@ package zendesk
 
 import (
 	"net/http"
+	"net/http/httptest"
 	"testing"
 )
 
@@ -30,3 +31,87 @@ func TestCreateTrigger(t *testing.T) {
 		t.Fatalf("Failed to send request to create trigger: %s", err)
 	}
 }
+
+func TestGetTrigger(t *testing.T) {
+	mockAPI := newMockAPI(http.MethodGet, "trigger.json")
+	client := newTestClient(mockAPI)
+	defer mockAPI.Close()
+
+	trg, err := client.GetTrigger(123)
+	if err != nil {
+		t.Fatalf("Failed to get trigger: %s", err)
+	}
+
+	expectedID := int64(360056295714)
+	if trg.ID != expectedID {
+		t.Fatalf("Returned trigger does not have the expected ID %d. Trigger id is %d", expectedID, trg.ID)
+	}
+}
+
+func TestGetTriggerFailure(t *testing.T) {
+	mockAPI := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		w.WriteHeader(http.StatusInternalServerError)
+		w.Write(nil)
+	}))
+
+	c := newTestClient(mockAPI)
+	_, err := c.GetTrigger(1234)
+	if err == nil {
+		t.Fatal("Client did not return error when api failed")
+	}
+}
+
+func TestUpdateTrigger(t *testing.T) {
+	mockAPI := newMockAPIWithStatus(http.MethodPut, "triggers.json", http.StatusOK)
+	client := newTestClient(mockAPI)
+	defer mockAPI.Close()
+
+	trg, err := client.UpdateTrigger(123, Trigger{})
+	if err != nil {
+		t.Fatalf("Failed to get trigger: %s", err)
+	}
+
+	expectedID := int64(360056295714)
+	if trg.ID != expectedID {
+		t.Fatalf("Returned trigger does not have the expected ID %d. Trigger id is %d", expectedID, trg.ID)
+	}
+}
+
+func TestUpdateTriggerFailure(t *testing.T) {
+	mockAPI := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		w.WriteHeader(http.StatusInternalServerError)
+		w.Write(nil)
+	}))
+
+	c := newTestClient(mockAPI)
+	_, err := c.UpdateTrigger(1234, Trigger{})
+	if err == nil {
+		t.Fatal("Client did not return error when api failed")
+	}
+}
+
+func TestDeleteTrigger(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.DeleteTrigger(1234)
+	if err != nil {
+		t.Fatalf("Failed to delete trigger: %s", err)
+	}
+}
+
+func TestDeleteTriggerFailure(t *testing.T) {
+	mockAPI := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		w.WriteHeader(http.StatusInternalServerError)
+		w.Write(nil)
+	}))
+
+	c := newTestClient(mockAPI)
+	err := c.DeleteTrigger(1234)
+	if err == nil {
+		t.Fatal("Client did not return error when api failed")
+	}
+}