SFEley-acts_as_icontact 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,301 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe ActsAsIcontact::Resource do
4
+ it "has a RestClient connection" do
5
+ ActsAsIcontact::Resource.connection.url.should == ActsAsIcontact.connection['resources'].url
6
+ end
7
+
8
+ it "can return all resources for the given URL" do
9
+ ActsAsIcontact::Resource.all.count.should == 12
10
+ end
11
+
12
+ it "can return the first resource" do
13
+ ActsAsIcontact::Resource.first.should be_a_kind_of(ActsAsIcontact::Resource)
14
+ end
15
+
16
+ describe "find method" do
17
+ it "returns a ResourceCollection when given :all" do
18
+ r = ActsAsIcontact::Resource.find(:all)
19
+ r.should be_a_kind_of(ActsAsIcontact::ResourceCollection)
20
+ end
21
+
22
+ it "returns a Resource when given :first" do
23
+ r = ActsAsIcontact::Resource.find(:first)
24
+ r.should be_a_kind_of(ActsAsIcontact::Resource)
25
+ end
26
+
27
+ it "understands the :limit option" do
28
+ r = ActsAsIcontact::Resource.find(:all, :limit => 5)
29
+ r.first.foo.should == "bar"
30
+ r[4].foo.should == "dar"
31
+ r.count.should == 5
32
+ end
33
+
34
+ it "understands the :offset option" do
35
+ r = ActsAsIcontact::Resource.find(:all, :offset => 5)
36
+ r.count.should == 7
37
+ r.first.foo.should == "ear"
38
+ r[6].foo.should == "yar"
39
+ end
40
+
41
+ it "understands multiple options together (:limit and :offset)" do
42
+ r = ActsAsIcontact::Resource.find(:all, :offset => 5, :limit => 5)
43
+ r.first.foo.should == "ear"
44
+ r[4].foo.should == "jar"
45
+ r.count.should == 5
46
+ end
47
+
48
+ it "returns fewer than the limit if it hits the end of the collection" do
49
+ r = ActsAsIcontact::Resource.find(:all, :offset => 10, :limit => 5)
50
+ r.count.should == 2
51
+ r.first.foo.should == "kar"
52
+ r[1].foo.should == "yar"
53
+ end
54
+ end
55
+
56
+ it "knows its properties" do
57
+ r = ActsAsIcontact::Resource.first
58
+ r.foo.should == "bar"
59
+ end
60
+
61
+ it "knows its id if it's not new" do
62
+ r = ActsAsIcontact::Resource.first
63
+ r.id.should == 1
64
+ end
65
+
66
+ it "does not have an id if it's new" do
67
+ r = ActsAsIcontact::Resource.new("foo" => "bar")
68
+ r.id.should be_nil
69
+ end
70
+
71
+ it "has its own connection if it's not new" do
72
+ r = ActsAsIcontact::Resource.first
73
+ r.connection.url.should == ActsAsIcontact.connection['resources/1'].url
74
+ end
75
+
76
+ it "does not have a connection if it's new" do
77
+ r = ActsAsIcontact::Resource.new("foo" => "bar")
78
+ r.connection.should be_nil
79
+ end
80
+
81
+ it "knows its REST base resource" do
82
+ ActsAsIcontact::Resource.base.should == ActsAsIcontact.connection
83
+ end
84
+
85
+ it "knows its primary key" do
86
+ ActsAsIcontact::Resource.primary_key.should == "resourceId"
87
+ end
88
+
89
+ it "knows that the primary key is required on update" do
90
+ ActsAsIcontact::Resource.required_on_update.should == ["resourceId"]
91
+ end
92
+
93
+ it "knows that the primary key MUST NOT be included on create" do
94
+ ActsAsIcontact::Resource.never_on_create.should == ["resourceId"]
95
+ end
96
+
97
+ context "updating records" do
98
+ before(:each) do
99
+ @res = ActsAsIcontact::Resource.first
100
+ end
101
+ it "knows it isn't a new record" do
102
+ @res.should_not be_a_new_record
103
+ end
104
+
105
+ it "can set new values on existing fields" do
106
+ @res.foo = "zar"
107
+ @res.foo.should == "zar"
108
+ end
109
+
110
+ it "can add new fields" do
111
+ @res.zoo = "flar"
112
+ @res.zoo.should == "flar"
113
+ end
114
+
115
+ it "knows the minimum set of properties that changed or must be sent" do
116
+ @res.too = "tar"
117
+ @res.send(:update_fields).should == {"resourceId" => "1", "too" => "tar"}
118
+ end
119
+
120
+ context "with successful save" do
121
+ before(:each) do
122
+ @res.too = "sar"
123
+ @result = @res.save
124
+ end
125
+
126
+ it "returns success" do
127
+ @result.should be_true
128
+ end
129
+
130
+ it "updates itself with the new values" do
131
+ @res.too.should == "sar"
132
+ end
133
+
134
+ it "has no errors" do
135
+ @res.errors.should be_empty
136
+ end
137
+
138
+ it "has no error" do
139
+ @res.error.should be_nil
140
+ end
141
+
142
+ it "can be called with a bang" do
143
+ @res.save!.should be_true
144
+ end
145
+ end
146
+
147
+ context "with failed save but status 200" do
148
+ before(:each) do
149
+ @bad = ActsAsIcontact::Resource.all[1]
150
+ @bad.foo = nil
151
+ @result = @bad.save
152
+ end
153
+
154
+ it "returns failure" do
155
+ @result.should be_false
156
+ end
157
+
158
+ it "returns the errors list" do
159
+ @bad.errors.should == ["You did not provide a foo. foo is a required field. Please provide a foo","This was not a good record"]
160
+ end
161
+
162
+ it "returns the top error" do
163
+ @bad.error.should == "You did not provide a foo. foo is a required field. Please provide a foo"
164
+ end
165
+
166
+ it "throws an exception with a bang" do
167
+ lambda{@bad.save!}.should raise_error(ActsAsIcontact::RecordNotSaved,"You did not provide a foo. foo is a required field. Please provide a foo")
168
+ end
169
+ end
170
+
171
+ context "with failed save on HTTP failure exception" do
172
+ before(:each) do
173
+ @bad = ActsAsIcontact::Resource.all[2]
174
+ @bad.foo = nil
175
+ @result = @bad.save
176
+ end
177
+
178
+ it "returns failure" do
179
+ @result.should be_false
180
+ end
181
+
182
+ it "returns the errors list" do
183
+ @bad.errors.should == ["You did not provide a clue. Clue is a required field. Please provide a clue"]
184
+ end
185
+
186
+ it "returns the top error" do
187
+ @bad.error.should == "You did not provide a clue. Clue is a required field. Please provide a clue"
188
+ end
189
+
190
+ it "throws an exception with a bang" do
191
+ lambda{@bad.save!}.should raise_error(ActsAsIcontact::RecordNotSaved,"You did not provide a clue. Clue is a required field. Please provide a clue")
192
+ end
193
+ end
194
+
195
+ end
196
+
197
+ context "creating records" do
198
+ before(:each) do
199
+ @res = ActsAsIcontact::Resource.new("foo" => "flar", "kroo" => "krar")
200
+ end
201
+ it "knows it's a new record" do
202
+ @res.should be_a_new_record
203
+ end
204
+
205
+ it "can set new values on existing fields" do
206
+ @res.foo = "zar"
207
+ @res.foo.should == "zar"
208
+ end
209
+
210
+ it "can add new fields" do
211
+ @res.zoo = "flar"
212
+ @res.zoo.should == "flar"
213
+ end
214
+
215
+ it "knows the full set of properties that were added or are required" do
216
+ ActsAsIcontact::Resource.stubs(:required_on_create).returns(["shoo"])
217
+ @res.send(:create_fields).should == {"foo" => "flar", "kroo" => "krar", "shoo" => ""}
218
+ end
219
+
220
+ context "with successful save" do
221
+ before(:each) do
222
+ FakeWeb.register_uri(:post, "https://app.beta.icontact.com/icp/resources", :body => %q<{"resources":[{"resourceId":"100","foo":"flar","kroo":"krar","too":"sar"}]}>)
223
+ @res.too = "sar"
224
+ end
225
+
226
+ it "returns success" do
227
+ @res.save.should be_true
228
+ end
229
+
230
+ it "updates itself with the new values" do
231
+ @res.save
232
+ @res.too.should == "sar"
233
+ end
234
+
235
+ it "has no errors" do
236
+ @res.save
237
+ @res.errors.should be_empty
238
+ end
239
+
240
+ it "has no error" do
241
+ @res.save
242
+ @res.error.should be_nil
243
+ end
244
+
245
+ it "can be called with a bang" do
246
+ @res.save!.should be_true
247
+ end
248
+ end
249
+
250
+ context "with failed save but status 200" do
251
+ before(:each) do
252
+ FakeWeb.register_uri(:post, "https://app.beta.icontact.com/icp/resources", :body => %q<{"resources":[],"warnings":["You did not provide a foo. foo is a required field. Please provide a foo","This was not a good record"]}>)
253
+ @res = ActsAsIcontact::Resource.new
254
+ @res.foo = nil
255
+ @result = @res.save
256
+ end
257
+
258
+ it "returns failure" do
259
+ @result.should be_false
260
+ end
261
+
262
+ it "returns the errors list" do
263
+ @res.errors.should == ["You did not provide a foo. foo is a required field. Please provide a foo","This was not a good record"]
264
+ end
265
+
266
+ it "returns the top error" do
267
+ @res.error.should == "You did not provide a foo. foo is a required field. Please provide a foo"
268
+ end
269
+
270
+ it "throws an exception with a bang" do
271
+ lambda{@res.save!}.should raise_error(ActsAsIcontact::RecordNotSaved,"You did not provide a foo. foo is a required field. Please provide a foo")
272
+ end
273
+ end
274
+
275
+ context "with failed save on HTTP failure exception" do
276
+ before(:each) do
277
+ FakeWeb.register_uri(:post, "https://app.beta.icontact.com/icp/resources", :status => ["400","Bad Request"], :body => %q<{"errors":["You did not provide a clue. Clue is a required field. Please provide a clue"]}>)
278
+ @res = ActsAsIcontact::Resource.new
279
+ @res.foo = nil
280
+ @result = @res.save
281
+ end
282
+
283
+ it "returns failure" do
284
+ @result.should be_false
285
+ end
286
+
287
+ it "returns the errors list" do
288
+ @res.errors.should == ["You did not provide a clue. Clue is a required field. Please provide a clue"]
289
+ end
290
+
291
+ it "returns the top error" do
292
+ @res.error.should == "You did not provide a clue. Clue is a required field. Please provide a clue"
293
+ end
294
+
295
+ it "throws an exception with a bang" do
296
+ lambda{@res.save!}.should raise_error(ActsAsIcontact::RecordNotSaved,"You did not provide a clue. Clue is a required field. Please provide a clue")
297
+ end
298
+ end
299
+
300
+ end
301
+ end
@@ -0,0 +1,52 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe ActsAsIcontact, "account_id" do
4
+ it "returns the ID from the first account returned by iContact" do
5
+ ActsAsIcontact.account_id.should == 111111
6
+ end
7
+
8
+ it "can be set by the user" do
9
+ ActsAsIcontact.account_id = 345
10
+ ActsAsIcontact.account_id.should == 345
11
+ end
12
+
13
+ after(:each) do
14
+ ActsAsIcontact.account_id = nil
15
+ end
16
+ end
17
+
18
+
19
+ describe ActsAsIcontact, "account method" do
20
+ it "returns a RestClient resource" do
21
+ ActsAsIcontact.account.should be_a_kind_of(RestClient::Resource)
22
+ end
23
+
24
+ it "builds upon the 'connection' object" do
25
+ ActsAsIcontact.expects(:connection).returns(ActsAsIcontact.instance_variable_get(:@connection))
26
+ ActsAsIcontact.account.should_not be_nil
27
+ end
28
+
29
+ it "can be cleared with the reset_account! method" do
30
+ ActsAsIcontact.reset_account!
31
+ ActsAsIcontact.instance_variable_get(:@account).should be_nil
32
+ end
33
+
34
+ after(:each) do
35
+ ActsAsIcontact.reset_account!
36
+ end
37
+ end
38
+
39
+ describe ActsAsIcontact::Account do
40
+ it "can return all accounts" do
41
+ ActsAsIcontact::Account.all.count.should == 1
42
+ end
43
+
44
+ it "can return the first account" do
45
+ ActsAsIcontact::Account.first.should be_a_kind_of(ActsAsIcontact::Account)
46
+ end
47
+
48
+ it "knows its attributes" do
49
+ a = ActsAsIcontact::Account.first
50
+ a.firstName.should == "Bob"
51
+ end
52
+ end
@@ -0,0 +1,52 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe ActsAsIcontact, "account_id" do
4
+ it "returns the ID from the first client folder returned by iContact" do
5
+ ActsAsIcontact.client_id.should == 222222
6
+ end
7
+
8
+ it "can be set by the user" do
9
+ ActsAsIcontact.client_id = 456
10
+ ActsAsIcontact.client_id.should == 456
11
+ end
12
+
13
+ after(:each) do
14
+ ActsAsIcontact.client_id = nil
15
+ end
16
+ end
17
+
18
+
19
+ describe ActsAsIcontact, "client method" do
20
+ it "returns a RestClient resource" do
21
+ ActsAsIcontact.client.should be_a_kind_of(RestClient::Resource)
22
+ end
23
+
24
+ it "builds upon the 'account' object" do
25
+ ActsAsIcontact.expects(:account).returns(ActsAsIcontact.instance_variable_get(:@account))
26
+ ActsAsIcontact.client.should_not be_nil
27
+ end
28
+
29
+ it "can be cleared with the reset_account! method" do
30
+ ActsAsIcontact.reset_client!
31
+ ActsAsIcontact.instance_variable_get(:@client).should be_nil
32
+ end
33
+
34
+ after(:each) do
35
+ ActsAsIcontact.reset_client!
36
+ end
37
+ end
38
+
39
+ describe ActsAsIcontact::Client do
40
+ it "can return all clients for the given account" do
41
+ ActsAsIcontact::Client.all.count.should == 1
42
+ end
43
+
44
+ it "can return the first client" do
45
+ ActsAsIcontact::Client.first.should be_a_kind_of(ActsAsIcontact::Client)
46
+ end
47
+
48
+ it "knows its properties" do
49
+ c = ActsAsIcontact::Client.first
50
+ c.emailRecipient.should == "bob@example.org"
51
+ end
52
+ end
@@ -0,0 +1,8 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe ActsAsIcontact::Contact do
4
+ it "defaults to a limit of 500"
5
+ it "defaults to searching on all contacts regardless of list status"
6
+ it "throws an exception if a limit higher than 500 is attempted"
7
+
8
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,4 @@
1
+ --colour
2
+ --format progress
3
+ --loadby mtime
4
+ --reverse
@@ -0,0 +1,23 @@
1
+ require 'rubygems'
2
+ require 'fakeweb'
3
+
4
+ FakeWeb.allow_net_connect = false
5
+
6
+ # Resources (this one's a fake stub for pure testing)
7
+ FakeWeb.register_uri(:get, "https://app.beta.icontact.com/icp/resources", :body => %q<{"resources":[{"foo":"bar","resourceId":"1","too":"bar"},{"foo":"aar","resourceId":"2"},{"foo":"far","resourceId":"3"},{"foo":"car","resourceId":"4"},{"foo":"dar","resourceId":"5"},{"foo":"ear","resourceId":"6"},{"foo":"gar","resourceId":"7"},{"foo":"har","resourceId":"8"},{"foo":"iar","resourceId":"9"},{"foo":"jar","resourceId":"10"},{"foo":"kar","resourceId":"11"},{"foo":"yar","resourceId":"12"}],"total":12,"limit":20,"offset":0}>)
8
+ FakeWeb.register_uri(:get, "https://app.beta.icontact.com/icp/resources?limit=5", :body => %q<{"resources":[{"foo":"bar","resourceId":"1"},{"foo":"aar","resourceId":"2"},{"foo":"far","resourceId":"3"},{"foo":"car","resourceId":"4"},{"foo":"dar","resourceId":"5"}],"total":12,"limit":5,"offset":0}>)
9
+ FakeWeb.register_uri(:get, "https://app.beta.icontact.com/icp/resources?offset=5", :body => %q<{"resources":[{"foo":"ear","resourceId":"6"},{"foo":"gar","resourceId":"7"},{"foo":"har","resourceId":"8"},{"foo":"iar","resourceId":"9"},{"foo":"jar","resourceId":"10"},{"foo":"kar","resourceId":"11"},{"foo":"yar","resourceId":"12"}],"total":12,"limit":20,"offset":5}>)
10
+ FakeWeb.register_uri(:get, "https://app.beta.icontact.com/icp/resources?offset=5&limit=5", :body => %q<{"resources":[{"foo":"ear","resourceId":"6"},{"foo":"gar","resourceId":"7"},{"foo":"har","resourceId":"8"},{"foo":"iar","resourceId":"9"},{"foo":"jar","resourceId":"10"}],"total":12,"limit":5,"offset":5}>)
11
+ FakeWeb.register_uri(:get, "https://app.beta.icontact.com/icp/resources?offset=10&limit=5", :body => %q<{"resources":[{"foo":"kar","resourceId":"11"},{"foo":"yar","resourceId":"12"}],"total":12,"limit":5,"offset":10}>)
12
+ FakeWeb.register_uri(:post, "https://app.beta.icontact.com/icp/resources/1", :body => %q<{"resource":{"foo":"bar","resourceId":"1","too":"sar"}}>)
13
+ FakeWeb.register_uri(:post, "https://app.beta.icontact.com/icp/resources/2", :body => %q<{"resource":{},"warnings":["You did not provide a foo. foo is a required field. Please provide a foo","This was not a good record"]}>)
14
+ FakeWeb.register_uri(:post, "https://app.beta.icontact.com/icp/resources/3", :status => ["400","Bad Request"], :body => %q<{"errors":["You did not provide a clue. Clue is a required field. Please provide a clue"]}>)
15
+
16
+ # Time
17
+ FakeWeb.register_uri(:get, "https://app.beta.icontact.com/icp/time", :body => %q<{"time":"2009-07-13T01:28:18-04:00","timestamp":1247462898}>)
18
+
19
+ # Accounts
20
+ FakeWeb.register_uri(:get, "https://app.beta.icontact.com/icp/a", :body => %q<{"accounts":[{"billingStreet":"","billingCity":"","billingState":"","billingPostalCode":"","billingCountry":"","city":"Testville","accountId":"111111","companyName":"","country":"United States","email":"bob@example.org","enabled":1,"fax":"","firstName":"Bob","lastName":"Tester","multiClientFolder":"0","multiUser":"0","phone":"","postalCode":"12345","state":"TN","street":"123 Test Street","title":"","accountType":"0","subscriberLimit":"250000"}],"total":1,"limit":20,"offset":0}>)
21
+
22
+ # Clients
23
+ FakeWeb.register_uri(:get, "https://app.beta.icontact.com/icp/a/111111/c", :body => %q<{"clientfolders":[{"clientFolderId":"222222","logoId":null,"emailRecipient":"bob@example.org"}],"total":1}>)
@@ -0,0 +1,18 @@
1
+ require 'spec'
2
+
3
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
4
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
5
+ require 'acts_as_icontact'
6
+
7
+ require 'spec_fakeweb'
8
+
9
+ Spec::Runner.configure do |config|
10
+ # config.after(:each) do
11
+ # # Make sure we don't run afoul of iContact's rate limiting
12
+ # sleep 1
13
+ # end
14
+ config.mock_with :mocha
15
+
16
+ # Set up some reasonable testing variables
17
+ ActsAsIcontact::Config.mode = :beta
18
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: SFEley-acts_as_icontact
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Stephen Eley
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-07-24 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: "ActsAsIcontact connects Ruby applications with the iContact e-mail marketing service using the iContact API v2.0. Building on the RestClient gem, it offers two significant feature sets: * Simple, consistent access to all resources in the iContact API; and * Automatic synchronizing between ActiveRecord models and iContact contact lists for Rails applications."
17
+ email: sfeley@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README.markdown
24
+ files:
25
+ - .document
26
+ - .gitignore
27
+ - LICENSE
28
+ - README.markdown
29
+ - Rakefile
30
+ - VERSION
31
+ - acts_as_icontact.gemspec
32
+ - lib/acts_as_icontact.rb
33
+ - lib/acts_as_icontact/config.rb
34
+ - lib/acts_as_icontact/connection.rb
35
+ - lib/acts_as_icontact/exceptions.rb
36
+ - lib/acts_as_icontact/resource.rb
37
+ - lib/acts_as_icontact/resource_collection.rb
38
+ - lib/acts_as_icontact/resources/account.rb
39
+ - lib/acts_as_icontact/resources/client.rb
40
+ - lib/acts_as_icontact/resources/contact.rb
41
+ - spec/config_spec.rb
42
+ - spec/connection_spec.rb
43
+ - spec/resource_collection_spec.rb
44
+ - spec/resource_spec.rb
45
+ - spec/resources/account_spec.rb
46
+ - spec/resources/client_spec.rb
47
+ - spec/resources/contact_spec.rb
48
+ - spec/spec.opts
49
+ - spec/spec_fakeweb.rb
50
+ - spec/spec_helper.rb
51
+ has_rdoc: false
52
+ homepage: http://github.com/SFEley/acts_as_icontact
53
+ post_install_message:
54
+ rdoc_options:
55
+ - --charset=UTF-8
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: "0"
63
+ version:
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: "0"
69
+ version:
70
+ requirements: []
71
+
72
+ rubyforge_project: actsasicontact
73
+ rubygems_version: 1.2.0
74
+ signing_key:
75
+ specification_version: 3
76
+ summary: Automatic bridge between iContact e-mail marketing service and Rails ActiveRecord
77
+ test_files:
78
+ - spec/config_spec.rb
79
+ - spec/connection_spec.rb
80
+ - spec/resource_collection_spec.rb
81
+ - spec/resource_spec.rb
82
+ - spec/resources/account_spec.rb
83
+ - spec/resources/client_spec.rb
84
+ - spec/resources/contact_spec.rb
85
+ - spec/spec_fakeweb.rb
86
+ - spec/spec_helper.rb