SFEley-acts_as_icontact 0.1.1

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.
@@ -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