createsend 3.0.0 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.coveralls.yml ADDED
@@ -0,0 +1 @@
1
+ service_name: travis-ci
data/.gitignore CHANGED
@@ -1,7 +1,6 @@
1
1
  .DS_Store
2
+ coverage
2
3
  rdoc
3
4
  pkg
4
5
  *.gem
5
6
  example.rb
6
- /.buildpath
7
- /.project
data/Gemfile CHANGED
@@ -1,3 +1,3 @@
1
- source "http://rubygems.org"
1
+ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
data/Gemfile.lock CHANGED
@@ -1,19 +1,26 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- createsend (3.0.0)
4
+ createsend (3.1.0)
5
5
  hashie (>= 1.2, < 3)
6
6
  httparty (~> 0.10)
7
7
  json
8
8
 
9
9
  GEM
10
- remote: http://rubygems.org/
10
+ remote: https://rubygems.org/
11
11
  specs:
12
12
  activesupport (3.2.11)
13
13
  i18n (~> 0.6)
14
14
  multi_json (~> 1.0)
15
15
  bourne (1.1.2)
16
16
  mocha (= 0.10.5)
17
+ colorize (0.5.8)
18
+ coveralls (0.6.3)
19
+ colorize
20
+ multi_json (~> 1.3)
21
+ rest-client
22
+ simplecov (>= 0.7)
23
+ thor
17
24
  fakeweb (1.3.0)
18
25
  hashie (2.0.3)
19
26
  httparty (0.10.2)
@@ -23,11 +30,14 @@ GEM
23
30
  jnunemaker-matchy (0.4.0)
24
31
  json (1.7.7)
25
32
  metaclass (0.0.1)
33
+ mime-types (1.21)
26
34
  mocha (0.10.5)
27
35
  metaclass (~> 0.0.1)
28
36
  multi_json (1.5.0)
29
37
  multi_xml (0.5.3)
30
38
  rake (10.0.3)
39
+ rest-client (1.6.7)
40
+ mime-types (>= 1.16)
31
41
  shoulda (3.3.2)
32
42
  shoulda-context (~> 1.0.1)
33
43
  shoulda-matchers (~> 1.4.1)
@@ -35,13 +45,20 @@ GEM
35
45
  shoulda-matchers (1.4.2)
36
46
  activesupport (>= 3.0.0)
37
47
  bourne (~> 1.1.2)
48
+ simplecov (0.7.1)
49
+ multi_json (~> 1.0)
50
+ simplecov-html (~> 0.7.1)
51
+ simplecov-html (0.7.1)
52
+ thor (0.18.0)
38
53
 
39
54
  PLATFORMS
40
55
  ruby
41
56
 
42
57
  DEPENDENCIES
58
+ coveralls
43
59
  createsend!
44
60
  fakeweb (~> 1.3)
45
61
  jnunemaker-matchy (~> 0.4)
46
62
  rake (~> 10.0)
47
63
  shoulda (~> 3.3)
64
+ simplecov
data/HISTORY.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # createsend-ruby history
2
2
 
3
+ ## v3.1.0 - 28 Mar, 2013 (8a91dda)
4
+
5
+ * Added `CreateSend::CreateSend.refresh_access_token` to allow easier refreshing of access tokens when using class methods.
6
+
7
+ So you can now refresh an access token using _any_ refresh token like so:
8
+
9
+ ```ruby
10
+ access_token, expires_in, refresh_token =
11
+ CreateSend::CreateSend.refresh_access_token 'refresh token'
12
+ ```
13
+
14
+ Or, you can refresh the _current_ access token (with your current refresh token) like so:
15
+
16
+ ```ruby
17
+ cs = CreateSend::CreateSend.new :access_token => 'access token',
18
+ :refresh_token => 'refresh token'
19
+ access_token, expires_in, refresh_token = cs.refresh_token
20
+ ```
21
+
22
+ * Added `CreateSend::InvalidOAuthToken` and `CreateSend::RevokedOAuthToken` exceptions to make handling of OAuth exceptions in user code easier.
23
+
3
24
  ## v3.0.0 - 25 Mar, 2013 (129ad0e)
