Skip to content

Commit

Permalink
Merge pull request #197 from 0Delta/add_macro_min
Browse files Browse the repository at this point in the history
Add macro API support
  • Loading branch information
nukosuke authored Jan 28, 2021
2 parents fde1b33 + 0257cce commit 6209dbb
Show file tree
Hide file tree
Showing 8 changed files with 442 additions and 1 deletion.
39 changes: 39 additions & 0 deletions fixture/GET/macro.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"macro":{
"actions": [
{
"field": "status",
"value": "solved"
},
{
"field": "priority",
"value": "normal"
},
{
"field": "type",
"value": "incident"
},
{
"field": "assignee_id",
"value": "current_user"
},
{
"field": "group_id",
"value": "current_groups"
},
{
"field": "comment_value",
"value": "Thanks for your request. This issue you reported is a known issue. For more information, please visit our forums. "
}
],
"active": true,
"created_at": "2019-09-16T02:17:38Z",
"description": null,
"id": 360111062754,
"position": 9999,
"restriction": null,
"title": "Close and redirect to topics",
"updated_at": "2019-09-16T02:17:38Z",
"url": "https://subdomain.zendesk.com/api/v2/macros/360111062754.json"
}
}
24 changes: 24 additions & 0 deletions fixture/GET/macros.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"count": 2,
"macros": [
{
"actions": [],
"active": true,
"description": "Sets the ticket status to `solved`",
"id": 25,
"position": 42,
"restriction": {},
"title": "Close and Save"
},
{
"actions": [],
"active": false,
"description": "Adds a `priority` tag to the ticket",
"id": 26,
"restriction": {},
"title": "Assign priority tag"
}
],
"next_page": null,
"previous_page": null
}
13 changes: 13 additions & 0 deletions fixture/POST/macro.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"macro": {
"actions": [
{
"field": "status",
"value": "solved"
}
],
"id": 4,
"restriction": {},
"title": "Roger Wilco"
}
}
16 changes: 16 additions & 0 deletions fixture/PUT/macro.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"macro": {
"actions": [
{
"field": "status",
"value": "solved"
}
],
"active": true,
"description": "Sets the ticket status to `solved`",
"id": 2,
"position": 42,
"restriction": {},
"title": "Close and Save"
}
}
1 change: 1 addition & 0 deletions zendesk/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type API interface {
DynamicContentAPI
GroupAPI
LocaleAPI
MacroAPI
TicketAPI
TicketFieldAPI
TicketFormAPI
Expand Down
165 changes: 165 additions & 0 deletions zendesk/macro.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
package zendesk

import (
"context"
"encoding/json"
"fmt"
"time"
)

// Macro is information about zendesk macro
type Macro struct {
Actions []MacroAction `json:"actions"`
Active bool `json:"active"`
CreatedAt time.Time `json:"created_at,omitempty"`
Description interface{} `json:"description"`
ID int64 `json:"id,omitempty"`
Position int `json:"position,omitempty"`
Restriction interface{} `json:"restriction"`
Title string `json:"title"`
UpdatedAt time.Time `json:"updated_at,omitempty"`
URL string `json:"url,omitempty"`
}

// MacroAction is definition of what the macro does to the ticket
//
// ref: https://develop.zendesk.com/hc/en-us/articles/360056760874-Support-API-Actions-reference
type MacroAction struct {
Field string `json:"field"`
Value string `json:"value"`
}

// MacroListOptions is parameters used of GetMacros
type MacroListOptions struct {
Access string `json:"access"`
Active string `json:"active"`
Category int `json:"category"`
GroupID int `json:"group_id"`
Include string `json:"include"`
OnlyViewable bool `json:"only_viewable"`

PageOptions

// SortBy can take "created_at", "updated_at", "usage_1h", "usage_24h",
// "usage_7d", "usage_30d", "alphabetical"
SortBy string `url:"sort_by,omitempty"`

// SortOrder can take "asc" or "desc"
SortOrder string `url:"sort_order,omitempty"`
}

// MacroAPI an interface containing all macro related methods
type MacroAPI interface {
GetMacros(ctx context.Context, opts *MacroListOptions) ([]Macro, Page, error)
GetMacro(ctx context.Context, macroID int64) (Macro, error)
CreateMacro(ctx context.Context, macro Macro) (Macro, error)
UpdateMacro(ctx context.Context, macroID int64, macro Macro) (Macro, error)
DeleteMacro(ctx context.Context, macroID int64) error
}

// GetMacros get macro list
//
// ref: https://developer.zendesk.com/rest_api/docs/support/macros#list-macros
func (z *Client) GetMacros(ctx context.Context, opts *MacroListOptions) ([]Macro, Page, error) {
var data struct {
Macros []Macro `json:"macros"`
Page
}

tmp := opts
if tmp == nil {
tmp = &MacroListOptions{}
}

u, err := addOptions("/macros.json", tmp)
if err != nil {
return nil, Page{}, err
}

body, err := z.get(ctx, u)
if err != nil {
return nil, Page{}, err
}

err = json.Unmarshal(body, &data)
if err != nil {
return nil, Page{}, err
}
return data.Macros, data.Page, nil
}

// GetMacro gets a specified macro
//
// ref: https://developer.zendesk.com/rest_api/docs/support/macros#show-macro
func (z *Client) GetMacro(ctx context.Context, macroID int64) (Macro, error) {
var result struct {
Macro Macro `json:"macro"`
}

body, err := z.get(ctx, fmt.Sprintf("/macros/%d.json", macroID))
if err != nil {
return Macro{}, err
}

err = json.Unmarshal(body, &result)
if err != nil {
return Macro{}, err
}

return result.Macro, err
}

// CreateMacro create a new macro
//
// ref: https://developer.zendesk.com/rest_api/docs/support/macros#create-macro
func (z *Client) CreateMacro(ctx context.Context, macro Macro) (Macro, error) {
var data, result struct {
Macro Macro `json:"macro"`
}
data.Macro = macro

body, err := z.post(ctx, "/macros.json", data)
if err != nil {
return Macro{}, err
}

err = json.Unmarshal(body, &result)
if err != nil {
return Macro{}, err
}
return result.Macro, nil
}

// UpdateMacro update an existing macro
// ref: https://developer.zendesk.com/rest_api/docs/support/macros#update-macro
func (z *Client) UpdateMacro(ctx context.Context, macroID int64, macro Macro) (Macro, error) {
var data, result struct {
Macro Macro `json:"macro"`
}
data.Macro = macro

path := fmt.Sprintf("/macros/%d.json", macroID)
body, err := z.put(ctx, path, data)
if err != nil {
return Macro{}, err
}

err = json.Unmarshal(body, &result)
if err != nil {
return Macro{}, err
}

return result.Macro, nil
}

// DeleteMacro deletes the specified macro
// ref: https://developer.zendesk.com/rest_api/docs/support/macros#delete-macro
func (z *Client) DeleteMacro(ctx context.Context, macroID int64) error {
err := z.delete(ctx, fmt.Sprintf("/macros/%d.json", macroID))

if err != nil {
return err
}

return nil
}
108 changes: 108 additions & 0 deletions zendesk/macro_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package zendesk

import (
"net/http"
"net/http/httptest"
"testing"
)

func TestGetMacros(t *testing.T) {
mockAPI := newMockAPI(http.MethodGet, "macros.json")
client := newTestClient(mockAPI)
defer mockAPI.Close()

macros, _, err := client.GetMacros(ctx, &MacroListOptions{
PageOptions: PageOptions{
Page: 1,
PerPage: 10,
},
SortBy: "id",
SortOrder: "asc",
})
if err != nil {
t.Fatalf("Failed to get macros: %s", err)
}

expectedLength := 2
if len(macros) != expectedLength {
t.Fatalf("Returned macros does not have the expected length %d. Macros length is %d", expectedLength, len(macros))
}
}

func TestGetMacro(t *testing.T) {
mockAPI := newMockAPI(http.MethodGet, "macro.json")
client := newTestClient(mockAPI)
defer mockAPI.Close()

macro, err := client.GetMacro(ctx, 2)
if err != nil {
t.Fatalf("Failed to get macro: %s", err)
}

expectedID := int64(360111062754)
if macro.ID != expectedID {
t.Fatalf("Returned macro does not have the expected ID %d. Macro id is %d", expectedID, macro.ID)
}

}

func TestCreateMacro(t *testing.T) {
mockAPI := newMockAPIWithStatus(http.MethodPost, "macro.json", http.StatusCreated)
client := newTestClient(mockAPI)
defer mockAPI.Close()

macro, err := client.CreateMacro(ctx, Macro{
Title: "nyanyanyanya",
// Comment: MacroComment{
// Body: "(●ↀ ω ↀ )",
// },
})
if err != nil {
t.Fatalf("Failed to create macro: %s", err)
}

expectedID := int64(4)
if macro.ID != expectedID {
t.Fatalf("Returned macro does not have the expected ID %d. Macro id is %d", expectedID, macro.ID)
}
}

func TestUpdateMacro(t *testing.T) {
mockAPI := newMockAPIWithStatus(http.MethodPut, "macro.json", http.StatusOK)
client := newTestClient(mockAPI)
defer mockAPI.Close()

macro, err := client.UpdateMacro(ctx, 2, Macro{})
if err != nil {
t.Fatalf("Failed to update macro: %s", err)
}

expectedID := int64(2)
if macro.ID != expectedID {
t.Fatalf("Returned macro does not have the expected ID %d. Macro id is %d", expectedID, macro.ID)
}
}

func TestUpdateMacroFailure(t *testing.T) {
mockAPI := newMockAPIWithStatus(http.MethodPut, "macro.json", http.StatusInternalServerError)
client := newTestClient(mockAPI)
defer mockAPI.Close()

_, err := client.UpdateMacro(ctx, 2, Macro{})
if err == nil {
t.Fatal("Client did not return error when api failed")
}
}

func TestDeleteMacro(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.DeleteMacro(ctx, 437)
if err != nil {
t.Fatalf("Failed to delete macro field: %s", err)
}
}
Loading

0 comments on commit 6209dbb

Please sign in to comment.