eloqua 1.1.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 (72) hide show
  1. data/.gitignore +11 -0
  2. data/.yardopts +2 -0
  3. data/CHANGELOG.md +23 -0
  4. data/Gemfile +3 -0
  5. data/Gemfile.lock +81 -0
  6. data/LICENSE +21 -0
  7. data/README.md +245 -0
  8. data/Rakefile +13 -0
  9. data/TODO.md +8 -0
  10. data/eloqua.gemspec +32 -0
  11. data/eloqua_initializer.tpl.rb +3 -0
  12. data/lib/eloqua.rb +51 -0
  13. data/lib/eloqua/api.rb +119 -0
  14. data/lib/eloqua/api/action.rb +41 -0
  15. data/lib/eloqua/api/service.rb +240 -0
  16. data/lib/eloqua/asset.rb +31 -0
  17. data/lib/eloqua/builder/templates.rb +31 -0
  18. data/lib/eloqua/builder/xml.rb +129 -0
  19. data/lib/eloqua/entity.rb +72 -0
  20. data/lib/eloqua/exceptions.rb +5 -0
  21. data/lib/eloqua/helper/attribute_map.rb +78 -0
  22. data/lib/eloqua/query.rb +291 -0
  23. data/lib/eloqua/remote_object.rb +274 -0
  24. data/lib/eloqua/version.rb +3 -0
  25. data/lib/eloqua/wsdl/action.wsdl +1 -0
  26. data/lib/eloqua/wsdl/data.wsdl +1 -0
  27. data/lib/eloqua/wsdl/email.wsdl +1 -0
  28. data/lib/eloqua/wsdl/service.wsdl +1 -0
  29. data/lib/tasks/test.rake +24 -0
  30. data/rspec.watchr +74 -0
  31. data/spec/fixtures/add_group_member/success.xml +18 -0
  32. data/spec/fixtures/create/contact_duplicate.xml +30 -0
  33. data/spec/fixtures/create/contact_success.xml +25 -0
  34. data/spec/fixtures/create_asset/failure.xml +30 -0
  35. data/spec/fixtures/create_asset/group_success.xml +25 -0
  36. data/spec/fixtures/delete_asset/access_deny.xml +31 -0
  37. data/spec/fixtures/describe_asset/success.xml +72 -0
  38. data/spec/fixtures/describe_asset_type/success.xml +23 -0
  39. data/spec/fixtures/describe_entity/success.xml +54 -0
  40. data/spec/fixtures/describe_entity_type/success.xml +45 -0
  41. data/spec/fixtures/get_member_count_in_step_by_status/success.xml +15 -0
  42. data/spec/fixtures/list_asset_types/success.xml +28 -0
  43. data/spec/fixtures/list_entity_types/success.xml +21 -0
  44. data/spec/fixtures/list_group_membership/success.xml +25 -0
  45. data/spec/fixtures/list_members_in_step_by_status/success.xml +15 -0
  46. data/spec/fixtures/query/contact_email_one.xml +38 -0
  47. data/spec/fixtures/query/contact_email_two.xml +56 -0
  48. data/spec/fixtures/query/contact_missing.xml +19 -0
  49. data/spec/fixtures/query/fault.xml +43 -0
  50. data/spec/fixtures/remove_group_member/success.xml +18 -0
  51. data/spec/fixtures/retrieve/contact_missing.xml +17 -0
  52. data/spec/fixtures/retrieve/contact_multiple.xml +3460 -0
  53. data/spec/fixtures/retrieve/contact_single.xml +38 -0
  54. data/spec/fixtures/retrieve_asset/failure.xml +17 -0
  55. data/spec/fixtures/retrieve_asset/success.xml +50 -0
  56. data/spec/fixtures/update/contact_success.xml +26 -0
  57. data/spec/lib/eloqua/api/action_spec.rb +36 -0
  58. data/spec/lib/eloqua/api/service_spec.rb +498 -0
  59. data/spec/lib/eloqua/api_spec.rb +133 -0
  60. data/spec/lib/eloqua/asset_spec.rb +63 -0
  61. data/spec/lib/eloqua/builder/templates_spec.rb +68 -0
  62. data/spec/lib/eloqua/builder/xml_spec.rb +254 -0
  63. data/spec/lib/eloqua/entity_spec.rb +224 -0
  64. data/spec/lib/eloqua/helper/attribute_map_spec.rb +14 -0
  65. data/spec/lib/eloqua/query_spec.rb +596 -0
  66. data/spec/lib/eloqua/remote_object_spec.rb +742 -0
  67. data/spec/lib/eloqua_spec.rb +171 -0
  68. data/spec/shared/attribute_map.rb +173 -0
  69. data/spec/shared/class_to_api_delegation.rb +50 -0
  70. data/spec/spec_helper.rb +48 -0
  71. data/spec/support/helper.rb +73 -0
  72. metadata +366 -0
