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.
Files changed (74) hide show
  1. data/.gemtest +0 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +3 -0
  4. data/.yardopts +9 -0
  5. data/Gemfile +12 -0
  6. data/HISTORY.mkd +44 -0
  7. data/LICENSE.mkd +20 -0
  8. data/README.mkd +267 -0
  9. data/Rakefile +23 -0
  10. data/desk.gemspec +44 -0
  11. data/lib/desk.rb +26 -0
  12. data/lib/desk/api.rb +28 -0
  13. data/lib/desk/authentication.rb +25 -0
  14. data/lib/desk/client.rb +28 -0
  15. data/lib/desk/client/article.rb +92 -0
  16. data/lib/desk/client/case.rb +55 -0
  17. data/lib/desk/client/customer.rb +146 -0
  18. data/lib/desk/client/interaction.rb +75 -0
  19. data/lib/desk/client/macro.rb +142 -0
  20. data/lib/desk/client/topic.rb +90 -0
  21. data/lib/desk/client/user.rb +38 -0
  22. data/lib/desk/configuration.rb +98 -0
  23. data/lib/desk/connection.rb +39 -0
  24. data/lib/desk/error.rb +67 -0
  25. data/lib/desk/request.rb +44 -0
  26. data/lib/desk/version.rb +4 -0
  27. data/lib/faraday/request/multipart_with_file.rb +30 -0
  28. data/lib/faraday/request/oauth.rb +23 -0
  29. data/lib/faraday/response/raise_http_4xx.rb +45 -0
  30. data/lib/faraday/response/raise_http_5xx.rb +24 -0
  31. data/spec/desk/api_spec.rb +70 -0
  32. data/spec/desk/client/article_spec.rb +134 -0
  33. data/spec/desk/client/case_spec.rb +99 -0
  34. data/spec/desk/client/customer_spec.rb +158 -0
  35. data/spec/desk/client/interaction_spec.rb +191 -0
  36. data/spec/desk/client/macro_spec.rb +204 -0
  37. data/spec/desk/client/topic_spec.rb +135 -0
  38. data/spec/desk/client/user_spec.rb +58 -0
  39. data/spec/desk/client_spec.rb +10 -0
  40. data/spec/desk_spec.rb +127 -0
  41. data/spec/faraday/response_spec.rb +34 -0
  42. data/spec/fixtures/article.json +50 -0
  43. data/spec/fixtures/article_create.json +54 -0
  44. data/spec/fixtures/article_destroy.json +3 -0
  45. data/spec/fixtures/article_update.json +54 -0
  46. data/spec/fixtures/articles.json +58 -0
  47. data/spec/fixtures/case.json +59 -0
  48. data/spec/fixtures/case_update.json +59 -0
  49. data/spec/fixtures/cases.json +182 -0
  50. data/spec/fixtures/customer.json +58 -0
  51. data/spec/fixtures/customer_create.json +56 -0
  52. data/spec/fixtures/customer_create_email.json +15 -0
  53. data/spec/fixtures/customer_update.json +47 -0
  54. data/spec/fixtures/customer_update_email.json +15 -0
  55. data/spec/fixtures/customers.json +98 -0
  56. data/spec/fixtures/interaction_create.json +126 -0
  57. data/spec/fixtures/interactions.json +139 -0
  58. data/spec/fixtures/macro.json +8 -0
  59. data/spec/fixtures/macro_action.json +9 -0
  60. data/spec/fixtures/macro_action_update.json +12 -0
  61. data/spec/fixtures/macro_actions.json +69 -0
  62. data/spec/fixtures/macro_create.json +13 -0
  63. data/spec/fixtures/macro_destroy.json +3 -0
  64. data/spec/fixtures/macro_update.json +13 -0
  65. data/spec/fixtures/macros.json +24 -0
  66. data/spec/fixtures/topic.json +9 -0
  67. data/spec/fixtures/topic_create.json +14 -0
  68. data/spec/fixtures/topic_destroy.json +3 -0
  69. data/spec/fixtures/topic_update.json +14 -0
  70. data/spec/fixtures/topics.json +35 -0
  71. data/spec/fixtures/user.json +15 -0
  72. data/spec/fixtures/users.json +24 -0
  73. data/spec/helper.rb +55 -0
  74. metadata +464 -0
@@ -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
@@ -0,0 +1,4 @@
1
+ module Desk
2
+ # The version of the gem
3
+ VERSION = '0.3.0'.freeze unless defined?(::Desk::VERSION)
4
+ end
@@ -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