desk 0.3.0
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.
- data/.gemtest +0 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.yardopts +9 -0
- data/Gemfile +12 -0
- data/HISTORY.mkd +44 -0
- data/LICENSE.mkd +20 -0
- data/README.mkd +267 -0
- data/Rakefile +23 -0
- data/desk.gemspec +44 -0
- data/lib/desk.rb +26 -0
- data/lib/desk/api.rb +28 -0
- data/lib/desk/authentication.rb +25 -0
- data/lib/desk/client.rb +28 -0
- data/lib/desk/client/article.rb +92 -0
- data/lib/desk/client/case.rb +55 -0
- data/lib/desk/client/customer.rb +146 -0
- data/lib/desk/client/interaction.rb +75 -0
- data/lib/desk/client/macro.rb +142 -0
- data/lib/desk/client/topic.rb +90 -0
- data/lib/desk/client/user.rb +38 -0
- data/lib/desk/configuration.rb +98 -0
- data/lib/desk/connection.rb +39 -0
- data/lib/desk/error.rb +67 -0
- data/lib/desk/request.rb +44 -0
- data/lib/desk/version.rb +4 -0
- data/lib/faraday/request/multipart_with_file.rb +30 -0
- data/lib/faraday/request/oauth.rb +23 -0
- data/lib/faraday/response/raise_http_4xx.rb +45 -0
- data/lib/faraday/response/raise_http_5xx.rb +24 -0
- data/spec/desk/api_spec.rb +70 -0
- data/spec/desk/client/article_spec.rb +134 -0
- data/spec/desk/client/case_spec.rb +99 -0
- data/spec/desk/client/customer_spec.rb +158 -0
- data/spec/desk/client/interaction_spec.rb +191 -0
- data/spec/desk/client/macro_spec.rb +204 -0
- data/spec/desk/client/topic_spec.rb +135 -0
- data/spec/desk/client/user_spec.rb +58 -0
- data/spec/desk/client_spec.rb +10 -0
- data/spec/desk_spec.rb +127 -0
- data/spec/faraday/response_spec.rb +34 -0
- data/spec/fixtures/article.json +50 -0
- data/spec/fixtures/article_create.json +54 -0
- data/spec/fixtures/article_destroy.json +3 -0
- data/spec/fixtures/article_update.json +54 -0
- data/spec/fixtures/articles.json +58 -0
- data/spec/fixtures/case.json +59 -0
- data/spec/fixtures/case_update.json +59 -0
- data/spec/fixtures/cases.json +182 -0
- data/spec/fixtures/customer.json +58 -0
- data/spec/fixtures/customer_create.json +56 -0
- data/spec/fixtures/customer_create_email.json +15 -0
- data/spec/fixtures/customer_update.json +47 -0
- data/spec/fixtures/customer_update_email.json +15 -0
- data/spec/fixtures/customers.json +98 -0
- data/spec/fixtures/interaction_create.json +126 -0
- data/spec/fixtures/interactions.json +139 -0
- data/spec/fixtures/macro.json +8 -0
- data/spec/fixtures/macro_action.json +9 -0
- data/spec/fixtures/macro_action_update.json +12 -0
- data/spec/fixtures/macro_actions.json +69 -0
- data/spec/fixtures/macro_create.json +13 -0
- data/spec/fixtures/macro_destroy.json +3 -0
- data/spec/fixtures/macro_update.json +13 -0
- data/spec/fixtures/macros.json +24 -0
- data/spec/fixtures/topic.json +9 -0
- data/spec/fixtures/topic_create.json +14 -0
- data/spec/fixtures/topic_destroy.json +3 -0
- data/spec/fixtures/topic_update.json +14 -0
- data/spec/fixtures/topics.json +35 -0
- data/spec/fixtures/user.json +15 -0
- data/spec/fixtures/users.json +24 -0
- data/spec/helper.rb +55 -0
- metadata +464 -0
data/lib/desk/request.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
module Desk
|
2
|
+
# Defines HTTP request methods
|
3
|
+
module Request
|
4
|
+
# Perform an HTTP GET request
|
5
|
+
def get(path, options={}, raw=false)
|
6
|
+
request(:get, path, options, raw)
|
7
|
+
end
|
8
|
+
|
9
|
+
# Perform an HTTP POST request
|
10
|
+
def post(path, options={}, raw=false)
|
11
|
+
request(:post, path, options, raw)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Perform an HTTP PUT request
|
15
|
+
def put(path, options={}, raw=false)
|
16
|
+
request(:put, path, options, raw)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Perform an HTTP DELETE request
|
20
|
+
def delete(path, options={}, raw=false)
|
21
|
+
request(:delete, path, options, raw)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
# Perform an HTTP request
|
27
|
+
def request(method, path, options, raw=false)
|
28
|
+
response = connection(raw).send(method) do |request|
|
29
|
+
case method
|
30
|
+
when :get, :delete
|
31
|
+
request.url(formatted_path(path), options)
|
32
|
+
when :post, :put
|
33
|
+
request.path = formatted_path(path)
|
34
|
+
request.body = options unless options.empty?
|
35
|
+
end
|
36
|
+
end
|
37
|
+
raw ? response : response.body
|
38
|
+
end
|
39
|
+
|
40
|
+
def formatted_path(path)
|
41
|
+
[path, format].compact.join('.')
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/desk/version.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
|
3
|
+
# @private
|
4
|
+
module Faraday
|
5
|
+
# @private
|
6
|
+
class Request::MultipartWithFile < Faraday::Middleware
|
7
|
+
def call(env)
|
8
|
+
if env[:body].is_a?(Hash)
|
9
|
+
env[:body].each do |key, value|
|
10
|
+
if value.is_a?(File)
|
11
|
+
env[:body][key] = Faraday::UploadIO.new(value, mime_type(value), value.path)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
@app.call(env)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def mime_type(file)
|
22
|
+
case file.path
|
23
|
+
when /\.jpe?g/i then 'image/jpeg'
|
24
|
+
when /\.gif$/i then 'image/gif'
|
25
|
+
when /\.png$/i then 'image/png'
|
26
|
+
else 'application/octet-stream'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
|
3
|
+
module Faraday
|
4
|
+
class Request::OAuth < Faraday::Middleware
|
5
|
+
dependency 'simple_oauth'
|
6
|
+
|
7
|
+
def call(env)
|
8
|
+
params = env[:body] || {}
|
9
|
+
|
10
|
+
signature_params = params.reject{ |k,v| v.respond_to?(:content_type) || (env[:method] == :put) }
|
11
|
+
|
12
|
+
header = SimpleOAuth::Header.new(env[:method], env[:url], signature_params, @options)
|
13
|
+
|
14
|
+
env[:request_headers]['Authorization'] = header.to_s
|
15
|
+
|
16
|
+
@app.call(env)
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(app, options)
|
20
|
+
@app, @options = app, options
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
|
3
|
+
# @private
|
4
|
+
module Faraday
|
5
|
+
# @private
|
6
|
+
class Response::RaiseHttp4xx < Response::Middleware
|
7
|
+
def on_complete(env)
|
8
|
+
case env[:status].to_i
|
9
|
+
when 400
|
10
|
+
raise Desk::BadRequest.new(error_message(env), env[:response_headers])
|
11
|
+
when 401
|
12
|
+
raise Desk::Unauthorized.new(error_message(env), env[:response_headers])
|
13
|
+
when 403
|
14
|
+
raise Desk::Forbidden.new(error_message(env), env[:response_headers])
|
15
|
+
when 404
|
16
|
+
raise Desk::NotFound.new(error_message(env), env[:response_headers])
|
17
|
+
when 406
|
18
|
+
raise Desk::NotAcceptable.new(error_message(env), env[:response_headers])
|
19
|
+
when 420
|
20
|
+
raise Desk::EnhanceYourCalm.new(error_message(env), env[:response_headers])
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def error_message(env)
|
27
|
+
"#{env[:method].to_s.upcase} #{env[:url].to_s}: #{env[:status]}#{error_body(env[:body])}"
|
28
|
+
end
|
29
|
+
|
30
|
+
def error_body(body)
|
31
|
+
if body.nil?
|
32
|
+
nil
|
33
|
+
elsif body['error']
|
34
|
+
": #{body['error']}"
|
35
|
+
elsif body['errors']
|
36
|
+
first = body['errors'].to_a.first
|
37
|
+
if first.kind_of? Hash
|
38
|
+
": #{first['message'].chomp}"
|
39
|
+
else
|
40
|
+
": #{first.chomp}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
|
3
|
+
# @private
|
4
|
+
module Faraday
|
5
|
+
# @private
|
6
|
+
class Response::RaiseHttp5xx < Response::Middleware
|
7
|
+
def on_complete(env)
|
8
|
+
case env[:status].to_i
|
9
|
+
when 500
|
10
|
+
raise Desk::InternalServerError.new(error_message(env, "Something is technically wrong."), env[:response_headers])
|
11
|
+
when 502
|
12
|
+
raise Desk::BadGateway.new(error_message(env, "Desk.com is down or being upgraded."), env[:response_headers])
|
13
|
+
when 503
|
14
|
+
raise Desk::ServiceUnavailable.new(error_message(env, "(__-){ Desk.com is over capacity."), env[:response_headers])
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def error_message(env, body=nil)
|
21
|
+
"#{env[:method].to_s.upcase} #{env[:url].to_s}: #{[env[:status].to_s + ':', body].compact.join(' ')} Check http://desk.com/ for updates on the status of the Desk.com service."
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Desk::API do
|
4
|
+
before do
|
5
|
+
@keys = Desk::Configuration::VALID_OPTIONS_KEYS
|
6
|
+
end
|
7
|
+
|
8
|
+
context "with module configuration" do
|
9
|
+
|
10
|
+
before do
|
11
|
+
Desk.configure do |config|
|
12
|
+
@keys.each do |key|
|
13
|
+
config.send("#{key}=", key)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
after do
|
19
|
+
Desk.reset
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should inherit module configuration" do
|
23
|
+
api = Desk::API.new
|
24
|
+
@keys.each do |key|
|
25
|
+
api.send(key).should == key
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context "with class configuration" do
|
30
|
+
|
31
|
+
before do
|
32
|
+
@configuration = {
|
33
|
+
:consumer_key => 'CK',
|
34
|
+
:consumer_secret => 'CS',
|
35
|
+
:oauth_token => 'OT',
|
36
|
+
:oauth_token_secret => 'OS',
|
37
|
+
:adapter => :typhoeus,
|
38
|
+
:format => :xml,
|
39
|
+
:proxy => 'http://erik:sekret@proxy.example.com:8080',
|
40
|
+
:subdomain => 'zencoder',
|
41
|
+
:support_email => 'help@zencoder.com',
|
42
|
+
:user_agent => 'Custom User Agent',
|
43
|
+
:version => "amazing"
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
context "during initialization"
|
48
|
+
|
49
|
+
it "should override module configuration" do
|
50
|
+
api = Desk::API.new(@configuration)
|
51
|
+
@keys.each do |key|
|
52
|
+
api.send(key).should == @configuration[key]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context "after initilization" do
|
57
|
+
|
58
|
+
it "should override module configuration after initialization" do
|
59
|
+
api = Desk::API.new
|
60
|
+
@configuration.each do |key, value|
|
61
|
+
api.send("#{key}=", value)
|
62
|
+
end
|
63
|
+
@keys.each do |key|
|
64
|
+
api.send(key).should == @configuration[key]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Desk::Client do
|
4
|
+
Desk::Configuration::VALID_FORMATS.each do |format|
|
5
|
+
context ".new(:format => '#{format}')" do
|
6
|
+
before do
|
7
|
+
@client = Desk::Client.new(:subdomain => "example", :format => format, :consumer_key => 'CK', :consumer_secret => 'CS', :oauth_token => 'OT', :oauth_token_secret => 'OS')
|
8
|
+
end
|
9
|
+
|
10
|
+
describe ".articles" do
|
11
|
+
|
12
|
+
context "lookup" do
|
13
|
+
|
14
|
+
before do
|
15
|
+
stub_get("topics/1/articles.#{format}").
|
16
|
+
to_return(:body => fixture("articles.#{format}"), :headers => {:content_type => "application/#{format}; charset=utf-8"})
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should post to the correct resource" do
|
20
|
+
@client.articles(1)
|
21
|
+
a_get("topics/1/articles.#{format}").
|
22
|
+
should have_been_made
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should return the articles" do
|
26
|
+
articles = @client.articles(1)
|
27
|
+
|
28
|
+
articles.results.should be_a Array
|
29
|
+
articles.results.first.article.id.should == 13
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe ".article" do
|
36
|
+
|
37
|
+
context "lookup" do
|
38
|
+
|
39
|
+
before do
|
40
|
+
stub_get("articles/13.#{format}").
|
41
|
+
to_return(:body => fixture("article.#{format}"), :headers => {:content_type => "application/#{format}; charset=utf-8"})
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should get the correct resource" do
|
45
|
+
@client.article(13)
|
46
|
+
a_get("articles/13.#{format}").
|
47
|
+
should have_been_made
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should return up to 100 cases worth of extended information" do
|
51
|
+
article = @client.article(13)
|
52
|
+
|
53
|
+
article.id.should == 13
|
54
|
+
article.subject.should == "API Tips"
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe ".create_article" do
|
61
|
+
|
62
|
+
context "create" do
|
63
|
+
|
64
|
+
before do
|
65
|
+
stub_post("topics/1/articles.#{format}").
|
66
|
+
to_return(:body => fixture("article_create.#{format}"), :headers => {:content_type => "application/#{format}; charset=utf-8"})
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should post to the correct resource" do
|
70
|
+
@client.create_article(1, :subject => "API Tips", :main_content => "Tips on using our API")
|
71
|
+
a_post("topics/1/articles.#{format}").
|
72
|
+
should have_been_made
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should return the articles" do
|
76
|
+
article = @client.create_article(1, :subject => "API Tips", :main_content => "Tips on using our API")
|
77
|
+
|
78
|
+
article.id.should == 13
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe ".update_article" do
|
85
|
+
|
86
|
+
context "update" do
|
87
|
+
|
88
|
+
before do
|
89
|
+
stub_put("articles/1.#{format}").
|
90
|
+
to_return(:body => fixture("article_update.#{format}"), :headers => {:content_type => "application/#{format}; charset=utf-8"})
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should post to the correct resource" do
|
94
|
+
@client.update_article(1, :subject => "API Tips", :main_content => "Tips on using our API")
|
95
|
+
a_put("articles/1.#{format}").
|
96
|
+
should have_been_made
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should return the new topic" do
|
100
|
+
topic = @client.update_article(1, :subject => "API Tips", :main_content => "Tips on using our API")
|
101
|
+
|
102
|
+
topic.subject.should == "API Tips"
|
103
|
+
topic.main_content.should == "Tips on using our API"
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe ".delete_article" do
|
110
|
+
|
111
|
+
context "delete" do
|
112
|
+
|
113
|
+
before do
|
114
|
+
stub_delete("articles/1.#{format}").
|
115
|
+
to_return(:body => fixture("article_destroy.#{format}"), :headers => {:content_type => "application/#{format}; charset=utf-8"})
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should post to the correct resource" do
|
119
|
+
@client.delete_article(1)
|
120
|
+
a_delete("articles/1.#{format}").
|
121
|
+
should have_been_made
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should return a successful response" do
|
125
|
+
topic = @client.delete_article(1)
|
126
|
+
topic.success.should == true
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Desk::Client do
|
4
|
+
Desk::Configuration::VALID_FORMATS.each do |format|
|
5
|
+
context ".new(:format => '#{format}')" do
|
6
|
+
before do
|
7
|
+
@client = Desk::Client.new(:subdomain => "example", :format => format, :consumer_key => 'CK', :consumer_secret => 'CS', :oauth_token => 'OT', :oauth_token_secret => 'OS')
|
8
|
+
end
|
9
|
+
|
10
|
+
describe ".cases" do
|
11
|
+
|
12
|
+
context "lookup" do
|
13
|
+
|
14
|
+
before do
|
15
|
+
stub_get("cases.#{format}").
|
16
|
+
to_return(:body => fixture("cases.#{format}"), :headers => {:content_type => "application/#{format}; charset=utf-8"})
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should get the correct resource" do
|
20
|
+
@client.cases
|
21
|
+
a_get("cases.#{format}").
|
22
|
+
should have_been_made
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should return up to 100 cases worth of extended information" do
|
26
|
+
cases = @client.cases
|
27
|
+
|
28
|
+
cases.results.should be_a Array
|
29
|
+
cases.results.first.case.id.should == 1
|
30
|
+
cases.results.first.case.user.name.should == "Jeremy Suriel"
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe ".case" do
|
37
|
+
|
38
|
+
context "lookup" do
|
39
|
+
|
40
|
+
before do
|
41
|
+
stub_get("cases/1.#{format}").
|
42
|
+
to_return(:body => fixture("case.#{format}"), :headers => {:content_type => "application/#{format}; charset=utf-8"})
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should get the correct resource" do
|
46
|
+
@client.case(1)
|
47
|
+
a_get("cases/1.#{format}").
|
48
|
+
should have_been_made
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should return up to 100 cases worth of extended information" do
|
52
|
+
a_case = @client.case(1)
|
53
|
+
|
54
|
+
a_case.id.should == 1
|
55
|
+
a_case.external_id.should == "123"
|
56
|
+
a_case.subject.should == "Welcome to Desk.com"
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe ".update_case" do
|
63
|
+
|
64
|
+
context "update" do
|
65
|
+
|
66
|
+
before do
|
67
|
+
stub_put("cases/1.#{format}").
|
68
|
+
to_return(:body => fixture("case_update.#{format}"), :headers => {:content_type => "application/#{format}; charset=utf-8"})
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should get the correct resource" do
|
72
|
+
@client.update_case(1, :subject => "Welcome to Desk")
|
73
|
+
a_put("cases/1.#{format}").
|
74
|
+
should have_been_made
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should return up to 100 cases worth of extended information" do
|
78
|
+
a_case = @client.update_case(1, :subject => "Welcome to Desk.com")
|
79
|
+
|
80
|
+
a_case.id.should == 1
|
81
|
+
a_case.subject.should == "Welcome to Desk.com"
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe ".case_url" do
|
88
|
+
|
89
|
+
context "generating a case url" do
|
90
|
+
|
91
|
+
it "should make a correct url for the case" do
|
92
|
+
@client.case_url(123).should == "https://example.desk.com/agent/case/123"
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|