@@ -0,0 +1,224 @@
1
+ require 'spec_helper'
2
+
3
+ describe Eloqua::Entity do
4
+
5
+ subject do
6
+ Class.new(Eloqua::Entity) do
7
+ self.remote_type = Eloqua::Api.remote_type('Contact')
8
+ def self.name
9
+ 'ContactEntity'
10
+ end
11
+ end
12
+ end
13
+
14
+ let(:asset) do
15
+ Class.new(Eloqua::Asset) do
16
+ self.remote_type = api.remote_type('0', 'ContactGroup', '0')
17
+ end
18
+ end
19
+
20
+ let(:object) do
21
+ subject.new({:id => 1}, :remote)
22
+ end
23
+
24
+ it_behaves_like 'class level delegation of remote operations for', :entity
25
+
26
+ context "membership methods" do
27
+
28
+ context "#add_membership" do
29
+ it 'should call remove_member on given asset' do
30
+ flexmock(asset).should_receive(:add_member).with(object).once
31
+ object.add_membership(asset)
32
+ end
33
+ end
34
+
35
+ context "#remove_membership" do
36
+ it 'should call remove_member on given asset' do
37
+ flexmock(asset).should_receive(:remove_member).with(object).once
38
+ object.remove_membership(asset)
39
+ end
40
+ end
41
+
42
+
43
+ end
44
+
45
+ context "#list_memberships" do
46
+
47
+ it 'should delegate call to class level with current id' do
48
+ flexmock(subject).should_receive(:list_memberships).with(1).once
49
+ object.list_memberships
50
+ end
51
+
52
+ end
53
+
54
+ context "#self.list_memberships" do
55
+
56
+ let(:mock_memberships) do
57
+ list = []
58
+
59
+ 3.times do |n|
60
+ list << {:id => n, :type => 'ContactGroup', :name => "ContactGroup#{n}"}
61
+ end
62
+
63
+ list
64
+ end
65
+
66
+
67
+ it 'should delegate call to api' do
68
+ flexmock(subject.api).should_receive(:list_memberships).with(subject.remote_type, 1).once
69
+ subject.list_memberships(1)
70
+ end
71
+
72
+ it "should index memberships by id" do
73
+ flexmock(subject.api).should_receive(:list_memberships).with(subject.remote_type, 1).once.\
74
+ and_return(mock_memberships)
75
+
76
+ memberships = subject.list_memberships(1)
77
+ memberships.should be_an(Hash)
78
+ memberships.each do |key, membership|
79
+ key.should == membership[:id]
80
+ end
81
+ end
82
+
83
+ context "when low level api returns nil" do
84
+
85
+ before do
86
+ flexmock(subject.api).should_receive(:list_memberships).\
87
+ with(subject.remote_type, 1).\
88
+ once.and_return(nil)
89
+ end
90
+
91
+ it "should return an empty hash" do
92
+ subject.list_memberships(1).should == {}
93
+ end
94
+ end
95
+
96
+ end
97
+
98
+ context "#self.remote_group" do
99
+ specify { subject.remote_group.should == :entity }
100
+ end
101
+
102
+
103
+ context '#self.where' do
104
+ let(:expected_query) { "C_EmailAddress='james@lightsofapollo.com'" }
105
+ let(:klass) do
106
+ Class.new(subject) do
107
+ map :C_EmailAddress => :email
108
+ end
109
+ end
110
+
111
+ context "when given no arguments" do
112
+ it "should return an Eloqua::Query object" do
113
+ query = subject.where
114
+ query.should be_an(Eloqua::Query)
115
+ query.remote_object.should == subject
116
+ end
117
+ end
118
+
119
+ context "when successfuly finding single result with all fields" do
120
+
121
+ let(:input) { {:email => 'james@lightsofapollo.com'} }
122
+ let(:xml_body) do
123
+ api = subject.api
124
+ xml! do |xml|
125
+ xml.eloquaType do
126
+ xml.template!(:object_type, api.remote_type('Contact'))
127
+ end
128
+ xml.searchQuery(expected_query)
129
+ xml.pageNumber(1)
130
+ xml.pageSize(200)
131
+ end
132
+ end
133
+
134
+ before do
135
+ mock_eloqua_request(:query, :contact_email_one).\
136
+ with(:service, :query, xml_body)
137
+
138
+ @results = klass.where(input)
139
+ end
140
+
141
+ it 'should return an array' do
142
+ @results.class.should == Array
143
+ end
144
+
145
+ it 'should return an array of objects' do
146
+ @results.first.class.should == klass
147
+ end
148
+
149
+ it 'should have attributes acording to XML file (query/contact_email_one.xml)' do
150
+ record = @results.first
151
+ expected = {
152
+ :id => '1',
153
+ :email => 'james@lightsofapollo.com',
154
+ :first_name => 'James'
155
+ }
156
+ record.attributes.length.should == 3
157
+ expected.each do |attr, value|
158
+ record.attributes[attr].should == value
159
+ end
160
+ end
161
+
162
+ end
163
+
164
+ context "when successfuly finding results with limited number of fields" do
165
+ let(:input) { [{:email => 'james@lightsofapollo.com'}, [:email]] }
166
+ let(:xml_body) do
167
+ api = subject.api
168
+ xml! do |xml|
169
+ xml.eloquaType do
170
+ xml.template!(:object_type, api.remote_type('Contact'))
171
+ end
172
+ xml.searchQuery(expected_query)
173
+ xml.fieldNames do
174
+ xml.template!(:array, ['C_EmailAddress'])
175
+ end
176
+ xml.pageNumber(1)
177
+ xml.pageSize(200)
178
+ end
179
+ end
180
+
181
+ before do
182
+ mock_eloqua_request(:query, :contact_email_one).\
183
+ with(:service, :query, xml_body)
184
+
185
+ @results = klass.where(*input)
186
+ end
187
+
188
+ # HINT- This is actually asserted above in the mock_eloqua_request
189
+ it "should request that the results only return the C_EmailAddress field" do
190
+ @results.should be_true
191
+ end
192
+
193
+ end
194
+
195
+ context "when rows are not found" do
196
+ let(:input) { {:email => 'james@lightsofapollo.com'} }
197
+ let(:xml_body) do
198
+ api = subject.api
199
+
200
+ xml! do |xml|
201
+ xml.eloquaType do
202
+ xml.template!(:object_type, api.remote_type('Contact'))
203
+ end
204
+ xml.searchQuery("C_EmailAddress='james@lightsofapollo.com'")
205
+ xml.pageNumber(1)
206
+ xml.pageSize(200)
207
+ end
208
+ end
209
+
210
+ before do
211
+ mock_eloqua_request(:query, :contact_missing).\
212
+ with(:service, :query, xml_body)
213
+
214
+ @results = klass.where(input)
215
+ end
216
+
217
+ specify { @results.should be_false }
218
+
219
+ end
220
+
221
+ end
222
+
223
+
224
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+ require 'eloqua/remote_object'
3
+
4
+ describe Eloqua::Helper::AttributeMap do
5
+
6
+ subject do
7
+ Class.new do
8
+ include Eloqua::Helper::AttributeMap
9
+ end
10
+ end
11
+
12
+ it_behaves_like 'uses attribute map'
13
+
14
+ end
@@ -0,0 +1,596 @@
1
+ require 'spec_helper'
2
+ require 'eloqua/query'
3
+
4
+
5
+ shared_examples_for "chainable query attribute that resets has_requested?" do |method, given|
6
+ context "##{method}" do
7
+
8
+ it "should act like a getter when given no value" do
9
+ subject.send(method).should == subject.instance_variable_get("@#{method}".to_sym)
10
+ end
11
+
12
+ it "should act like a setter and return self when given a value" do
13
+ subject.send(method, given).should === subject
14
+ subject.send(method).should == given
15
+ end
16
+
17
+ context "when modifying #{method} after a request" do
18
+
19
+ before do
20
+ simple_request!
21
+ end
22
+
23
+ it "should reset has_requested to false" do
24
+ subject.should have_requested
25
+ subject.send(method, given)
26
+ subject.should_not have_requested
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+ end
33
+
34
+ describe Eloqua::Query do
35
+ subject { klass.new(entity) }
36
+ let(:klass) { Eloqua::Query }
37
+ let(:expected_query) { "C_EmailAddress='*' AND Date>'2011-04-20'" }
38
+
39
+ let(:entity) do
40
+ Class.new(Eloqua::Entity) do
41
+ self.remote_type = api.remote_type('Contact')
42
+ map :C_EmailAddress => :email
43
+ end
44
+ end
45
+
46
+ before do
47
+ subject.request_delay = false
48
+ end
49
+
50
+ after { Timecop.return }
51
+
52
+ def mock_query_hash(records, pages)
53
+ entities = []
54
+ records.to_i.times do |i|
55
+ entities << {:field_value_collection=>
56
+ {:entity_fields=>
57
+ [{:value=>"james@lightsofapollo.com",
58
+ :internal_name=>"C_EmailAddress"},
59
+ {:value=>"James", :internal_name=>"C_FirstName"}]},
60
+ :id=>"#{i + 1}",
61
+ :entity_type=>{:type=>"Base", :name=>"Contact", :id=>"0"}
62
+ }
63
+ end
64
+ {
65
+ :total_pages=>"#{pages}",
66
+ :total_records=>"#{records * pages}",
67
+ :entities=>{ :dynamic_entity => entities },
68
+ :i=>"http://www.w3.org/2001/XMLSchema-instance"
69
+ }
70
+ end
71
+
72
+ def conditions!(query = nil)
73
+ query = (query.nil?)? subject : query
74
+ query.\
75
+ on(:email, '=', '*').\
76
+ on('Date', '>', '2011-04-20')
77
+ end
78
+
79
+ def limit!(query = nil, page = 1)
80
+ query = (query.nil?)? subject : query
81
+ query.page(page).limit(200)
82
+ end
83
+
84
+ def expect_simple_request(page = 1)
85
+ xml_body = xml! do |xml|
86
+ api = subject.remote_object.api
87
+ xml.eloquaType do
88
+ xml.template!(:object_type, api.remote_type('Contact'))
89
+ end
90
+ xml.searchQuery(expected_query)
91
+ xml.pageNumber(page)
92
+ xml.pageSize(200)
93
+ end
94
+ mock_eloqua_request(:query, :contact_email_one).\
95
+ with(:service, :query, xml_body).globally.ordered.once
96
+ end
97
+
98
+ def round_1(number)
99
+ sprintf('%.1f', number).to_f
100
+ end
101
+
102
+ def expect_request_pages(records, pages, current_page = nil, limit = 200)
103
+ remote_results = mock_query_hash(records, pages)
104
+ mock = mock_api_request(remote_results)
105
+ if(current_page)
106
+ xml_body = xml! do |xml|
107
+ api = subject.remote_object.api
108
+ xml.eloquaType do
109
+ xml.template!(:object_type, api.remote_type('Contact'))
110
+ end
111
+ xml.searchQuery(expected_query)
112
+ xml.pageNumber(current_page)
113
+ xml.pageSize(limit)
114
+ end
115
+ mock.with(:query, xml_body)
116
+ end
117
+ mock
118
+ end
119
+
120
+ def simple_request!(page = 1)
121
+ expect_simple_request(page)
122
+ subject.clear_conditions!
123
+ conditions!
124
+ limit!(nil, page)
125
+ subject.request!
126
+ end
127
+
128
+
129
+ context "#test.mock_query_hash" do
130
+ it "should have proper number of pages" do
131
+ mock = mock_query_hash(20, 20)
132
+ mock[:total_pages].should == "20"
133
+ mock[:total_records].should == (20 * 20).to_s
134
+ mock[:entities][:dynamic_entity].length.should == 20
135
+ end
136
+ end
137
+
138
+
139
+ context "#api" do
140
+ it "should delegate #api to remote object" do
141
+ flexmock(subject.remote_object).should_receive(:api).once
142
+ subject.api
143
+ end
144
+ end
145
+
146
+ context "#new" do
147
+
148
+ it 'should raise ArgumentError when given anything but an Eloqua::RemoteObject' do
149
+ lambda { klass.new({}) }.should raise_exception(ArgumentError, /must provide an Eloqua::RemoteObject /)
150
+ end
151
+
152
+ context "when initializing with Eloqua::RemoteObject" do
153
+ it "should have saved remote subject to #remote_object" do
154
+ subject.remote_object.should == entity
155
+ end
156
+
157
+ it "should preset the #page to 1" do
158
+ subject.page.should == 1
159
+ end
160
+
161
+ it "should preset #limit to 200" do
162
+ subject.limit.should == 200
163
+ end
164
+
165
+ it "should have an empty collection" do
166
+ subject.collection.should be_empty
167
+ end
168
+
169
+ it "should have no conditions" do
170
+ subject.conditions.should be_empty
171
+ end
172
+
173
+ it "should #fields should be nil" do
174
+ subject.fields.should be_nil
175
+ end
176
+
177
+ it "should not have requested yet" do
178
+ subject.should_not have_requested
179
+ end
180
+
181
+ end
182
+
183
+ end
184
+
185
+ it_behaves_like "chainable query attribute that resets has_requested?", :page, 5
186
+ it_behaves_like "chainable query attribute that resets has_requested?", :limit, 5
187
+ it_behaves_like "chainable query attribute that resets has_requested?", :fields, [:email, 'Date']
188
+
189
+ context "#on" do
190
+
191
+ context "adding a single condition" do
192
+ before do
193
+ @result = subject.on(:email, '=', '*')
194
+ end
195
+
196
+ it "should return self" do
197
+ @result.should === subject
198
+ end
199
+
200
+ it "should have added condition" do
201
+ subject.conditions.length.should == 1
202
+ end
203
+
204
+ it "should have added condition field, type and value" do
205
+ subject.conditions.first.should == {
206
+ :field => :email,
207
+ :type => '=',
208
+ :value => '*'
209
+ }
210
+ end
211
+
212
+ end
213
+
214
+ context "adding additional condition after request" do
215
+ it "should have not made request" do
216
+ subject.should_not have_requested
217
+ end
218
+
219
+ context "after request" do
220
+
221
+ before do
222
+ simple_request!
223
+ end
224
+
225
+ it "should have requested" do
226
+ subject.should have_requested
227
+ end
228
+
229
+ it "should reset have requested when adding new condition" do
230
+ subject.on(:email, '=', 'ouch')
231
+ subject.should_not have_requested
232
+ end
233
+
234
+ end
235
+
236
+ end
237
+
238
+ end
239
+
240
+ context "#clear_conditions!" do
241
+ it "should clear conditions added by on" do
242
+ subject.on(:email, '=', '1')
243
+ subject.conditions.length.should == 1
244
+ subject.clear_conditions!
245
+ subject.conditions.length.should == 0
246
+ end
247
+
248
+ it "should reset #has_requested?" do
249
+ simple_request!
250
+ subject.should have_requested
251
+ subject.clear_conditions!
252
+ subject.should_not have_requested
253
+ end
254
+
255
+ end
256
+
257
+
258
+
259
+ context "#build_query" do
260
+ let(:entity) do
261
+ Class.new(Eloqua::Entity) do
262
+ map :C_EmailAddress => :email
263
+ remote_type = api.remote_type('Contact')
264
+ end
265
+ end
266
+
267
+ before do
268
+ query = klass.new(entity)
269
+ conditions!(query)
270
+ @result = query.send(:build_query)
271
+ end
272
+
273
+ specify { @result.should == expected_query }
274
+ end
275
+
276
+ context "#request" do
277
+ context "when requesting without limiting the fields and remote returns one result" do
278
+ before do
279
+ @result = simple_request!
280
+ end
281
+
282
+ it "should return an array of objects" do
283
+ @result.should be_an(Array)
284
+ @result.first.should be_an(Eloqua::Entity)
285
+ end
286
+
287
+ it "should now mark query as #has_requested?" do
288
+ subject.should have_requested
289
+ end
290
+
291
+ it "should have added results to collection" do
292
+ subject.collection.length.should == 1
293
+ end
294
+
295
+ it "should have set total pages to 1" do
296
+ subject.total_pages.should == 1
297
+ end
298
+
299
+ it 'should have attributes acording to XML file (query/contact_email_one.xml)' do
300
+ record = subject.collection.first
301
+ record.should be_an(Eloqua::Entity)
302
+ expected = {
303
+ :id => '1',
304
+ :email => 'james@lightsofapollo.com',
305
+ :first_name => 'James'
306
+ }
307
+ record.attributes.length.should == 3
308
+ expected.each do |attr, value|
309
+ record.attributes[attr].should == value
310
+ end
311
+ end
312
+
313
+ context "when has_requested? is true" do
314
+ it "should send a remote request again" do
315
+ flexmock(subject.api).should_receive(:send_remote_request).never
316
+ subject.should have_requested
317
+ subject.request!
318
+ end
319
+ end
320
+
321
+ end
322
+
323
+ context "when successfuly finding results with limited number of fields" do
324
+ let(:xml_body) do
325
+ api = subject.api
326
+ xml! do |xml|
327
+ xml.eloquaType do
328
+ xml.template!(:object_type, api.remote_type('Contact'))
329
+ end
330
+ xml.searchQuery(expected_query)
331
+ xml.fieldNames do
332
+ xml.template!(:array, ['C_EmailAddress'])
333
+ end
334
+ xml.pageNumber(1)
335
+ xml.pageSize(200)
336
+ end
337
+ end
338
+
339
+ before do
340
+ mock_eloqua_request(:query, :contact_email_one).\
341
+ with(:service, :query, xml_body)
342
+
343
+ conditions!
344
+
345
+ @result = subject.fields([:email]).request!
346
+ end
347
+
348
+ # HINT- This is actually asserted above in the mock_eloqua_request
349
+ it "should request that the results only return the C_EmailAddress field" do
350
+ subject.should have_requested
351
+ end
352
+
353
+ end
354
+
355
+ context "when rows are not found" do
356
+ let(:xml_body) do
357
+ api = subject.api
358
+
359
+ xml! do |xml|
360
+ xml.eloquaType do
361
+ xml.template!(:object_type, api.remote_type('Contact'))
362
+ end
363
+ xml.searchQuery(expected_query)
364
+ xml.pageNumber(1)
365
+ xml.pageSize(200)
366
+ end
367
+ end
368
+
369
+ before do
370
+ mock_eloqua_request(:query, :contact_missing).\
371
+ with(:service, :query, xml_body)
372
+
373
+ conditions!
374
+ subject.request!
375
+ end
376
+
377
+ it "should an empty collection" do
378
+ subject.collection.should be_empty
379
+ end
380
+
381
+ it "should have requested" do
382
+ subject.should have_requested
383
+ end
384
+
385
+ it "should have total pages as 0" do
386
+ subject.total_pages.should == 0
387
+ end
388
+
389
+ end
390
+
391
+ # Eloqua has a request limit of 1 per second on queries.
392
+ # The goal of this spec is to specify that no requests run
393
+ # for at least a second after the first request.
394
+ context "when making a request within the time of the request delay" do
395
+
396
+ it "should save the initial request time to query_started" do
397
+ Timecop.freeze(Time.now) do
398
+ simple_request!
399
+ subject.send(:query_started).should == Time.now
400
+ end
401
+ end
402
+
403
+ context "with #request_delay of 1" do
404
+ before { subject.request_delay = 1 }
405
+ let(:now) { Time.now }
406
+
407
+ it "should call sleep when requesting again within the delay" do
408
+ Timecop.freeze(now) do
409
+ simple_request! # Setup initial request
410
+
411
+ flexmock(subject).should_receive(:sleep).with(FlexMock.on {|arg| round_1(arg) == 0.9 }).once
412
+ Timecop.travel(now + 0.1)
413
+ simple_request!(2)
414
+ end
415
+ end
416
+
417
+ it "should not call sleep when request has been made after delay" do
418
+ Timecop.freeze(now) do
419
+ simple_request!
420
+ flexmock(subject).should_receive(:sleep).never
421
+ Timecop.travel(now + 1.1)
422
+ simple_request!(2)
423
+ end
424
+ end
425
+
426
+
427
+ end
428
+ end
429
+
430
+ end
431
+
432
+ context "#wait_for_request_delay" do
433
+
434
+ it "should return false when request_delay is false" do
435
+ subject.request_delay = false
436
+ simple_request! # set query start time
437
+
438
+ subject.wait_for_request_delay.should == false
439
+ end
440
+
441
+ it "should retun false when query_started is false" do
442
+ subject.request_delay = 1
443
+ subject.wait_for_request_delay.should == false
444
+ end
445
+
446
+ it "should the amount of time to wait as a fraction when a delay is required" do
447
+ subject.request_delay = 1
448
+ now = Time.now
449
+ Timecop.freeze(now) do
450
+ simple_request!
451
+ Timecop.travel(now + 0.1)
452
+ delay = round_1(subject.wait_for_request_delay)
453
+ delay.should == 0.9
454
+ end
455
+ end
456
+
457
+ end
458
+
459
+ context "#all" do
460
+
461
+ context "when request has not yet been made" do
462
+
463
+ before do
464
+ expect_simple_request
465
+ conditions!
466
+ limit!
467
+
468
+ @result = subject.all
469
+ end
470
+
471
+ it "should have made request" do
472
+ subject.should have_requested
473
+ end
474
+
475
+ it "should return an array of objects" do
476
+ @result.should be_an(Array)
477
+ @result.first.should be_an(Eloqua::Entity)
478
+ end
479
+
480
+ end
481
+
482
+ end
483
+
484
+ context "#each" do
485
+ before do
486
+ expect_request_pages(20, 1)
487
+ conditions!
488
+ limit!
489
+ end
490
+
491
+ it "should iterator through each result and mark query as requested" do
492
+ subject.should_not have_requested
493
+ ids = []
494
+ subject.each do |record|
495
+ record.should be_an(Eloqua::Entity)
496
+ ids << record.id
497
+ end
498
+ ids.length.should == 20
499
+ ids.should == ('1'..'20').to_a
500
+ subject.should have_requested
501
+ end
502
+
503
+ end
504
+
505
+
506
+ context "#each_page" do
507
+
508
+ let(:total) { 10 }
509
+ let(:pages) { 5 }
510
+ let(:limit) { 2 }
511
+ let(:expected_range) { (1..5).to_a }
512
+ let(:expected_ids) { (['1', '2'] * 5) }
513
+
514
+ context "when iterating through 5 pages of results" do
515
+
516
+ before do
517
+
518
+ # - Clarity over brief
519
+ expect_request_pages(limit, pages, 1, limit)
520
+ expect_request_pages(limit, pages, 2, limit)
521
+ expect_request_pages(limit, pages, 3, limit)
522
+ expect_request_pages(limit, pages, 4, limit)
523
+ expect_request_pages(limit, pages, 5, limit)
524
+
525
+ @ids = []
526
+ @pages = []
527
+
528
+ conditions!
529
+ subject.limit(limit)
530
+
531
+ last_page = 0
532
+ subject.each_page do |record|
533
+ @ids << record.id
534
+
535
+ if(last_page != subject.page)
536
+ @pages << subject.page
537
+ last_page = subject.page
538
+ end
539
+ end
540
+ end
541
+
542
+ it "should have iterated through 5 pages" do
543
+ @pages.should == expected_range
544
+ end
545
+
546
+ it "should have iterated through all records in each page" do
547
+ @ids.length.should == total
548
+ @ids.should == expected_ids
549
+ end
550
+
551
+ end
552
+
553
+ context "when iterating through 5 out of 10 pages" do
554
+
555
+ let(:pages) { 10 }
556
+
557
+ before do
558
+ # - Clarity over brief
559
+ expect_request_pages(limit, pages, 1, limit)
560
+ expect_request_pages(limit, pages, 2, limit)
561
+ expect_request_pages(limit, pages, 3, limit)
562
+ expect_request_pages(limit, pages, 4, limit)
563
+ expect_request_pages(limit, pages, 5, limit)
564
+
565
+ @ids = []
566
+ @pages = []
567
+
568
+ conditions!
569
+ subject.limit(limit)
570
+
571
+ last_page = 0
572
+ # Max of 5 pages
573
+ subject.each_page(5) do |record|
574
+ @ids << record.id
575
+
576
+ if(last_page != subject.page)
577
+ @pages << subject.page
578
+ last_page = subject.page
579
+ end
580
+ end
581
+ end
582
+
583
+ it "should have iterated through 5 pages" do
584
+ @pages.should == expected_range
585
+ end
586
+
587
+ it "should have iterated through all records in each page" do
588
+ @ids.length.should == total
589
+ @ids.should == expected_ids
590
+ end
591
+
592
+ end
593
+
594
+ end
595
+
596
+ end