desk_api_v2 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +0 -0
  4. data/Gemfile +3 -0
  5. data/LICENSE +24 -0
  6. data/README.md +27 -0
  7. data/Rakefile +39 -0
  8. data/desk_api_v2.gemspec +27 -0
  9. data/lib/desk.rb +11 -0
  10. data/lib/desk/api/articles.rb +34 -0
  11. data/lib/desk/api/cases.rb +47 -0
  12. data/lib/desk/api/customers.rb +36 -0
  13. data/lib/desk/api/groups.rb +30 -0
  14. data/lib/desk/api/modules/creatable.rb +15 -0
  15. data/lib/desk/api/modules/deletable.rb +11 -0
  16. data/lib/desk/api/modules/listable.rb +16 -0
  17. data/lib/desk/api/modules/searchable.rb +13 -0
  18. data/lib/desk/api/topics.rb +25 -0
  19. data/lib/desk/api/translations.rb +24 -0
  20. data/lib/desk/article.rb +7 -0
  21. data/lib/desk/case.rb +7 -0
  22. data/lib/desk/client.rb +39 -0
  23. data/lib/desk/collection.rb +17 -0
  24. data/lib/desk/connection.rb +71 -0
  25. data/lib/desk/customer.rb +7 -0
  26. data/lib/desk/entity.rb +7 -0
  27. data/lib/desk/error.rb +17 -0
  28. data/lib/desk/filter.rb +7 -0
  29. data/lib/desk/group.rb +7 -0
  30. data/lib/desk/message.rb +7 -0
  31. data/lib/desk/response/error_handling.rb +30 -0
  32. data/lib/desk/topic.rb +7 -0
  33. data/lib/desk/translation.rb +7 -0
  34. data/lib/desk/user.rb +7 -0
  35. data/spec/desk/api/articles_spec.rb +135 -0
  36. data/spec/desk/api/cases_spec.rb +181 -0
  37. data/spec/desk/api/customers_spec.rb +135 -0
  38. data/spec/desk/api/groups_spec.rb +98 -0
  39. data/spec/desk/api/topics_spec.rb +98 -0
  40. data/spec/desk/api/translations_spec.rb +92 -0
  41. data/spec/desk/collection_spec.rb +22 -0
  42. data/spec/desk/connection_spec.rb +95 -0
  43. data/spec/fixtures/article.json +39 -0
  44. data/spec/fixtures/articles.json +101 -0
  45. data/spec/fixtures/case.json +40 -0
  46. data/spec/fixtures/cases.json +105 -0
  47. data/spec/fixtures/customer.json +60 -0
  48. data/spec/fixtures/customers.json +143 -0
  49. data/spec/fixtures/group.json +9 -0
  50. data/spec/fixtures/group_filters.json +53 -0
  51. data/spec/fixtures/group_users.json +71 -0
  52. data/spec/fixtures/groups.json +42 -0
  53. data/spec/fixtures/message.json +26 -0
  54. data/spec/fixtures/topic.json +23 -0
  55. data/spec/fixtures/topics.json +69 -0
  56. data/spec/fixtures/translation.json +28 -0
  57. data/spec/fixtures/translations.json +79 -0
  58. data/spec/spec_helper.rb +17 -0
  59. metadata +200 -0
@@ -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
@@ -0,0 +1,7 @@
1
+ require 'desk/entity'
2
+
3
+ module Desk
4
+ class Customer < Entity
5
+
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ require 'ostruct'
2
+
3
+ module Desk
4
+ class Entity < OpenStruct
5
+
6
+ end
7
+ end
@@ -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
@@ -0,0 +1,7 @@
1
+ require 'desk/entity'
2
+
3
+ module Desk
4
+ class Filter < Entity
5
+
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ require 'desk/entity'
2
+
3
+ module Desk
4
+ class Group < Entity
5
+
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ require 'desk/entity'
2
+
3
+ module Desk
4
+ class Message < Entity
5
+
6
+ end
7
+ end
@@ -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
@@ -0,0 +1,7 @@
1
+ require 'desk/entity'
2
+
3
+ module Desk
4
+ class Topic < Entity
5
+
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ require 'desk/entity'
2
+
3
+ module Desk
4
+ class Translation < Entity
5
+
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ require 'desk/entity'
2
+
3
+ module Desk
4
+ class User < Entity
5
+
6
+ end
7
+ end
@@ -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