From 054ad1ff46a768b6e7ebf04d3c2806a30b909480 Mon Sep 17 00:00:00 2001 From: Andy McCall Date: Sun, 8 Dec 2019 19:52:26 -0800 Subject: [PATCH 01/23] Added search API added test for searching groups fixed the url path --- fixture/GET/search_group.json | 18 +++++ fixture/GET/search_ticket.json | 59 ++++++++++++++++ zendesk/search.go | 122 +++++++++++++++++++++++++++++++++ zendesk/search_test.go | 56 +++++++++++++++ 4 files changed, 255 insertions(+) create mode 100644 fixture/GET/search_group.json create mode 100644 fixture/GET/search_ticket.json create mode 100644 zendesk/search.go create mode 100644 zendesk/search_test.go diff --git a/fixture/GET/search_group.json b/fixture/GET/search_group.json new file mode 100644 index 00000000..e02c04bd --- /dev/null +++ b/fixture/GET/search_group.json @@ -0,0 +1,18 @@ +{ + "results": [ + { + "url": "https://d3v-terraform-provider.zendesk.com/api/v2/groups/360007194452.json", + "id": 360007194452, + "name": "nyan", + "description": "", + "deleted": false, + "created_at": "2019-12-09T02:40:11Z", + "updated_at": "2019-12-09T02:40:11Z", + "result_type": "group" + } + ], + "facets": null, + "next_page": null, + "previous_page": null, + "count": 1 +} \ No newline at end of file diff --git a/fixture/GET/search_ticket.json b/fixture/GET/search_ticket.json new file mode 100644 index 00000000..1d748f87 --- /dev/null +++ b/fixture/GET/search_ticket.json @@ -0,0 +1,59 @@ +{ + "results": [ + { + "url": "https://d3v-terraform-provider.zendesk.com/api/v2/tickets/4.json", + "id": 4, + "external_id": null, + "via": { + "channel": "api", + "source": { + "from": {}, + "to": {}, + "rel": null + } + }, + "created_at": "2019-06-06T10:02:04Z", + "updated_at": "2019-06-06T10:02:04Z", + "type": null, + "subject": "nyanyanyanya", + "raw_subject": "nyanyanyanya", + "description": "(●ↀ ω ↀ )", + "priority": "urgent", + "status": "new", + "recipient": null, + "requester_id": 377922500012, + "submitter_id": 377922500012, + "assignee_id": null, + "organization_id": 360363695492, + "group_id": 360004077472, + "collaborator_ids": [ + 377922500012 + ], + "follower_ids": [ + 377922500012 + ], + "email_cc_ids": [], + "forum_topic_id": null, + "problem_id": null, + "has_incidents": false, + "is_public": true, + "due_at": null, + "tags": [], + "custom_fields": [], + "satisfaction_rating": null, + "sharing_agreement_ids": [], + "fields": [], + "followup_ids": [], + "ticket_form_id": 360000389592, + "brand_id": 360002256672, + "satisfaction_probability": null, + "allow_channelback": false, + "allow_attachments": true, + "result_type": "ticket" + } + ], + "facets": null, + "next_page": null, + "previous_page": null, + "count": 1 +} \ No newline at end of file diff --git a/zendesk/search.go b/zendesk/search.go new file mode 100644 index 00000000..90d2f82c --- /dev/null +++ b/zendesk/search.go @@ -0,0 +1,122 @@ +package zendesk + +import ( + "context" + "encoding/json" + "fmt" +) + +// SearchOptions are the options that can be provided to the search API +// +// ref: https://developer.zendesk.com/rest_api/docs/support/search#available-parameters +type SearchOptions struct { + PageOptions + Query string `url:"query"` + SortBy string `url:"sort_by,omitempty"` + SortOrder string `url:"sort_order,omitempty"` +} + +type SearchAPI interface { + Search(ctx context.Context, opts *SearchOptions) (SearchResults, Page, error) +} + +type SearchResults struct { + results []interface{} +} + +func (r *SearchResults) MarshalJSON() ([]byte, error) { + return json.Marshal(r.results) +} + +func (r *SearchResults) UnmarshalJSON(b []byte) error { + var results []interface{} + var tmp []json.RawMessage + err := json.Unmarshal(b, &tmp) + if err != nil { + return err + } + + for _, v := range tmp { + m := make(map[string]interface{}) + err := json.Unmarshal(v, &m) + if err != nil { + return err + } + + t, ok := m["result_type"].(string) + if !ok { + fmt.Errorf("could not assert result type to string. json was: %v", v) + } + + var value interface{} + switch t { + case "group": + var g Group + err = json.Unmarshal(v, &g) + value = g + case "ticket": + var t Ticket + err = json.Unmarshal(v, &t) + value = t + case "user": + var u User + err = json.Unmarshal(v, &u) + value = u + case "organization": + var o Organization + err = json.Unmarshal(v, &o) + value = o + default: + err = fmt.Errorf("value of result was an unsupported type %s", t) + } + + if err != nil { + return err + } + + results= append(results, value) + } + + r.results = results + return nil +} + +// GetTriggers fetch trigger list +// +// ref: https://developer.zendesk.com/rest_api/docs/support/triggers#getting-triggers +func (z *Client) Search(ctx context.Context, opts *SearchOptions) (SearchResults, Page, error) { + var data struct { + Results SearchResults `json:"results"` + Page + } + + if opts == nil { + return SearchResults{}, Page{}, &OptionsError{opts} + } + + u, err := addOptions("/search.json", opts) + if err != nil { + return SearchResults{}, Page{}, err + } + + body, err := z.get(ctx, u) + if err != nil { + return SearchResults{}, Page{}, err + } + + err = json.Unmarshal(body, &data) + if err != nil { + return SearchResults{}, Page{}, err + } + return data.Results, data.Page, nil +} + +// String return string formatted for Search results +func (r *SearchResults) String() string { + return fmt.Sprintf("%v", r.results) +} + +// List return internal array in Search Results +func (r *SearchResults) List() []interface{} { + return r.results +} diff --git a/zendesk/search_test.go b/zendesk/search_test.go new file mode 100644 index 00000000..8eac9a9b --- /dev/null +++ b/zendesk/search_test.go @@ -0,0 +1,56 @@ +package zendesk + +import ( + "net/http" + "testing" +) + +func TestSearchTickets(t *testing.T) { + mockAPI := newMockAPI(http.MethodGet, "search_ticket.json") + client := newTestClient(mockAPI) + defer mockAPI.Close() + + results, _, err := client.Search(ctx, &SearchOptions{}) + if err != nil { + t.Fatalf("Failed to get search results: %s", err) + } + + list := results.List() + if len(list) != 1 { + t.Fatalf("expected length of sla policies is , but got %d", len(list)) + } + + ticket, ok := list[0].(Ticket) + if !ok { + t.Fatalf("Cannot assert %v as a ticket", list[0]) + } + + if ticket.ID != 4 { + t.Fatalf("Ticket did not have the expected id %v", ticket) + } +} + +func TestSearchGroup(t *testing.T) { + mockAPI := newMockAPI(http.MethodGet, "search_group.json") + client := newTestClient(mockAPI) + defer mockAPI.Close() + + results, _, err := client.Search(ctx, &SearchOptions{}) + if err != nil { + t.Fatalf("Failed to get search results: %s", err) + } + + list := results.List() + if len(list) != 1 { + t.Fatalf("expected length of sla policies is , but got %d", len(list)) + } + + ticket, ok := list[0].(Group) + if !ok { + t.Fatalf("Cannot assert %v as a group", list[0]) + } + + if ticket.ID != 360007194452 { + t.Fatalf("Group did not have the expected id %v", ticket) + } +} \ No newline at end of file From 7505a58480dd7616888830132a182d44670ad29a Mon Sep 17 00:00:00 2001 From: Andy McCall Date: Sun, 8 Dec 2019 20:26:48 -0800 Subject: [PATCH 02/23] added todo --- zendesk/search.go | 1 + 1 file changed, 1 insertion(+) diff --git a/zendesk/search.go b/zendesk/search.go index 90d2f82c..230c5c32 100644 --- a/zendesk/search.go +++ b/zendesk/search.go @@ -66,6 +66,7 @@ func (r *SearchResults) UnmarshalJSON(b []byte) error { var o Organization err = json.Unmarshal(v, &o) value = o + // TODO: Handle topics default: err = fmt.Errorf("value of result was an unsupported type %s", t) } From 3f3e0b7aceb61d356f686af781254a9bc471560f Mon Sep 17 00:00:00 2001 From: Andy McCall Date: Sun, 8 Dec 2019 21:57:45 -0800 Subject: [PATCH 03/23] added the benchmark --- fixture/ticket_result.json | 53 ++++++++++++++++++++++++++++++++++++++ zendesk/search_test.go | 12 +++++++++ 2 files changed, 65 insertions(+) create mode 100644 fixture/ticket_result.json diff --git a/fixture/ticket_result.json b/fixture/ticket_result.json new file mode 100644 index 00000000..327b6b23 --- /dev/null +++ b/fixture/ticket_result.json @@ -0,0 +1,53 @@ +[ + { + "url": "https://d3v-terraform-provider.zendesk.com/api/v2/tickets/4.json", + "id": 4, + "external_id": null, + "via": { + "channel": "api", + "source": { + "from": {}, + "to": {}, + "rel": null + } + }, + "created_at": "2019-06-06T10:02:04Z", + "updated_at": "2019-06-06T10:02:04Z", + "type": null, + "subject": "nyanyanyanya", + "raw_subject": "nyanyanyanya", + "description": "(●ↀ ω ↀ )", + "priority": "urgent", + "status": "new", + "recipient": null, + "requester_id": 377922500012, + "submitter_id": 377922500012, + "assignee_id": null, + "organization_id": 360363695492, + "group_id": 360004077472, + "collaborator_ids": [ + 377922500012 + ], + "follower_ids": [ + 377922500012 + ], + "email_cc_ids": [], + "forum_topic_id": null, + "problem_id": null, + "has_incidents": false, + "is_public": true, + "due_at": null, + "tags": [], + "custom_fields": [], + "satisfaction_rating": null, + "sharing_agreement_ids": [], + "fields": [], + "followup_ids": [], + "ticket_form_id": 360000389592, + "brand_id": 360002256672, + "satisfaction_probability": null, + "allow_channelback": false, + "allow_attachments": true, + "result_type": "ticket" + } +] \ No newline at end of file diff --git a/zendesk/search_test.go b/zendesk/search_test.go index 8eac9a9b..8a0c3f86 100644 --- a/zendesk/search_test.go +++ b/zendesk/search_test.go @@ -1,6 +1,7 @@ package zendesk import ( + "encoding/json" "net/http" "testing" ) @@ -30,6 +31,17 @@ func TestSearchTickets(t *testing.T) { } } +func BenchmarkUnmarshalSearchResults(b *testing.B) { + file := readFixture("ticket_result.json") + for i := 0; i < b.N; i++ { + var result SearchResults + err := json.Unmarshal(file, &result) + if err != nil { + b.Fatalf("Recieved error when unmarshalling. %v", err) + } + } +} + func TestSearchGroup(t *testing.T) { mockAPI := newMockAPI(http.MethodGet, "search_group.json") client := newTestClient(mockAPI) From 8a23e65014e410bc8cc0b9b2e4af86bdf50ea236 Mon Sep 17 00:00:00 2001 From: Andy McCall Date: Sun, 8 Dec 2019 22:16:42 -0800 Subject: [PATCH 04/23] Adding comment for pr. --- zendesk/search.go | 1 + 1 file changed, 1 insertion(+) diff --git a/zendesk/search.go b/zendesk/search.go index 230c5c32..4640099e 100644 --- a/zendesk/search.go +++ b/zendesk/search.go @@ -37,6 +37,7 @@ func (r *SearchResults) UnmarshalJSON(b []byte) error { } for _, v := range tmp { + // TODO: check with @nukosuke to see if we should try to speed this up using github.com/tidwall/gjson m := make(map[string]interface{}) err := json.Unmarshal(v, &m) if err != nil { From 40fe90b42759ad5fb101ccd2a1c7334bcc269ef8 Mon Sep 17 00:00:00 2001 From: Andy McCall Date: Sun, 8 Dec 2019 22:46:33 -0800 Subject: [PATCH 05/23] Added Topic --- zendesk/search.go | 5 ++++- zendesk/topics.go | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 zendesk/topics.go diff --git a/zendesk/search.go b/zendesk/search.go index 4640099e..e29eea90 100644 --- a/zendesk/search.go +++ b/zendesk/search.go @@ -67,7 +67,10 @@ func (r *SearchResults) UnmarshalJSON(b []byte) error { var o Organization err = json.Unmarshal(v, &o) value = o - // TODO: Handle topics + case "topic": + var t Topic + err = json.Unmarshal(v, &t) + value = t default: err = fmt.Errorf("value of result was an unsupported type %s", t) } diff --git a/zendesk/topics.go b/zendesk/topics.go new file mode 100644 index 00000000..c4e63f22 --- /dev/null +++ b/zendesk/topics.go @@ -0,0 +1,17 @@ +package zendesk + +import "time" + +type Topic struct { + ID int64 `json:"id"` + URL string `json:"url"` + HtmlURL string `json:"html_url"` + Name string `json:"name"` + Description string `json:"description"` + Position int `json:"position"` + FollowerCount int `json:"follower_count"` + ManageableBy string `json:"manageable_by"` + UserSegmentID int64 `json:"user_segment_id"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` +} From 60ddce4b03f9a28abdf4430387df9bd6252ae520 Mon Sep 17 00:00:00 2001 From: Andy McCall Date: Sun, 8 Dec 2019 22:51:26 -0800 Subject: [PATCH 06/23] Added test for users --- fixture/GET/search_user.json | 80 ++++++++++++++++++++++++++++++++++++ zendesk/search_test.go | 31 ++++++++++++-- 2 files changed, 108 insertions(+), 3 deletions(-) create mode 100644 fixture/GET/search_user.json diff --git a/fixture/GET/search_user.json b/fixture/GET/search_user.json new file mode 100644 index 00000000..a173705f --- /dev/null +++ b/fixture/GET/search_user.json @@ -0,0 +1,80 @@ +{ + "results": [ + { + "id": 1234, + "url": "https://d3v-terraform-provider.zendesk.com/api/v2/users/1234.json", + "name": "Foo Bar", + "email": "a@a.com", + "created_at": "2019-03-18T05:48:08Z", + "updated_at": "2019-12-09T06:48:10Z", + "time_zone": "Eastern Time (US & Canada)", + "iana_time_zone": "America/New_York", + "phone": null, + "shared_phone_number": null, + "photo": { + "url": "https://d3v-terraform-provider.zendesk.com/api/v2/attachments/360215133211.json", + "id": 360215133211, + "file_name": "profile_image_1234_9184218.png", + "content_url": "https://d3v-terraform-provider.zendesk.com/system/photos/3602/1513/3211/profile_image_1234_9184218.png", + "mapped_content_url": "https://d3v-terraform-provider.zendesk.com/system/photos/3602/1513/3211/profile_image_1234_9184218.png", + "content_type": "image/png", + "size": 1979, + "width": 80, + "height": 80, + "inline": false, + "deleted": false, + "thumbnails": [ + { + "url": "https://d3v-terraform-provider.zendesk.com/api/v2/attachments/360215133231.json", + "id": 360215133231, + "file_name": "profile_image_1234_9184218_thumb.png", + "content_url": "https://d3v-terraform-provider.zendesk.com/system/photos/3602/1513/3211/profile_image_1234_9184218_thumb.png", + "mapped_content_url": "https://d3v-terraform-provider.zendesk.com/system/photos/3602/1513/3211/profile_image_1234_9184218_thumb.png", + "content_type": "image/png", + "size": 784, + "width": 32, + "height": 32, + "inline": false, + "deleted": false + } + ] + }, + "locale_id": 1, + "locale": "en-US", + "organization_id": 360363695492, + "role": "admin", + "verified": true, + "external_id": null, + "tags": [], + "alias": "", + "active": true, + "shared": false, + "shared_agent": false, + "last_login_at": "2019-12-09T06:48:10Z", + "two_factor_auth_enabled": null, + "signature": "", + "details": "", + "notes": "", + "role_type": null, + "custom_role_id": null, + "moderator": true, + "ticket_restriction": null, + "only_private_comments": false, + "restricted_agent": false, + "suspended": false, + "chat_only": false, + "default_group_id": 360004077472, + "report_csv": false, + "user_fields": { + "github_profile": "https://github.com/foobar", + "nickname": "foo bar", + "twitter_account": "https://twitter.com/foobar1345" + }, + "result_type": "user" + } + ], + "facets": null, + "next_page": null, + "previous_page": null, + "count": 1 +} \ No newline at end of file diff --git a/zendesk/search_test.go b/zendesk/search_test.go index 8a0c3f86..ec4b6355 100644 --- a/zendesk/search_test.go +++ b/zendesk/search_test.go @@ -57,12 +57,37 @@ func TestSearchGroup(t *testing.T) { t.Fatalf("expected length of sla policies is , but got %d", len(list)) } - ticket, ok := list[0].(Group) + result, ok := list[0].(Group) if !ok { t.Fatalf("Cannot assert %v as a group", list[0]) } - if ticket.ID != 360007194452 { - t.Fatalf("Group did not have the expected id %v", ticket) + if result.ID != 360007194452 { + t.Fatalf("Group did not have the expected id %v", result) + } +} + +func TestSearchUser(t *testing.T) { + mockAPI := newMockAPI(http.MethodGet, "search_user.json") + client := newTestClient(mockAPI) + defer mockAPI.Close() + + results, _, err := client.Search(ctx, &SearchOptions{}) + if err != nil { + t.Fatalf("Failed to get search results: %s", err) + } + + list := results.List() + if len(list) != 1 { + t.Fatalf("expected length of sla policies is , but got %d", len(list)) + } + + result, ok := list[0].(User) + if !ok { + t.Fatalf("Cannot assert %v as a group", list[0]) + } + + if result.ID != 1234 { + t.Fatalf("Group did not have the expected id %v", result) } } \ No newline at end of file From 84ae6554ad4a40bda417a8d95d5215587ee120b6 Mon Sep 17 00:00:00 2001 From: Andy McCall Date: Sun, 8 Dec 2019 22:58:14 -0800 Subject: [PATCH 07/23] Testing that the query is in the correct parameter --- zendesk/search_test.go | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/zendesk/search_test.go b/zendesk/search_test.go index ec4b6355..f6d50cfb 100644 --- a/zendesk/search_test.go +++ b/zendesk/search_test.go @@ -3,6 +3,8 @@ package zendesk import ( "encoding/json" "net/http" + "net/http/httptest" + "path/filepath" "testing" ) @@ -90,4 +92,31 @@ func TestSearchUser(t *testing.T) { if result.ID != 1234 { t.Fatalf("Group did not have the expected id %v", result) } -} \ No newline at end of file +} + +func TestSearchQueryParam(t *testing.T) { + expected := "query string" + mockAPI := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + queryString := r.URL.Query().Get("query") + if queryString != expected { + t.Fatalf(`Did not get the expect query string: "%s". Was: "%s"`, expected, queryString) + } + w.Write(readFixture(filepath.Join(http.MethodGet, "search_user.json"))) + })) + + client := newTestClient(mockAPI) + defer mockAPI.Close() + + opts := SearchOptions{ + PageOptions: PageOptions{ + Page: 1, + PerPage: 2, + }, + Query: expected, + } + + _, _, err := client.Search(ctx, &opts) + if err != nil { + t.Fatalf("Received error from search api") + } +} From 376c9708c42eb2cc4aec5f653d85320fdef919b6 Mon Sep 17 00:00:00 2001 From: Andy McCall Date: Sun, 8 Dec 2019 22:59:56 -0800 Subject: [PATCH 08/23] Added Search API to client interface --- zendesk/api.go | 1 + 1 file changed, 1 insertion(+) diff --git a/zendesk/api.go b/zendesk/api.go index cdb9c1c8..bd2cdd01 100644 --- a/zendesk/api.go +++ b/zendesk/api.go @@ -19,6 +19,7 @@ type API interface { UserAPI UserFieldAPI OrganizationAPI + SearchAPI SLAPolicyAPI } From 81c4aa05d63f810eb2e8a0c1036a5bbed621c795 Mon Sep 17 00:00:00 2001 From: Andy McCall Date: Sun, 8 Dec 2019 23:00:22 -0800 Subject: [PATCH 09/23] regenerated mock client --- zendesk/mock/client.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/zendesk/mock/client.go b/zendesk/mock/client.go index 0a2eb22a..d876319e 100644 --- a/zendesk/mock/client.go +++ b/zendesk/mock/client.go @@ -725,6 +725,22 @@ func (mr *ClientMockRecorder) GetUsers(arg0, arg1 interface{}) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUsers", reflect.TypeOf((*Client)(nil).GetUsers), arg0, arg1) } +// Search mocks base method +func (m *Client) Search(arg0 context.Context, arg1 *zendesk.SearchOptions) (zendesk.SearchResults, zendesk.Page, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Search", arg0, arg1) + ret0, _ := ret[0].(zendesk.SearchResults) + ret1, _ := ret[1].(zendesk.Page) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// Search indicates an expected call of Search +func (mr *ClientMockRecorder) Search(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Search", reflect.TypeOf((*Client)(nil).Search), arg0, arg1) +} + // UpdateAutomation mocks base method func (m *Client) UpdateAutomation(arg0 context.Context, arg1 int64, arg2 zendesk.Automation) (zendesk.Automation, error) { m.ctrl.T.Helper() From 718b521c26d91e3943107b6c7449f636b6857291 Mon Sep 17 00:00:00 2001 From: Andy McCall Date: Tue, 10 Dec 2019 08:10:56 -0800 Subject: [PATCH 10/23] Added whitespace to return --- zendesk/search.go | 1 + 1 file changed, 1 insertion(+) diff --git a/zendesk/search.go b/zendesk/search.go index e29eea90..52f1d789 100644 --- a/zendesk/search.go +++ b/zendesk/search.go @@ -113,6 +113,7 @@ func (z *Client) Search(ctx context.Context, opts *SearchOptions) (SearchResults if err != nil { return SearchResults{}, Page{}, err } + return data.Results, data.Page, nil } From 8fe402ed8d8b0ec0dd8b726d9396a1b9c0ffdfe5 Mon Sep 17 00:00:00 2001 From: Andy McCall Date: Tue, 10 Dec 2019 08:11:45 -0800 Subject: [PATCH 11/23] Adding whitespace before switch --- zendesk/search.go | 1 + 1 file changed, 1 insertion(+) diff --git a/zendesk/search.go b/zendesk/search.go index 52f1d789..d3ebd2dc 100644 --- a/zendesk/search.go +++ b/zendesk/search.go @@ -50,6 +50,7 @@ func (r *SearchResults) UnmarshalJSON(b []byte) error { } var value interface{} + switch t { case "group": var g Group From dc0db3084aa703f9d03bfd2df3db77e5e6f1973b Mon Sep 17 00:00:00 2001 From: Andy McCall Date: Tue, 10 Dec 2019 08:15:09 -0800 Subject: [PATCH 12/23] Fixing grouped vars --- zendesk/search.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/zendesk/search.go b/zendesk/search.go index d3ebd2dc..4d57f0e7 100644 --- a/zendesk/search.go +++ b/zendesk/search.go @@ -29,8 +29,11 @@ func (r *SearchResults) MarshalJSON() ([]byte, error) { } func (r *SearchResults) UnmarshalJSON(b []byte) error { - var results []interface{} - var tmp []json.RawMessage + var ( + results []interface{} + tmp []json.RawMessage + ) + err := json.Unmarshal(b, &tmp) if err != nil { return err From 685cdca1385692b05ec239ee5a3c9f2e1a2098c0 Mon Sep 17 00:00:00 2001 From: Andy McCall Date: Tue, 10 Dec 2019 08:31:19 -0800 Subject: [PATCH 13/23] go vet error --- zendesk/search.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zendesk/search.go b/zendesk/search.go index 4d57f0e7..0a905719 100644 --- a/zendesk/search.go +++ b/zendesk/search.go @@ -49,7 +49,7 @@ func (r *SearchResults) UnmarshalJSON(b []byte) error { t, ok := m["result_type"].(string) if !ok { - fmt.Errorf("could not assert result type to string. json was: %v", v) + return fmt.Errorf("could not assert result type to string. json was: %v", v) } var value interface{} From 710920537c0d2e4896a1632ddd65770bba4bcf22 Mon Sep 17 00:00:00 2001 From: Andy McCall Date: Tue, 10 Dec 2019 09:35:56 -0800 Subject: [PATCH 14/23] Update zendesk/search.go Co-Authored-By: Bot from GolangCI <42910462+golangcibot@users.noreply.github.com> --- zendesk/search.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zendesk/search.go b/zendesk/search.go index 0a905719..2c5d9cf9 100644 --- a/zendesk/search.go +++ b/zendesk/search.go @@ -24,7 +24,7 @@ type SearchResults struct { results []interface{} } -func (r *SearchResults) MarshalJSON() ([]byte, error) { +func (r *SearchResults) MarshalJSON() ([]byte, error) { return json.Marshal(r.results) } From 4abe56e23347741e7146d362ee30405666bcc81f Mon Sep 17 00:00:00 2001 From: Andy McCall Date: Tue, 10 Dec 2019 17:41:56 -0800 Subject: [PATCH 15/23] Update zendesk/search.go Co-Authored-By: Bot from GolangCI <42910462+golangcibot@users.noreply.github.com> --- zendesk/search.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zendesk/search.go b/zendesk/search.go index 2c5d9cf9..fdd65d78 100644 --- a/zendesk/search.go +++ b/zendesk/search.go @@ -31,7 +31,7 @@ func (r *SearchResults) MarshalJSON() ([]byte, error) { func (r *SearchResults) UnmarshalJSON(b []byte) error { var ( results []interface{} - tmp []json.RawMessage + tmp []json.RawMessage ) err := json.Unmarshal(b, &tmp) From 3c16f9c71223e7a5c2da4e6d8a4476fe9e18c0f1 Mon Sep 17 00:00:00 2001 From: Andy McCall Date: Tue, 10 Dec 2019 17:41:34 -0800 Subject: [PATCH 16/23] renamed variable --- zendesk/topics.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zendesk/topics.go b/zendesk/topics.go index c4e63f22..279d01b1 100644 --- a/zendesk/topics.go +++ b/zendesk/topics.go @@ -5,7 +5,7 @@ import "time" type Topic struct { ID int64 `json:"id"` URL string `json:"url"` - HtmlURL string `json:"html_url"` + HTMLURL string `json:"html_url"` Name string `json:"name"` Description string `json:"description"` Position int `json:"position"` From dac99cfee8f92de09511ef860d72a448c44fdb7e Mon Sep 17 00:00:00 2001 From: Andy McCall Date: Tue, 10 Dec 2019 17:42:51 -0800 Subject: [PATCH 17/23] more whitespace fixes --- zendesk/search.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zendesk/search.go b/zendesk/search.go index fdd65d78..79679818 100644 --- a/zendesk/search.go +++ b/zendesk/search.go @@ -42,6 +42,7 @@ func (r *SearchResults) UnmarshalJSON(b []byte) error { for _, v := range tmp { // TODO: check with @nukosuke to see if we should try to speed this up using github.com/tidwall/gjson m := make(map[string]interface{}) + err := json.Unmarshal(v, &m) if err != nil { return err @@ -87,6 +88,7 @@ func (r *SearchResults) UnmarshalJSON(b []byte) error { } r.results = results + return nil } From ceba437eea3bd5250dc42275ca3f9616932ab17f Mon Sep 17 00:00:00 2001 From: Andy McCall Date: Wed, 11 Dec 2019 17:53:47 -0800 Subject: [PATCH 18/23] Refactored Unmarshal into multiple methods --- zendesk/search.go | 86 ++++++++++++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 39 deletions(-) diff --git a/zendesk/search.go b/zendesk/search.go index 79679818..006b2169 100644 --- a/zendesk/search.go +++ b/zendesk/search.go @@ -40,56 +40,64 @@ func (r *SearchResults) UnmarshalJSON(b []byte) error { } for _, v := range tmp { - // TODO: check with @nukosuke to see if we should try to speed this up using github.com/tidwall/gjson - m := make(map[string]interface{}) - err := json.Unmarshal(v, &m) + value, err := r.getObject(v) if err != nil { return err } - t, ok := m["result_type"].(string) - if !ok { - return fmt.Errorf("could not assert result type to string. json was: %v", v) - } + results = append(results, value) + } - var value interface{} - - switch t { - case "group": - var g Group - err = json.Unmarshal(v, &g) - value = g - case "ticket": - var t Ticket - err = json.Unmarshal(v, &t) - value = t - case "user": - var u User - err = json.Unmarshal(v, &u) - value = u - case "organization": - var o Organization - err = json.Unmarshal(v, &o) - value = o - case "topic": - var t Topic - err = json.Unmarshal(v, &t) - value = t - default: - err = fmt.Errorf("value of result was an unsupported type %s", t) - } + r.results = results - if err != nil { - return err - } + return nil +} + +func (r *SearchResults) getObject(blob json.RawMessage) (interface{}, error) { + m := make(map[string]interface{}) - results= append(results, value) + err := json.Unmarshal(blob, &m) + if err != nil { + return nil, err } - r.results = results + t, ok := m["result_type"].(string) + if !ok { + return nil, fmt.Errorf("could not assert result type to string. json was: %v", blob) + } - return nil + var value interface{} + switch t { + case "group": + var g Group + err = json.Unmarshal(blob, &g) + value = g + case "ticket": + var t Ticket + err = json.Unmarshal(blob, &t) + value = t + case "user": + var u User + err = json.Unmarshal(blob, &u) + value = u + case "organization": + var o Organization + err = json.Unmarshal(blob, &o) + value = o + case "topic": + var t Topic + err = json.Unmarshal(blob, &t) + value = t + default: + err = fmt.Errorf("value of result was an unsupported type %s", t) + } + + if err != nil { + return nil, err + } + + return value, nil } // GetTriggers fetch trigger list From c9cf2a0ecf808613ea33528a08b0deb812a91740 Mon Sep 17 00:00:00 2001 From: Andy McCall Date: Wed, 11 Dec 2019 17:54:53 -0800 Subject: [PATCH 19/23] fixing error message --- zendesk/search_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zendesk/search_test.go b/zendesk/search_test.go index f6d50cfb..4d3668f7 100644 --- a/zendesk/search_test.go +++ b/zendesk/search_test.go @@ -86,7 +86,7 @@ func TestSearchUser(t *testing.T) { result, ok := list[0].(User) if !ok { - t.Fatalf("Cannot assert %v as a group", list[0]) + t.Fatalf("Cannot assert %v as a user", list[0]) } if result.ID != 1234 { From ac377ba10f86e23105fb739150bdc8fd29dd93ae Mon Sep 17 00:00:00 2001 From: Andy McCall Date: Wed, 11 Dec 2019 17:57:57 -0800 Subject: [PATCH 20/23] whitespace changes --- zendesk/search.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zendesk/search.go b/zendesk/search.go index 006b2169..c02152d8 100644 --- a/zendesk/search.go +++ b/zendesk/search.go @@ -40,7 +40,6 @@ func (r *SearchResults) UnmarshalJSON(b []byte) error { } for _, v := range tmp { - value, err := r.getObject(v) if err != nil { return err @@ -68,6 +67,7 @@ func (r *SearchResults) getObject(blob json.RawMessage) (interface{}, error) { } var value interface{} + switch t { case "group": var g Group From 17a6db36d51d40f3e0452eeaab9112d90181b214 Mon Sep 17 00:00:00 2001 From: Andy McCall Date: Wed, 11 Dec 2019 18:00:05 -0800 Subject: [PATCH 21/23] go fmt --- zendesk/search.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zendesk/search.go b/zendesk/search.go index c02152d8..84824e43 100644 --- a/zendesk/search.go +++ b/zendesk/search.go @@ -28,7 +28,7 @@ func (r *SearchResults) MarshalJSON() ([]byte, error) { return json.Marshal(r.results) } -func (r *SearchResults) UnmarshalJSON(b []byte) error { +func (r *SearchResults) UnmarshalJSON(b []byte) error { var ( results []interface{} tmp []json.RawMessage From 9653508d18d6e3df944e9a03f4a25809662db78e Mon Sep 17 00:00:00 2001 From: Andy McCall Date: Wed, 11 Dec 2019 18:00:50 -0800 Subject: [PATCH 22/23] colocating SearchResult Methods --- zendesk/search.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/zendesk/search.go b/zendesk/search.go index 84824e43..13e94475 100644 --- a/zendesk/search.go +++ b/zendesk/search.go @@ -100,6 +100,16 @@ func (r *SearchResults) getObject(blob json.RawMessage) (interface{}, error) { return value, nil } +// String return string formatted for Search results +func (r *SearchResults) String() string { + return fmt.Sprintf("%v", r.results) +} + +// List return internal array in Search Results +func (r *SearchResults) List() []interface{} { + return r.results +} + // GetTriggers fetch trigger list // // ref: https://developer.zendesk.com/rest_api/docs/support/triggers#getting-triggers @@ -130,13 +140,3 @@ func (z *Client) Search(ctx context.Context, opts *SearchOptions) (SearchResults return data.Results, data.Page, nil } - -// String return string formatted for Search results -func (r *SearchResults) String() string { - return fmt.Sprintf("%v", r.results) -} - -// List return internal array in Search Results -func (r *SearchResults) List() []interface{} { - return r.results -} From 7b87871c5f75e14e49c13f9600d50b56c05c810d Mon Sep 17 00:00:00 2001 From: Andy McCall Date: Wed, 11 Dec 2019 18:23:23 -0800 Subject: [PATCH 23/23] Updated godoc comment --- zendesk/search.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zendesk/search.go b/zendesk/search.go index 13e94475..0cff9889 100644 --- a/zendesk/search.go +++ b/zendesk/search.go @@ -110,9 +110,9 @@ func (r *SearchResults) List() []interface{} { return r.results } -// GetTriggers fetch trigger list +// Search allows users to query zendesk's unified search api. // -// ref: https://developer.zendesk.com/rest_api/docs/support/triggers#getting-triggers +// ref: https://developer.zendesk.com/rest_api/docs/support/search func (z *Client) Search(ctx context.Context, opts *SearchOptions) (SearchResults, Page, error) { var data struct { Results SearchResults `json:"results"`