eloqua 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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