desk_api_v2 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +15 -0
- data/.gitignore +1 -0
- data/CHANGELOG.md +0 -0
- data/Gemfile +3 -0
- data/LICENSE +24 -0
- data/README.md +27 -0
- data/Rakefile +39 -0
- data/desk_api_v2.gemspec +27 -0
- data/lib/desk.rb +11 -0
- data/lib/desk/api/articles.rb +34 -0
- data/lib/desk/api/cases.rb +47 -0
- data/lib/desk/api/customers.rb +36 -0
- data/lib/desk/api/groups.rb +30 -0
- data/lib/desk/api/modules/creatable.rb +15 -0
- data/lib/desk/api/modules/deletable.rb +11 -0
- data/lib/desk/api/modules/listable.rb +16 -0
- data/lib/desk/api/modules/searchable.rb +13 -0
- data/lib/desk/api/topics.rb +25 -0
- data/lib/desk/api/translations.rb +24 -0
- data/lib/desk/article.rb +7 -0
- data/lib/desk/case.rb +7 -0
- data/lib/desk/client.rb +39 -0
- data/lib/desk/collection.rb +17 -0
- data/lib/desk/connection.rb +71 -0
- data/lib/desk/customer.rb +7 -0
- data/lib/desk/entity.rb +7 -0
- data/lib/desk/error.rb +17 -0
- data/lib/desk/filter.rb +7 -0
- data/lib/desk/group.rb +7 -0
- data/lib/desk/message.rb +7 -0
- data/lib/desk/response/error_handling.rb +30 -0
- data/lib/desk/topic.rb +7 -0
- data/lib/desk/translation.rb +7 -0
- data/lib/desk/user.rb +7 -0
- data/spec/desk/api/articles_spec.rb +135 -0
- data/spec/desk/api/cases_spec.rb +181 -0
- data/spec/desk/api/customers_spec.rb +135 -0
- data/spec/desk/api/groups_spec.rb +98 -0
- data/spec/desk/api/topics_spec.rb +98 -0
- data/spec/desk/api/translations_spec.rb +92 -0
- data/spec/desk/collection_spec.rb +22 -0
- data/spec/desk/connection_spec.rb +95 -0
- data/spec/fixtures/article.json +39 -0
- data/spec/fixtures/articles.json +101 -0
- data/spec/fixtures/case.json +40 -0
- data/spec/fixtures/cases.json +105 -0
- data/spec/fixtures/customer.json +60 -0
- data/spec/fixtures/customers.json +143 -0
- data/spec/fixtures/group.json +9 -0
- data/spec/fixtures/group_filters.json +53 -0
- data/spec/fixtures/group_users.json +71 -0
- data/spec/fixtures/groups.json +42 -0
- data/spec/fixtures/message.json +26 -0
- data/spec/fixtures/topic.json +23 -0
- data/spec/fixtures/topics.json +69 -0
- data/spec/fixtures/translation.json +28 -0
- data/spec/fixtures/translations.json +79 -0
- data/spec/spec_helper.rb +17 -0
- metadata +200 -0
data/lib/desk/client.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'desk/connection'
|
2
|
+
require 'desk/api/cases'
|
3
|
+
require 'desk/api/articles'
|
4
|
+
require 'desk/api/translations'
|
5
|
+
require 'desk/api/customers'
|
6
|
+
require 'desk/api/topics'
|
7
|
+
require 'desk/api/groups'
|
8
|
+
|
9
|
+
module Desk
|
10
|
+
class Client
|
11
|
+
|
12
|
+
def initialize(opts={})
|
13
|
+
@opts = opts
|
14
|
+
end
|
15
|
+
|
16
|
+
def articles
|
17
|
+
Desk::Api::Articles.new(connection)
|
18
|
+
end
|
19
|
+
|
20
|
+
def cases
|
21
|
+
Desk::Api::Cases.new(connection)
|
22
|
+
end
|
23
|
+
|
24
|
+
def customers
|
25
|
+
Desk::Api::Customers.new(connection)
|
26
|
+
end
|
27
|
+
|
28
|
+
def topics
|
29
|
+
Desk::Api::Topics.new(connection)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def connection
|
35
|
+
@connection ||= Desk::Connection.new(@opts)
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Desk
|
2
|
+
class Collection < Array
|
3
|
+
|
4
|
+
def initialize(response, klass)
|
5
|
+
@response = response
|
6
|
+
super response["_embedded"]["entries"]
|
7
|
+
coerce_into klass
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def coerce_into(klass)
|
13
|
+
self.map! { |obj| klass.new(obj) }
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'faraday_middleware'
|
2
|
+
require 'desk/response/error_handling'
|
3
|
+
|
4
|
+
module Desk
|
5
|
+
class Connection
|
6
|
+
|
7
|
+
def initialize(opts={})
|
8
|
+
@site = opts[:site]
|
9
|
+
connection
|
10
|
+
use_basic_auth(opts) if opts[:email] && opts[:password]
|
11
|
+
use_oauth(opts) if opts[:consumer_key] &&
|
12
|
+
opts[:consumer_secret] &&
|
13
|
+
opts[:token] &&
|
14
|
+
opts[:token_secret]
|
15
|
+
end
|
16
|
+
|
17
|
+
def get(*opts)
|
18
|
+
@connection.get(*stringify_arrays(*opts)).body
|
19
|
+
end
|
20
|
+
|
21
|
+
def post(*opts)
|
22
|
+
@connection.post(*opts).body
|
23
|
+
end
|
24
|
+
|
25
|
+
def patch(*opts)
|
26
|
+
@connection.patch(*opts).body
|
27
|
+
end
|
28
|
+
|
29
|
+
def delete(*opts)
|
30
|
+
result = @connection.delete(*opts)
|
31
|
+
|
32
|
+
result.status == 204
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def connection
|
38
|
+
@connection ||= Faraday.new(base_url, ssl: { verify: true } ) do |conn|
|
39
|
+
conn.use Desk::Response::ErrorHandling
|
40
|
+
conn.use FaradayMiddleware::ParseJson
|
41
|
+
conn.headers = {'Content-Type' => 'application/json', 'Accept' => 'application/json' }
|
42
|
+
conn.request :json
|
43
|
+
conn.use Faraday::Adapter::NetHttp
|
44
|
+
end
|
45
|
+
@connection
|
46
|
+
end
|
47
|
+
|
48
|
+
def use_basic_auth(opts)
|
49
|
+
@connection.builder.insert(1, Faraday::Request::BasicAuthentication, opts[:email], opts[:password])
|
50
|
+
end
|
51
|
+
|
52
|
+
def use_oauth(opts)
|
53
|
+
@connection.builder.insert(1, FaradayMiddleware::OAuth, {
|
54
|
+
:consumer_key => opts[:consumer_key],
|
55
|
+
:consumer_secret => opts[:consumer_secret],
|
56
|
+
:token => opts[:token],
|
57
|
+
:token_secret => opts[:token_secret]
|
58
|
+
} )
|
59
|
+
end
|
60
|
+
|
61
|
+
def base_url
|
62
|
+
"https://#{@site}.desk.com/api/v2/"
|
63
|
+
end
|
64
|
+
|
65
|
+
def stringify_arrays(*opts)
|
66
|
+
opts.collect do |opt|
|
67
|
+
opt.is_a?(Hash) ? opt.each {|k,v| opt[k] = v.is_a?(Array) ? v.join(",") : v} : opt
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/desk/entity.rb
ADDED
data/lib/desk/error.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module Desk
|
2
|
+
class Error < StandardError
|
3
|
+
|
4
|
+
end
|
5
|
+
|
6
|
+
BadRequest = Class.new(Desk::Error)
|
7
|
+
Unauthorized = Class.new(Desk::Error)
|
8
|
+
NotFound = Class.new(Desk::Error)
|
9
|
+
Forbidden = Class.new(Desk::Error)
|
10
|
+
MethodNotAllowed = Class.new(Desk::Error)
|
11
|
+
NotAcceptable = Class.new(Desk::Error)
|
12
|
+
Conflict = Class.new(Desk::Error)
|
13
|
+
UnsupportedMediaType = Class.new(Desk::Error)
|
14
|
+
UnprocessableEntity = Class.new(Desk::Error)
|
15
|
+
TooManyRequests = Class.new(Desk::Error)
|
16
|
+
NotImplemented = Class.new(Desk::Error)
|
17
|
+
end
|
data/lib/desk/filter.rb
ADDED
data/lib/desk/group.rb
ADDED
data/lib/desk/message.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'desk/error'
|
2
|
+
|
3
|
+
module Desk
|
4
|
+
module Response
|
5
|
+
class ErrorHandling < Faraday::Response::Middleware
|
6
|
+
|
7
|
+
ERROR_TYPE = {
|
8
|
+
400 => BadRequest,
|
9
|
+
401 => Unauthorized,
|
10
|
+
404 => NotFound,
|
11
|
+
403 => Forbidden,
|
12
|
+
405 => MethodNotAllowed,
|
13
|
+
406 => NotAcceptable,
|
14
|
+
409 => Conflict,
|
15
|
+
415 => UnsupportedMediaType,
|
16
|
+
422 => UnprocessableEntity,
|
17
|
+
429 => TooManyRequests,
|
18
|
+
501 => NotImplemented
|
19
|
+
}
|
20
|
+
|
21
|
+
def call(env)
|
22
|
+
@app.call(env).on_complete do |finished_env|
|
23
|
+
if finished_env[:status] >= 400
|
24
|
+
raise ERROR_TYPE[finished_env[:status]], finished_env[:body]["message"] if ERROR_TYPE[finished_env[:status]]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/desk/topic.rb
ADDED
data/lib/desk/user.rb
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'json'
|
2
|
+
require_relative '../../spec_helper'
|
3
|
+
|
4
|
+
describe Desk::Api::Articles do
|
5
|
+
|
6
|
+
before { @connection = Minitest::Mock.new }
|
7
|
+
|
8
|
+
subject { Desk::Api::Articles.new(@connection) }
|
9
|
+
|
10
|
+
describe "#all" do
|
11
|
+
|
12
|
+
before { @connection.expect(:get, articles_fixture, ["articles"]) }
|
13
|
+
|
14
|
+
it "will connect to the articles endpoint" do
|
15
|
+
subject.all
|
16
|
+
end
|
17
|
+
|
18
|
+
it "will return an array of articles" do
|
19
|
+
result = subject.all
|
20
|
+
|
21
|
+
assert result.is_a? Array
|
22
|
+
assert result.first.is_a? Desk::Article
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#show" do
|
27
|
+
|
28
|
+
before { @connection.expect(:get, article_fixture, ["articles/1234"]) }
|
29
|
+
|
30
|
+
it "will connect to the article show endpoint" do
|
31
|
+
subject.show(1234)
|
32
|
+
|
33
|
+
@connection.verify
|
34
|
+
end
|
35
|
+
|
36
|
+
it "will return a single article object" do
|
37
|
+
result = subject.show(1234)
|
38
|
+
|
39
|
+
assert result.is_a? Desk::Article
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "#create" do
|
44
|
+
|
45
|
+
before do
|
46
|
+
@data = {
|
47
|
+
subject: "How to make your customers happy",
|
48
|
+
body: "<strong>Use Desk.com</strong>",
|
49
|
+
body_email: "Custom email body for article",
|
50
|
+
body_email_auto: false,
|
51
|
+
_links: { topic: { href: "/api/v2/topics/1", class: "topic" } }
|
52
|
+
}
|
53
|
+
|
54
|
+
@connection.expect(:post, article_fixture, ["articles", @data])
|
55
|
+
end
|
56
|
+
|
57
|
+
it "will connect to the article creation endpoint" do
|
58
|
+
subject.create(@data)
|
59
|
+
|
60
|
+
@connection.verify
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "#update" do
|
65
|
+
before do
|
66
|
+
@data = {
|
67
|
+
subject: "How to make your customers happy",
|
68
|
+
body: "<strong>Use Desk.com</strong>",
|
69
|
+
body_email: "Email just doesn't cut it",
|
70
|
+
body_email_auto: false,
|
71
|
+
body_twitter: "Use Desk.com in 140 chars or less",
|
72
|
+
body_twitter_auto: false,
|
73
|
+
_links: {
|
74
|
+
topic: {
|
75
|
+
href: "/api/v2/topics/2"
|
76
|
+
}
|
77
|
+
}
|
78
|
+
}
|
79
|
+
|
80
|
+
@connection.expect(:patch, article_fixture, ["articles/1234", @data])
|
81
|
+
end
|
82
|
+
|
83
|
+
it "will connect to the article update endpoint" do
|
84
|
+
subject.update(1234, @data)
|
85
|
+
|
86
|
+
@connection.verify
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "#delete" do
|
91
|
+
|
92
|
+
before { @connection.expect(:delete, true, ["articles/1234"]) }
|
93
|
+
|
94
|
+
it "will connect to the article delete endpoint" do
|
95
|
+
subject.delete(1234)
|
96
|
+
|
97
|
+
@connection.verify
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe "#search" do
|
102
|
+
|
103
|
+
it "will connect to the article search endpoint" do
|
104
|
+
@connection.expect(:get, articles_fixture, ["articles/search", {text: "foo"}])
|
105
|
+
|
106
|
+
subject.search(text: "foo")
|
107
|
+
|
108
|
+
@connection.verify
|
109
|
+
end
|
110
|
+
|
111
|
+
it "will pass topic IDs into the search query" do
|
112
|
+
@connection.expect(:get, articles_fixture, ["articles/search", {text: "foo", topic_ids: [1,2,3]}])
|
113
|
+
|
114
|
+
subject.search(text: "foo", topic_ids: [1,2,3])
|
115
|
+
|
116
|
+
@connection.verify
|
117
|
+
end
|
118
|
+
|
119
|
+
it "will whitelist hash arguments" do
|
120
|
+
@connection.expect(:get, articles_fixture, ["articles/search", {text: "foo", topic_ids: [1,2,3]}])
|
121
|
+
|
122
|
+
subject.search(text: "foo", topic_ids: [1,2,3], bar: "baz")
|
123
|
+
|
124
|
+
@connection.verify
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def articles_fixture
|
129
|
+
JSON.load(fixture("articles.json"))
|
130
|
+
end
|
131
|
+
|
132
|
+
def article_fixture
|
133
|
+
JSON.load(fixture("article.json"))
|
134
|
+
end
|
135
|
+
end
|
@@ -0,0 +1,181 @@
|
|
1
|
+
require 'json'
|
2
|
+
require_relative '../../spec_helper'
|
3
|
+
|
4
|
+
class CasesSpec
|
5
|
+
describe Desk::Api::Cases do
|
6
|
+
|
7
|
+
before { @connection = Minitest::Mock.new }
|
8
|
+
|
9
|
+
subject { Desk::Api::Cases.new(@connection) }
|
10
|
+
|
11
|
+
describe "#all" do
|
12
|
+
|
13
|
+
before { @connection.expect(:get, cases_fixture, ["cases"]) }
|
14
|
+
|
15
|
+
it "will connect to the cases endpoint" do
|
16
|
+
subject.all
|
17
|
+
|
18
|
+
@connection.verify
|
19
|
+
end
|
20
|
+
|
21
|
+
it "will return an array of cases" do
|
22
|
+
result = subject.all
|
23
|
+
|
24
|
+
assert result.is_a? Array
|
25
|
+
assert result.first.is_a? Desk::Case
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "#show" do
|
30
|
+
|
31
|
+
before { @connection.expect(:get, case_fixture, ["cases/1234"]) }
|
32
|
+
|
33
|
+
it "will connect to the case show endpoint" do
|
34
|
+
subject.show(1234)
|
35
|
+
|
36
|
+
@connection.verify
|
37
|
+
end
|
38
|
+
|
39
|
+
it "will return a single case object" do
|
40
|
+
result = subject.show(1234)
|
41
|
+
|
42
|
+
assert result.is_a? Desk::Case
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#create" do
|
47
|
+
|
48
|
+
before do
|
49
|
+
@data = {
|
50
|
+
type: "email",
|
51
|
+
subject: "Creating a case via the API",
|
52
|
+
priority: 4,
|
53
|
+
status: "open",
|
54
|
+
labels: [
|
55
|
+
"Spam",
|
56
|
+
"Ignore"
|
57
|
+
],
|
58
|
+
language: "fr",
|
59
|
+
created_at: "2012-05-01T21:38:48Z",
|
60
|
+
_links: {
|
61
|
+
customer: {
|
62
|
+
href: "/api/v2/customers/1",
|
63
|
+
class: "customer"
|
64
|
+
},
|
65
|
+
assigned_user: {
|
66
|
+
href: "/api/v2/users/1",
|
67
|
+
class: "user"
|
68
|
+
},
|
69
|
+
assigned_group: {
|
70
|
+
href: "/api/v2/groups/1",
|
71
|
+
class: "group"
|
72
|
+
},
|
73
|
+
locked_by: {
|
74
|
+
href: "/api/v2/users/1",
|
75
|
+
class: "user"
|
76
|
+
}
|
77
|
+
},
|
78
|
+
message: {
|
79
|
+
direction: "in",
|
80
|
+
status: "received",
|
81
|
+
to: "someone@desk.com",
|
82
|
+
from: "someone-else@desk.com",
|
83
|
+
cc: "alpha@desk.com",
|
84
|
+
bcc: "beta@desk.com",
|
85
|
+
subject: "Creating a case via the API",
|
86
|
+
body: "Please assist me with this case",
|
87
|
+
created_at: "2012-05-02T21:38:48Z"
|
88
|
+
}
|
89
|
+
}
|
90
|
+
|
91
|
+
@connection.expect(:post, case_fixture, ["cases", @data])
|
92
|
+
end
|
93
|
+
|
94
|
+
it "will connect to the case creation endpoint" do
|
95
|
+
subject.create(@data)
|
96
|
+
|
97
|
+
@connection.verify
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe "#update" do
|
102
|
+
before do
|
103
|
+
@data = {
|
104
|
+
subject: "Updated",
|
105
|
+
status: "pending",
|
106
|
+
labels: [
|
107
|
+
"Spam",
|
108
|
+
"Test"
|
109
|
+
],
|
110
|
+
custom_fields: {
|
111
|
+
level: "super"
|
112
|
+
},
|
113
|
+
_links: {
|
114
|
+
assigned_group: {
|
115
|
+
href: "/api/v2/groups/1",
|
116
|
+
rel: "group"
|
117
|
+
}
|
118
|
+
}
|
119
|
+
}
|
120
|
+
|
121
|
+
@connection.expect(:patch, case_fixture, ["cases/1234", @data])
|
122
|
+
end
|
123
|
+
|
124
|
+
it "will connect to the case update endpoint" do
|
125
|
+
subject.update(1234, @data)
|
126
|
+
|
127
|
+
@connection.verify
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe "#search" do
|
132
|
+
|
133
|
+
Desk::Api::Cases::VALID_SEARCH_PARAMS.each do |param|
|
134
|
+
it "will pass whitelisted params into the search query" do
|
135
|
+
@connection.expect(:get, cases_fixture, ["cases/search", {param => "foo"}])
|
136
|
+
|
137
|
+
subject.search(param => "foo")
|
138
|
+
|
139
|
+
@connection.verify
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
it "will whitelist hash arguments" do
|
144
|
+
@connection.expect(:get, cases_fixture, ["cases/search", {name: "foo"}])
|
145
|
+
|
146
|
+
subject.search(name: "foo", bar: "baz")
|
147
|
+
|
148
|
+
@connection.verify
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
describe "#message" do
|
153
|
+
|
154
|
+
before { @connection.expect(:get, message_fixture, ["cases/1234/message"]) }
|
155
|
+
|
156
|
+
it "will connect to the case message endpoint" do
|
157
|
+
subject.message(1234)
|
158
|
+
|
159
|
+
@connection.verify
|
160
|
+
end
|
161
|
+
|
162
|
+
it "will return a single message object" do
|
163
|
+
result = subject.message(1234)
|
164
|
+
|
165
|
+
assert result.is_a? Desk::Message
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def cases_fixture
|
170
|
+
JSON.load(fixture("cases.json"))
|
171
|
+
end
|
172
|
+
|
173
|
+
def case_fixture
|
174
|
+
JSON.load(fixture("case.json"))
|
175
|
+
end
|
176
|
+
|
177
|
+
def message_fixture
|
178
|
+
JSON.load(fixture("message.json"))
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|