4
25
 
5
26
  * Added support for authenticating using OAuth. See the [README](README.md#authenticating) for full usage instructions.
data/README.md CHANGED
@@ -1,9 +1,10 @@
1
1
  # createsend
2
- [![Build Status](https://secure.travis-ci.org/campaignmonitor/createsend-ruby.png)][travis] [![Dependency Status](https://gemnasium.com/campaignmonitor/createsend-ruby.png)][gemnasium] [![Gem Version](https://badge.fury.io/rb/createsend.png)][gembadge]
2
+ [![Build Status](https://secure.travis-ci.org/campaignmonitor/createsend-ruby.png)][travis] [![Coverage Status](https://coveralls.io/repos/campaignmonitor/createsend-ruby/badge.png?branch=master)][coveralls] [![Dependency Status](https://gemnasium.com/campaignmonitor/createsend-ruby.png)][gemnasium] [![Gem Version](https://badge.fury.io/rb/createsend.png)][gembadge]
3
3
 
4
4
  A ruby library which implements the complete functionality of the [Campaign Monitor API](http://www.campaignmonitor.com/api/).
5
5
 
6
6
  [travis]: http://travis-ci.org/campaignmonitor/createsend-ruby
7
+ [coveralls]: https://coveralls.io/r/campaignmonitor/createsend-ruby
7
8
  [gemnasium]: https://gemnasium.com/campaignmonitor/createsend-ruby
8
9
  [gembadge]: http://badge.fury.io/rb/createsend
9
10
 
@@ -31,6 +32,8 @@ If you're developing a Rails or Rack based application, we recommend using [omni
31
32
 
32
33
  If you don't use [omniauth-createsend](https://github.com/jdennes/omniauth-createsend), you'll need to get access tokens for your users by following the instructions included in the Campaign Monitor API [documentation](http://www.campaignmonitor.com/api/getting-started/#authenticating_with_oauth). This gem provides functionality to help you do this, as described below. There's also another [example application](https://gist.github.com/jdennes/4945412) you may wish to reference, which doesn't depend on any OAuth libraries.
33
34
 
35
+ #### Redirecting to the authorization URL
36
+
34
37
  The first thing your application should do is redirect your user to the Campaign Monitor authorization URL where they will have the opportunity to approve your application to access their Campaign Monitor account. You can get this authorization URL by using `CreateSend::CreateSend.authorize_url`, like so:
35
38
 
36
39
  ```ruby
@@ -45,6 +48,8 @@ authorize_url = CreateSend::CreateSend.authorize_url(
45
48
  # Redirect your users to authorize_url.
46
49
  ```
47
50
 
51
+ #### Exchanging an OAuth code for an access token
52
+
48
53
  If your user approves your application, they will then be redirected to the `redirect_uri` you specified, which will include a `code` parameter, and optionally a `state` parameter in the query string. Your application should implement a handler which can exchange the code passed to it for an access token, using `CreateSend::CreateSend.exchange_token` like so:
49
54
 
50
55
  ```ruby
@@ -61,6 +66,8 @@ access_token, expires_in, refresh_token = CreateSend::CreateSend.exchange_token(
61
66
 
62
67
  At this point you have an access token and refresh token for your user which you should store somewhere convenient so that your application can look up these values when your user wants to make future Campaign Monitor API calls.
63
68
 
69
+ #### Making API calls using an access token
70
+
64
71
  Once you have an access token and refresh token for your user, you can use the `createsend` gem to authenticate and make further API calls like so:
65
72
 
66
73
  ```ruby
@@ -74,7 +81,11 @@ cs = CreateSend::CreateSend.new auth
74
81
  clients = cs.clients
75
82
  ```
76
83
 
77
- All OAuth tokens have an expiry time, and can be renewed with a corresponding refresh token. If your access token expires when attempting to make an API call, the `CreateSend::ExpiredOAuthToken` exception will be raised, so your code should handle this. Here's an example of how you could do this:
84
+ #### Refreshing access tokens
85
+
86
+ All OAuth access tokens have an expiry time, and can be renewed with a refresh token. If your access token expires when attempting to make an API call, the `CreateSend::ExpiredOAuthToken` exception will be raised, so your code should handle this. You can handle this using either `CreateSend::CreateSend.refresh_access_token` (when calling class methods) or `CreateSend::CreateSend#refresh_token` (when calling instance methods).
87
+
88
+ Here's an example of using `CreateSend::CreateSend#refresh_token` to refresh your current access token when calling `CreateSend::CreateSend#clients`:
78
89
 
79
90
  ```ruby
80
91
  require 'createsend'
@@ -90,7 +101,9 @@ begin
90
101
  clients = cs.clients
91
102
  rescue CreateSend::ExpiredOAuthToken => eot
92
103
  access_token, expires_in, refresh_token = cs.refresh_token
93
- # Save your updated access token, expire in value, and refresh token
104
+ # Here you should save your updated access token, 'expire in' value,
105
+ # and refresh token. `cs` will automatically have the new access token
106
+ # set, so there is no need to set it again.
94
107
  retry unless (tries -= 1).zero?
95
108
  p "Error: #{eot}"
96
109
  rescue Exception => e
@@ -98,6 +111,8 @@ begin
98
111
  end
99
112
  ```
100
113
 
114
+ In addition to raising `CreateSend::ExpiredOAuthToken` when an access token has expired, this library also raises `CreateSend::InvalidOAuthToken` if an invalid access token is used, and raises `CreateSend::RevokedOAuthToken` if a user has revoked the access token being used. This makes it easier for you to handle these cases in your code.
115
+
101
116
  ### Using an API key
102
117
 
103
118
  ```ruby
@@ -154,7 +169,8 @@ auth = {
154
169
  }
155
170
 
156
171
  begin
157
- id = CreateSend::Campaign.create auth, "4a397ccaaa55eb4e6aa1221e1e2d7122", "", "", "", "", "", "", "", [], []
172
+ id = CreateSend::Campaign.create auth, "4a397ccaaa55eb4e6aa1221e1e2d7122",
173
+ "", "", "", "", "", "", "", [], []
158
174
  p "New campaign ID: #{id}"
159
175
  rescue CreateSend::BadRequest => br
160
176
  p "Bad request error: #{br}"
@@ -182,7 +198,7 @@ For example, if you wanted to find out how to call the CreateSend::Subscriber.ad
182
198
  should "add a subscriber with custom fields" do
183
199
  stub_post(@auth, "subscribers/#{@list_id}.json", "add_subscriber.json")
184
200
  custom_fields = [ { :Key => 'website', :Value => 'http://example.com/' } ]
185
- email_address = CreateSend::Subscriber.add @list_id, "subscriber@example.com", "Subscriber", custom_fields, true
201
+ email_address = CreateSend::Subscriber.add @auth, @list_id, "subscriber@example.com", "Subscriber", custom_fields, true
186
202
  email_address.should == "subscriber@example.com"
187
203
  end
188
204
  ```
@@ -193,7 +209,7 @@ Full documentation is hosted by [RubyDoc.info](http://rubydoc.info/gems/createse
193
209
 
194
210
  ## Contributing
195
211
  1. Fork the repository
196
- 2. Make your changes, including tests for your changes.
212
+ 2. Make your changes, including tests for your changes which maintain [coverage][coveralls].
197
213
  3. Ensure that the build passes, by running `bundle exec rake` (CI runs on: `2.0.0`, `1.9.3`, `1.9.2`, `1.8.7`, and `ree`)
198
214
  4. It should go without saying, but do not increment the version number in your commits.
199
215
  5. Submit a pull request.
data/createsend.gemspec CHANGED
@@ -8,6 +8,8 @@ Gem::Specification.new do |s|
8
8
  s.add_development_dependency 'fakeweb', '~> 1.3'
9
9
  s.add_development_dependency 'jnunemaker-matchy', '~> 0.4'
10
10
  s.add_development_dependency 'shoulda', '~> 3.3'
11
+ s.add_development_dependency 'simplecov'
12
+ s.add_development_dependency 'coveralls'
11
13
  s.add_runtime_dependency 'json', '>= 0'
12
14
  s.add_runtime_dependency 'hashie', ['>= 1.2', '< 3']
13
15
  s.add_runtime_dependency 'httparty', '~> 0.10'
@@ -29,9 +29,15 @@ module CreateSend
29
29
  # Raised for HTTP response code of 404
30
30
  class NotFound < ClientError; end
31
31
 
32
+ # Raised for HTTP response code of 401, specifically when an OAuth token
33
+ # in invalid (Code: 120, Message: 'Invalid OAuth Token')
34
+ class InvalidOAuthToken < Unauthorized; end
32
35
  # Raised for HTTP response code of 401, specifically when an OAuth token
33
36
  # has expired (Code: 121, Message: 'Expired OAuth Token')
34
37
  class ExpiredOAuthToken < Unauthorized; end
38
+ # Raised for HTTP response code of 401, specifically when an OAuth token
39
+ # has been revoked (Code: 122, Message: 'Revoked OAuth Token')
40
+ class RevokedOAuthToken < Unauthorized; end
35
41
 
36
42
  # Provides high level CreateSend functionality/data you'll probably need.
37
43
  class CreateSend
@@ -49,7 +55,7 @@ module CreateSend
49
55
  end
50
56
 
51
57
  # Exchange a provided OAuth code for an OAuth access token, 'expires in'
52
- # value and refresh token.
58
+ # value, and refresh token.
53
59
  def self.exchange_token(client_id, client_secret, redirect_uri, code)
54
60
  body = "grant_type=authorization_code"
55
61
  body << "&client_id=#{CGI.escape(client_id.to_s)}"
@@ -67,25 +73,27 @@ module CreateSend
67
73
  [r.access_token, r.expires_in, r.refresh_token]
68
74
  end
69
75
 
76
+ # Refresh an OAuth access token, given an OAuth refresh token.
77
+ # Returns a new access token, 'expires in' value, and refresh token.
78
+ def self.refresh_access_token(refresh_token)
79
+ options = {
80
+ :body => "grant_type=refresh_token&refresh_token=#{refresh_token}" }
81
+ response = HTTParty.post(@@oauth_token_uri, options)
82
+ if response.has_key? 'error' and response.has_key? 'error_description'
83
+ err = "Error refreshing access token: "
84
+ err << "#{response['error']} - #{response['error_description']}"
85
+ raise err
86
+ end
87
+ r = Hashie::Mash.new(response)
88
+ [r.access_token, r.expires_in, r.refresh_token]
89
+ end
90
+
70
91
  def initialize(*args)
71
92
  if args.size > 0
72
93
  auth args.first # Expect auth details as first argument
73
94
  end
74
95
  end
75
96
 
76
- # Deals with an unfortunate situation where responses aren't valid json.
77
- class Parser::DealWithCreateSendInvalidJson < HTTParty::Parser
78
- # The createsend API returns an ID as a string when a 201 Created
79
- # response is returned. Unfortunately this is invalid json.
80
- def parse
81
- begin
82
- super
83
- rescue MultiJson::DecodeError => e
84
- body[1..-2] # Strip surrounding quotes and return as is.
85
- end
86
- end
87
- end
88
- parser Parser::DealWithCreateSendInvalidJson
89
97
  @@base_uri = "https://api.createsend.com/api/v3"
90
98
  @@oauth_base_uri = "https://api.createsend.com/oauth"
91
99
  @@oauth_token_uri = "#{@@oauth_base_uri}/token"
@@ -108,14 +116,12 @@ module CreateSend
108
116
  raise '@auth_details[:refresh_token] does not contain a refresh token.'
109
117
  end
110
118
 
111
- options = {
112
- :body => "grant_type=refresh_token&refresh_token=#{@auth_details[:refresh_token]}" }
113
- response = HTTParty.post(@@oauth_token_uri, options)
114
- r = Hashie::Mash.new(response)
119
+ access_token, expires_in, refresh_token =
120
+ self.class.refresh_access_token @auth_details[:refresh_token]
115
121
  auth({
116
- :access_token => r.access_token,
117
- :refresh_token => r.refresh_token})
118
- [r.access_token, r.expires_in, r.refresh_token]
122
+ :access_token => access_token,
123
+ :refresh_token => refresh_token})
124
+ [access_token, expires_in, refresh_token]
119
125
  end
120
126
 
121
127
  # Gets your CreateSend API key, given your site url, username and password.
@@ -227,10 +233,16 @@ module CreateSend
227
233
  raise BadRequest.new(Hashie::Mash.new response)
228
234
  when 401
229
235
  data = Hashie::Mash.new(response)
230
- if data.Code == 121
231
- raise ExpiredOAuthToken.new(data)
236
+ case data.Code
237
+ when 120
238
+ raise InvalidOAuthToken.new data
239
+ when 121
240
+ raise ExpiredOAuthToken.new data
241
+ when 122
242
+ raise RevokedOAuthToken.new data
243
+ else
244
+ raise Unauthorized.new data
232
245
  end
233
- raise Unauthorized.new(data)
234
246
  when 404
235
247
  raise NotFound.new
236
248
  when 400...500
@@ -73,10 +73,6 @@ module CreateSend
73
73
  super uri_for(action), options
74
74
  end
75
75
 
76
- def put(action, options = {})
77
- super uri_for(action), options
78
- end
79
-
80
76
  def uri_for(action)
81
77
  "/segments/#{segment_id}/#{action}.json"
82
78
  end
@@ -57,7 +57,7 @@ module CreateSend
57
57
  if br.data.ResultData
58
58
  return br.data.ResultData
59
59
  else
60
- raise br
60
+ raise br # Just raise other Bad Request errors
61
61
  end
62
62
  end
63
63
  Hashie::Mash.new(response)
@@ -1,3 +1,3 @@
1
1
  module CreateSend
2
- VERSION = "3.0.0" unless defined?(CreateSend::VERSION)
2
+ VERSION = "3.1.0" unless defined?(CreateSend::VERSION)
3
3
  end
@@ -73,6 +73,32 @@ class CreateSendTest < Test::Unit::TestCase
73
73
  Exception, 'Error exchanging code for access token: invalid_grant - Specified code was invalid or expired')
74
74
  FakeWeb.last_request.body.should == "grant_type=authorization_code&client_id=8998879&client_secret=iou0q9wud0q9wd0q9wid0q9iwd0q9wid0q9wdqwd&redirect_uri=http%3A%2F%2Fexample.com%2Fauth&code=invalidcode"
75
75
  end
76
+
77
+ should "refresh an access token given a refresh token" do
78
+ refresh_token = 'tGzv3JOkF0XG5Qx2TlKWIA'
79
+ options = {
80
+ :body => fixture_file("refresh_oauth_token.json"),
81
+ :content_type => "application/json; charset=utf-8" }
82
+ FakeWeb.register_uri(:post, "https://api.createsend.com/oauth/token", options)
83
+ new_access_token, new_expires_in, new_refresh_token = CreateSend::CreateSend.refresh_access_token refresh_token
84
+
85
+ FakeWeb.last_request.body.should == "grant_type=refresh_token&refresh_token=#{refresh_token}"
86
+ new_access_token.should == "SlAV32hkKG2e12e"
87
+ new_expires_in.should == 1209600
88
+ new_refresh_token.should == "tGzv3JOkF0XG5Qx2TlKWIA"
89
+ end
90
+
91
+ should "raise an error when an attempt to refresh an access token fails" do
92
+ refresh_token = 'invalidrefreshtoken'
93
+ options = {
94
+ :body => fixture_file("oauth_refresh_token_error.json"),
95
+ :content_type => "application/json; charset=utf-8" }
96
+ FakeWeb.register_uri(:post, "https://api.createsend.com/oauth/token", options)
97
+ lambda { access_token, expires_in, refresh_token = CreateSend::CreateSend.refresh_access_token(
98
+ refresh_token) }.should raise_error(
99
+ Exception, 'Error refreshing access token: invalid_grant - Specified refresh_token was invalid or expired')
100
+ FakeWeb.last_request.body.should == "grant_type=refresh_token&refresh_token=#{refresh_token}"
101
+ end
76
102
 
77
103
  should "get a person's api key" do
78
104
  base_uri = "https://api.createsend.com/api/v3"
@@ -134,6 +160,36 @@ class CreateSendTest < Test::Unit::TestCase
134
160
  lambda { new_access_token, new_refresh_token = cs.refresh_token }.should raise_error(
135
161
  Exception, '@auth_details[:refresh_token] does not contain a refresh token.')
136
162
  end
163
+
164
+ should "raise an error when an attempt to refresh the access token is made but the refresh token is invalid" do
165
+ refresh_token = 'invalidrefreshtoken'
166
+ cs = CreateSend::CreateSend.new :access_token => 'any token', :refresh_token => refresh_token
167
+ options = {
168
+ :body => fixture_file("oauth_refresh_token_error.json"),
169
+ :content_type => "application/json; charset=utf-8" }
170
+ FakeWeb.register_uri(:post, "https://api.createsend.com/oauth/token", options)
171
+ lambda { access_token, expires_in, refresh_token = cs.refresh_token }.should raise_error(
172
+ Exception, 'Error refreshing access token: invalid_grant - Specified refresh_token was invalid or expired')
173
+ end
174
+
175
+ should "raise a CreateSend::InvalidOAuthToken error when an access token is invalid" do
176
+ cs = CreateSend::CreateSend.new @auth
177
+ stub_get(@auth, "countries.json", "invalid_oauth_token_api_error.json", ["401", "Unauthorized"])
178
+ lambda { c = cs.countries }.should raise_error(CreateSend::InvalidOAuthToken)
179
+ end
180
+
181
+ should "raise a CreateSend::ExpiredOAuthToken error when an access token is expired" do
182
+ cs = CreateSend::CreateSend.new @auth
183
+ stub_get(@auth, "countries.json", "expired_oauth_token_api_error.json", ["401", "Unauthorized"])
184
+ lambda { c = cs.countries }.should raise_error(CreateSend::ExpiredOAuthToken)
185
+ end
186
+
187
+ should "raise a CreateSend::RevokedOAuthToken error when an access token is revoked" do
188
+ cs = CreateSend::CreateSend.new @auth
189
+ stub_get(@auth, "countries.json", "revoked_oauth_token_api_error.json", ["401", "Unauthorized"])
190
+ lambda { c = cs.countries }.should raise_error(CreateSend::RevokedOAuthToken)
191
+ end
192
+
137
193
  end
138
194
 
139
195
  multiple_contexts "authenticated_using_oauth_context", "authenticated_using_api_key_context" do
@@ -218,6 +274,7 @@ class CreateSendTest < Test::Unit::TestCase
218
274
  { ["400", "Bad Request"] => CreateSend::BadRequest,
219
275
  ["401", "Unauthorized"] => CreateSend::Unauthorized,
220
276
  ["404", "Not Found"] => CreateSend::NotFound,
277
+ ["418", "I'm a teapot"] => CreateSend::ClientError,
221
278
  ["500", "Server Error"] => CreateSend::ServerError
222
279
  }.each do |status, exception|
223
280
  context "#{status.first}, a get" do
@@ -229,7 +286,7 @@ class CreateSendTest < Test::Unit::TestCase
229
286
 
230
287
  context "#{status.first}, a post" do
231
288
  should "raise a #{exception.name} error" do
232
- stub_post(@auth, "clients.json", (status.first == '400' or status.first == '401') ? 'custom_api_error.json' : nil, status)
289
+ stub_post(@auth, "clients.json", (status.first == '400' or status.first == '401') ? 'custom_api_error.json' : nil, status)
233
290
  lambda { CreateSend::Client.create @auth, "Client Company Name",
234
291
  "(GMT+10:00) Canberra, Melbourne, Sydney", "Australia" }.should raise_error(exception)
235
292
  end
@@ -252,23 +309,6 @@ class CreateSendTest < Test::Unit::TestCase
252
309
  end
253
310
  end
254
311
 
255
- context "when authenticated using oauth and the access token has expired" do
256
- setup do
257
- @access_token = '98y98u98u98ue212'
258
- @refresh_token = 'kj9wud09wi0qi0w'
259
- @auth = {
260
- :access_token => @access_token,
261
- :refresh_token => @refresh_token
262
- }
263
- @cs = CreateSend::CreateSend.new @auth
264
- end
265
-
266
- should "raise a CreateSend::ExpiredOAuthToken error" do
267
- stub_get(@auth, "countries.json", "expired_oauth_token_api_error.json", ["401", "Unauthorized"])
268
- lambda { c = @cs.countries }.should raise_error(CreateSend::ExpiredOAuthToken)
269
- end
270
- end
271
-
272
312
  end
273
313
 
274
314
  end
@@ -0,0 +1,4 @@
1
+ {
2
+ "Code": 120,
3
+ "Message": "Invalid OAuth Token"
4
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "error": "invalid_grant",
3
+ "error_description": "Specified refresh_token was invalid or expired"
4
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "Code": 122,
3
+ "Message": "Revoked OAuth Token"
4
+ }
data/test/helper.rb CHANGED
@@ -1,3 +1,12 @@
1
+ require 'simplecov'
2
+ require 'coveralls'
3
+
4
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
5
+ SimpleCov::Formatter::HTMLFormatter,
6
+ Coveralls::SimpleCov::Formatter
7
+ ]
8
+ SimpleCov.start
9
+
1
10
  require 'test/unit'
2
11
  require 'pathname'
3
12
 
@@ -9,7 +18,7 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
9
18
  $LOAD_PATH.unshift(File.dirname(__FILE__))
10
19
  require 'createsend'
11
20
 
12
- FakeWeb.allow_net_connect = false
21
+ FakeWeb.allow_net_connect = %r[^https?://coveralls.io]
13
22
 
14
23
  def fixture_file(filename)
15
24
  return '' if filename == ''
@@ -125,6 +125,18 @@ class SubscriberTest < Test::Unit::TestCase
125
125
  import_result.DuplicateEmailsInSubmission.size.should == 0
126
126
  end
127
127
 
128
+ should "raise a BadRequest error if the import _completely_ fails because of a bad request" do
129
+ # Stub request with 400 Bad Request as the expected response status
130
+ stub_post(@auth, "subscribers/#{@list_id}/import.json", "custom_api_error.json", 400)
131
+ subscribers = [
132
+ { :EmailAddress => "example+1@example", :Name => "Example One" },
133
+ { :EmailAddress => "example+2@example.com", :Name => "Example Two" },
134
+ { :EmailAddress => "example+3@example.com", :Name => "Example Three" },
135
+ ]
136
+ lambda { import_result = CreateSend::Subscriber.import @auth, @list_id, subscribers, true
137
+ }.should raise_error(CreateSend::BadRequest)
138
+ end
139
+
128
140
  should "unsubscribe a subscriber" do
129
141
  stub_post(@auth, "subscribers/#{@subscriber.list_id}/unsubscribe.json", nil)
130
142
  @subscriber.unsubscribe
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: createsend
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
4
+ version: 3.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-25 00:00:00.000000000 Z
12
+ date: 2013-03-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -75,6 +75,38 @@ dependencies:
75
75
  - - ~>
76
76
  - !ruby/object:Gem::Version
77
77
  version: '3.3'
78
+ - !ruby/object:Gem::Dependency
79
+ name: simplecov
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: coveralls
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
78
110
  - !ruby/object:Gem::Dependency
79
111
  name: json
80
112
  requirement: !ruby/object:Gem::Requirement
@@ -136,6 +168,7 @@ executables: []
136
168
  extensions: []
137
169
  extra_rdoc_files: []
138
170
  files:
171
+ - .coveralls.yml
139
172
  - .gitignore
140
173
  - .travis.yml
141
174
  - Gemfile
@@ -200,6 +233,7 @@ files:
200
233
  - test/fixtures/expired_oauth_token_api_error.json
201
234
  - test/fixtures/import_subscribers.json
202
235
  - test/fixtures/import_subscribers_partial_success.json
236
+ - test/fixtures/invalid_oauth_token_api_error.json
203
237
  - test/fixtures/list_details.json
204
238
  - test/fixtures/list_stats.json
205
239
  - test/fixtures/list_webhooks.json
@@ -207,9 +241,11 @@ files:
207
241
  - test/fixtures/listsforemail.json
208
242
  - test/fixtures/oauth_exchange_token.json
209
243
  - test/fixtures/oauth_exchange_token_error.json
244
+ - test/fixtures/oauth_refresh_token_error.json
210
245
  - test/fixtures/people.json
211
246
  - test/fixtures/person_details.json
212
247
  - test/fixtures/refresh_oauth_token.json
248
+ - test/fixtures/revoked_oauth_token_api_error.json
213
249
  - test/fixtures/scheduled_campaigns.json
214
250
  - test/fixtures/segment_details.json
215
251
  - test/fixtures/segment_subscribers.json
@@ -245,7 +281,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
245
281
  version: '0'
246
282
  segments:
247
283
  - 0
248
- hash: 1052265859851701663
284
+ hash: -935543352703407509
249
285
  required_rubygems_version: !ruby/object:Gem::Requirement
250
286
  none: false
251
287
  requirements:
@@ -254,7 +290,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
254
290
  version: 1.3.6
255
291
  requirements: []
256
292
  rubyforge_project:
257
- rubygems_version: 1.8.24
293
+ rubygems_version: 1.8.23
258
294
  signing_key:
259
295
  specification_version: 3
260
296
  summary: A library which implements the complete functionality of the Campaign Monitor
@@ -304,6 +340,7 @@ test_files:
304
340
  - test/fixtures/expired_oauth_token_api_error.json
305
341
  - test/fixtures/import_subscribers.json
306
342
  - test/fixtures/import_subscribers_partial_success.json
343
+ - test/fixtures/invalid_oauth_token_api_error.json
307
344
  - test/fixtures/list_details.json
308
345
  - test/fixtures/list_stats.json
309
346
  - test/fixtures/list_webhooks.json
@@ -311,9 +348,11 @@ test_files:
311
348
  - test/fixtures/listsforemail.json
312
349
  - test/fixtures/oauth_exchange_token.json
313
350
  - test/fixtures/oauth_exchange_token_error.json
351
+ - test/fixtures/oauth_refresh_token_error.json
314
352
  - test/fixtures/people.json
315
353
  - test/fixtures/person_details.json
316
354
  - test/fixtures/refresh_oauth_token.json
355
+ - test/fixtures/revoked_oauth_token_api_error.json
317
356
  - test/fixtures/scheduled_campaigns.json
318
357
  - test/fixtures/segment_details.json
319
358
  - test/fixtures/segment_subscribers.json