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,38 @@
1
+ <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
2
+ <s:Header>
3
+ <o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
4
+ <u:Timestamp u:Id="_0">
5
+ <u:Created>2011-03-30T18:43:15.335Z</u:Created>
6
+ <u:Expires>2011-03-30T18:48:15.335Z</u:Expires>
7
+ </u:Timestamp>
8
+ </o:Security>
9
+ </s:Header>
10
+ <s:Body>
11
+ <RetrieveResponse xmlns="https://secure.eloqua.com/API/1.2">
12
+ <RetrieveResult xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
13
+ <DynamicEntity>
14
+ <EntityType>
15
+ <ID>0</ID>
16
+ <Name>Contact</Name>
17
+ <Type>Base</Type>
18
+ </EntityType>
19
+ <FieldValueCollection>
20
+ <EntityFields>
21
+ <InternalName>C_EmailAddress</InternalName>
22
+ <Value>test@email.com</Value>
23
+ </EntityFields>
24
+ <EntityFields>
25
+ <InternalName>C_FirstName</InternalName>
26
+ <Value>First</Value>
27
+ </EntityFields>
28
+ <EntityFields>
29
+ <InternalName>C_LastName</InternalName>
30
+ <Value>Last</Value>
31
+ </EntityFields>
32
+ </FieldValueCollection>
33
+ <Id>1</Id>
34
+ </DynamicEntity>
35
+ </RetrieveResult>
36
+ </RetrieveResponse>
37
+ </s:Body>
38
+ </s:Envelope>
@@ -0,0 +1,17 @@
1
+ <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
2
+ <s:Header>
3
+ <o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
4
+ <u:Timestamp u:Id="_0">
5
+ <u:Created>2011-04-12T01:51:52.684Z</u:Created>
6
+ <u:Expires>2011-04-12T01:56:52.684Z</u:Expires>
7
+ </u:Timestamp>
8
+ </o:Security>
9
+ </s:Header>
10
+ <s:Body>
11
+ <RetrieveAssetResponse xmlns="https://secure.eloqua.com/API/1.2">
12
+ <RetrieveAssetResult xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
13
+ <DynamicAsset i:nil="true"/>
14
+ </RetrieveAssetResult>
15
+ </RetrieveAssetResponse>
16
+ </s:Body>
17
+ </s:Envelope>
@@ -0,0 +1,50 @@
1
+ <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
2
+ <s:Header>
3
+ <o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
4
+ <u:Timestamp u:Id="_0">
5
+ <u:Created>2011-04-12T01:50:37.574Z</u:Created>
6
+ <u:Expires>2011-04-12T01:55:37.574Z</u:Expires>
7
+ </u:Timestamp>
8
+ </o:Security>
9
+ </s:Header>
10
+ <s:Body>
11
+ <RetrieveAssetResponse xmlns="https://secure.eloqua.com/API/1.2">
12
+ <RetrieveAssetResult xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
13
+ <DynamicAsset>
14
+ <AssetType>
15
+ <ID>0</ID>
16
+ <Name>ContactGroupName</Name>
17
+ <Type>ContactGroup</Type>
18
+ </AssetType>
19
+ <FieldValueCollection>
20
+ <AssetFields>
21
+ <InternalName>name</InternalName>
22
+ <Value>James created this contact group (again) !</Value>
23
+ </AssetFields>
24
+ <AssetFields>
25
+ <InternalName>description</InternalName>
26
+ <Value>through the api =)</Value>
27
+ </AssetFields>
28
+ <AssetFields>
29
+ <InternalName>createdby</InternalName>
30
+ <Value>Radius.API</Value>
31
+ </AssetFields>
32
+ <AssetFields>
33
+ <InternalName>createdat</InternalName>
34
+ <Value>4/11/2011 9:36:34 PM</Value>
35
+ </AssetFields>
36
+ <AssetFields>
37
+ <InternalName>modifiedby</InternalName>
38
+ <Value>Radius.API</Value>
39
+ </AssetFields>
40
+ <AssetFields>
41
+ <InternalName>modifiedat</InternalName>
42
+ <Value>4/11/2011 9:36:34 PM</Value>
43
+ </AssetFields>
44
+ </FieldValueCollection>
45
+ <Id>123</Id>
46
+ </DynamicAsset>
47
+ </RetrieveAssetResult>
48
+ </RetrieveAssetResponse>
49
+ </s:Body>
50
+ </s:Envelope>
@@ -0,0 +1,26 @@
1
+ <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
2
+ <s:Header>
3
+ <o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
4
+ <u:Timestamp u:Id="_0">
5
+ <u:Created>2011-04-07T04:08:25.936Z</u:Created>
6
+ <u:Expires>2011-04-07T04:13:25.936Z</u:Expires>
7
+ </u:Timestamp>
8
+ </o:Security>
9
+ </s:Header>
10
+ <s:Body>
11
+ <UpdateResponse xmlns="https://secure.eloqua.com/API/1.2">
12
+ <UpdateResult xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
13
+ <UpdateResult>
14
+ <EntityType>
15
+ <ID>0</ID>
16
+ <Name>Contact</Name>
17
+ <Type>Base</Type>
18
+ </EntityType>
19
+ <Errors/>
20
+ <ID>1</ID>
21
+ <Success>true</Success>
22
+ </UpdateResult>
23
+ </UpdateResult>
24
+ </UpdateResponse>
25
+ </s:Body>
26
+ </s:Envelope>
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+ require 'eloqua/api/action'
3
+ require 'ruby-debug'
4
+
5
+ describe Eloqua::Api::Action do
6
+ subject { Eloqua::Api::Action }
7
+
8
+ describe "Eloqua Action" do
9
+
10
+ it "should get member count in step by status" do
11
+ xml_query = xml! do |xml|
12
+ xml.tag!(:stepId, 100)
13
+ xml.tag!(:status, 'AwaitingAction')
14
+ end
15
+ mock_eloqua_request(:get_member_count_in_step_by_status, :success).\
16
+ with(:action, :get_member_count_in_step_by_status, xml_query).once
17
+
18
+ result = subject.get_member_count_in_step_by_status(100, 'AwaitingAction')
19
+ result.should equal(0)
20
+ end
21
+
22
+ it "should list members in step by status if there is a membercount higher than 0" do
23
+ xml_query = xml! do |xml|
24
+ xml.tag!(:stepId, 100)
25
+ xml.tag!(:status, 'AwaitingAction')
26
+ xml.tag!(:pageNumber, 0)
27
+ xml.tag!(:pageSize, 100)
28
+ end
29
+ mock_eloqua_request(:list_members_in_step_by_status, :success).\
30
+ with(:action, :list_members_in_step_by_status, xml_query).once
31
+ result = subject.list_members_in_step_by_status(100, 'AwaitingAction', 0, 100)
32
+ #returns with {:i => http://www.w3.org/2001/XMLSchema-instance} as there is no result from the array
33
+ result.should be_instance_of(Hash)
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,498 @@
1
+ require 'spec_helper'
2
+ require 'eloqua/api/service'
3
+
4
+ shared_examples_for "entity association with response" do |type, name|
5
+
6
+ let(:xml_body) do
7
+ subject.entity_association_xml(asset_type, 1, entity_type, 1)
8
+ end
9
+
10
+ before do
11
+ mock_eloqua_request(type, name).\
12
+ with(:service, type, xml_body).once
13
+
14
+ @result = subject.entity_asset_operation(type, asset_type, 1, entity_type, 1)
15
+ end
16
+
17
+ specify { @result.should be_true }
18
+
19
+ end
20
+
21
+ shared_examples_for "entity association operation" do |method|
22
+
23
+ before do
24
+ flexmock(subject).should_receive(:entity_asset_operation).with(method, asset_type, 1, entity_type, 1).once.returns(true)
25
+ end
26
+
27
+ it 'should use entity asset operation to make request' do
28
+ subject.send(method, asset_type, 1, entity_type, 1)
29
+ end
30
+
31
+ end
32
+
33
+ shared_examples_for "operations for entity and asset" do |group, type|
34
+
35
+ let(:group_name) { group }
36
+
37
+ let(:dynamic_key) { ("dynamic_#{group}".to_sym) }
38
+
39
+ let(:field_key) { "#{group}_fields".to_sym }
40
+
41
+ context "#self.group_methods" do
42
+ specify { subject.group_methods.class.should == Array }
43
+ end
44
+
45
+ context "#self.group_type_methods" do
46
+ specify { subject.group_type_methods.class.should == Array }
47
+ end
48
+
49
+ context "#self.type_methods" do
50
+ specify { subject.type_methods.class.should == Array }
51
+ end
52
+
53
+ context '#self.create_object' do
54
+
55
+ let(:result_key) { subject.key_with_object(group, :create_result) }
56
+ let(:input) { [group, type, {:C_EmailAddress => 'create'}] }
57
+ let(:create_result) do
58
+ {
59
+ result_key => {
60
+ ("#{group}_type").to_sym => type,
61
+ :errors => nil,
62
+ :id => 1
63
+ }
64
+ }
65
+ end
66
+
67
+ context 'when successfuly creating one record' do
68
+
69
+ let(:xml_body) do
70
+ xml! do |xml|
71
+ xml.object_collection!(group) do
72
+ xml.dynamic_object!(group) do
73
+ xml.template!(:dynamic, group, type, nil, {
74
+ :C_EmailAddress => 'create',
75
+ })
76
+ end
77
+ end
78
+ end
79
+ end
80
+
81
+ before do
82
+ mock_api_request(remote_method(:create), xml_body, create_result)
83
+ @results = subject.create_object(*input)
84
+ end
85
+
86
+
87
+ it 'should return {:id => 1}' do
88
+ @results[:id].should == 1
89
+ end
90
+
91
+ end
92
+
93
+ context "when the record is duplicate" do
94
+
95
+ let(:create_result) do
96
+ {
97
+ result_key => {
98
+ ("#{group}_type").to_sym => type,
99
+ :errors => {
100
+ :error => {
101
+ :error_code => 'DuplicateValue',
102
+ :message => 'You are attempting to create a duplicate entity.'
103
+ }
104
+ }
105
+ }
106
+ }
107
+ end
108
+
109
+ before do
110
+ mock_api_request(create_result)
111
+ end
112
+
113
+ it 'should raise duplicate error exception' do
114
+ lambda { subject.create_object(*input) }.should raise_exception(Eloqua::DuplicateRecordError)
115
+ end
116
+
117
+ end
118
+
119
+ end
120
+
121
+ context "#self.update_object" do
122
+
123
+ let(:result_key) { subject.key_with_object(group, :update_result) }
124
+
125
+ let(:update_result) do
126
+ {
127
+ result_key => {
128
+ ("#{group}_type").to_sym => type,
129
+ :errors => nil,
130
+ :id => 1,
131
+ :success => true
132
+ }
133
+ }
134
+ end
135
+
136
+ context "when successfully updating one record" do
137
+ let(:input) { [group, type, 1, {:C_EmailAddress => 'new'}] }
138
+ let(:xml_body) do
139
+ xml! do |xml|
140
+ xml.object_collection!(group) do
141
+ xml.dynamic_object!(group) do
142
+ xml.template!(:dynamic, group, type, '1', {
143
+ :C_EmailAddress => 'new',
144
+ })
145
+ end
146
+ end
147
+ end
148
+ end
149
+
150
+ before do
151
+ mock_api_request(remote_method(:update), xml_body, update_result)
152
+ @results = subject.update_object(*input)
153
+ end
154
+
155
+ it 'should return true' do
156
+ @results.should be_true
157
+ end
158
+
159
+ end
160
+
161
+ end
162
+
163
+ context "#self.delete_object" do
164
+
165
+ context "when given single int" do
166
+ let(:result_key) { subject.key_with_object(group, :delete_result) }
167
+
168
+ let(:delete_result) do
169
+ {
170
+ result_key => {
171
+ ("#{group}_type").to_sym => type,
172
+ :errors => nil,
173
+ :id => 1,
174
+ :success => true
175
+ }
176
+ }
177
+ end
178
+ let(:input) { 1 }
179
+ let(:xml_body) do
180
+ xml! do |xml|
181
+ xml.object_type_lower!(group) do
182
+ xml.template!(:object_type, type)
183
+ end
184
+ xml.ids do
185
+ xml.template!(:int_array, [input])
186
+ end
187
+ end
188
+ end
189
+
190
+ before do
191
+ mock_api_request(remote_method(:delete), xml_body, delete_result)
192
+ @result = subject.delete_object(group, type, 1)
193
+ end
194
+
195
+ it 'should return an array of deleted ids' do
196
+ @result.should == [1]
197
+ end
198
+
199
+ end
200
+ end
201
+
202
+ context "#self.find_object" do
203
+
204
+ let(:find_result) do
205
+ {
206
+ dynamic_key => {
207
+ :field_value_collection => {
208
+ field_key => [{
209
+ :internal_name => 'C_EmailAddress',
210
+ :value => email
211
+ }]
212
+ },
213
+ :id => '1'
214
+ }
215
+ }
216
+ end
217
+
218
+ context "successful find_object with all fields" do
219
+ let(:xml_body) do
220
+ xml! do |xml|
221
+ xml.object_type_lower!(group) do
222
+ xml.template!(:object_type, type)
223
+ end
224
+ xml.ids do
225
+ xml.template!(:int_array, [1])
226
+ end
227
+ end
228
+ end
229
+
230
+ before do
231
+ mock_api_request(remote_method(:retrieve), xml_body, find_result)
232
+ @result = subject.find_object(group, type, 1)
233
+ end
234
+
235
+ it 'should return a hash with fields from retrieve' do
236
+ @result.class.should == Hash
237
+ end
238
+
239
+ it 'should return hash with expected fields' do
240
+ expected = {
241
+ :C_EmailAddress => email,
242
+ :id => 1
243
+ }
244
+ expected.each do |key, value|
245
+ @result[key].should == value
246
+ end
247
+
248
+ end
249
+ end
250
+
251
+ context 'find_object without a result' do
252
+
253
+ before do
254
+ mock = mock_api_request(dynamic_key => nil)
255
+ @result = subject.find_object(group, type, 5)
256
+ end
257
+
258
+ it 'should return false' do
259
+ @result.should be_false
260
+ end
261
+
262
+ end
263
+
264
+ end
265
+
266
+ end
267
+
268
+ describe Eloqua::Api::Service do
269
+
270
+ subject { Eloqua::Api::Service }
271
+
272
+ let(:email) { 'test@email.com' }
273
+
274
+ let(:group) { :asset }
275
+
276
+ let(:type) do
277
+ subject.remote_type('Contact')
278
+ end
279
+
280
+ let(:asset_type) do
281
+ subject.remote_type('ContactGroupName', 'ContactGroup', 0)
282
+ end
283
+
284
+ let(:entity_type) do
285
+ subject.remote_type('Contact')
286
+ end
287
+
288
+ context "#self.entity_association_xml" do
289
+
290
+ let(:expected_xml) do
291
+ xml_query = xml! do |xml|
292
+ xml.template!(:object, :entity, entity_type, 1)
293
+ xml.template!(:object, :asset, asset_type, 1)
294
+ end
295
+ end
296
+
297
+
298
+ context 'when entity given is a class' do
299
+ it 'should return expected xml' do
300
+ output = subject.entity_association_xml(asset_type, 1, entity_type, 1)
301
+ output.should == expected_xml
302
+ end
303
+ end
304
+
305
+ context 'when entity given is a hash' do
306
+ it 'should return expected xml' do
307
+ output = subject.entity_association_xml(asset_type, 1, entity_type, 1)
308
+ output.should == expected_xml
309
+ end
310
+ end
311
+
312
+ end
313
+
314
+ context "#self.key_with_object" do
315
+
316
+ it 'should return given when obj type is entity' do
317
+ subject.key_with_object(:entity, :create_result).should == :create_result
318
+ end
319
+
320
+ it 'should inject asset in the middle of given method' do
321
+ subject.key_with_object(:asset, :create_result).should == :create_asset_result
322
+ end
323
+
324
+ end
325
+
326
+ context "#self.object_method" do
327
+ it 'should return given name when obj type is entity' do
328
+ subject.object_method(:entity, :create).should == :create
329
+ end
330
+
331
+ it 'should append obj type when type is other then entity' do
332
+ subject.object_method(:asset, :create).should == :create_asset
333
+ end
334
+ end
335
+
336
+ context "#self.request" do
337
+ it 'should make requests with the :service client' do
338
+ flexmock(Eloqua::Api).should_receive(:request).with(:service, :method, {})
339
+ subject.request(:method, {})
340
+ end
341
+ end
342
+
343
+ it_behaves_like 'operations for entity and asset', :asset, Eloqua::Api.remote_type('ContactGroupName', 'ContactGroup', 0)
344
+ it_behaves_like 'operations for entity and asset', :entity, Eloqua::Api.remote_type('Contact')
345
+
346
+ context "#self.list_memberships" do
347
+ let(:xml_body) do
348
+ xml! do |xml|
349
+ xml.template!(:object, :entity, type, 1)
350
+ end
351
+ end
352
+
353
+ before do
354
+ mock_eloqua_request(:list_group_membership, :success).\
355
+ with(:service, :list_group_membership, xml_body).once
356
+
357
+ @result = subject.list_memberships(type, 1)
358
+ end
359
+
360
+ it "should provide array of contact groups" do
361
+ @result
362
+ end
363
+ end
364
+
365
+ context "during group member class operations" do
366
+
367
+ let(:xml_body) do
368
+ subject.entity_association_xml(asset_type, 1, entity_type, 1)
369
+ end
370
+
371
+ context "#self.entity_asset_operation" do
372
+
373
+ context "when adding group member" do
374
+ it_behaves_like 'entity association with response', :add_group_member, :success
375
+ end
376
+
377
+ context "when removing group member" do
378
+ it_behaves_like 'entity association with response', :remove_group_member, :success
379
+ end
380
+
381
+ end
382
+
383
+ context "#self.add_group_member" do
384
+ it_behaves_like 'entity association operation', :add_group_member
385
+ end
386
+
387
+ context "#self.remove_group_member" do
388
+ it_behaves_like 'entity association operation', :remove_group_member
389
+ end
390
+
391
+ end
392
+
393
+ context "#self.list_types" do
394
+ let(:remote_method) { "list_#{group}_types".to_sym }
395
+
396
+ before do
397
+ mock_eloqua_request(remote_method, :success).with(:service, remote_method, nil)
398
+ end
399
+
400
+ it 'should return results as an array' do
401
+ result = subject.list_types(group)
402
+ result.class.should == Array
403
+ end
404
+
405
+ end
406
+
407
+ context "#self.describe" do
408
+ let(:remote_method) { "describe_#{group}".to_sym }
409
+
410
+ let(:xml_body) do
411
+ xml! do |xml|
412
+ xml.object_type_lower!(group) do
413
+ xml.template!(:object_type, type)
414
+ end
415
+ end
416
+ end
417
+
418
+ before do
419
+ mock_eloqua_request(remote_method, :success).with(:service, remote_method, xml_body)
420
+ @result = subject.describe(group, type)
421
+ end
422
+
423
+ it 'should have fields in the top level in result as an array' do
424
+ @result.should have_key(:fields)
425
+ @result[:fields].class.should == Array
426
+ end
427
+
428
+ end
429
+
430
+ context "#self.describe_type" do
431
+
432
+ shared_examples_for "will return collection of types" do
433
+ it "should return an array" do
434
+ @result.class.should == Array
435
+ end
436
+
437
+ it "should contain type hash in first element with :id, :name and :type keys" do
438
+ first = @result.first
439
+
440
+ first.should have_key(:id)
441
+ first.should have_key(:name)
442
+ first.should have_key(:type)
443
+ end
444
+
445
+ end
446
+
447
+ context "when group is :asset" do
448
+ let(:request_hash) do
449
+ {:asset_type => 'Type'}
450
+ end
451
+
452
+ before do
453
+ mock_eloqua_request(:describe_asset_type, :success).\
454
+ with(:service, :describe_asset_type, request_hash).once
455
+ @result = subject.describe_type(:asset, 'Type')
456
+ end
457
+
458
+ it_behaves_like 'will return collection of types'
459
+ end
460
+
461
+ context "when group is :entity" do
462
+ let(:request_hash) do
463
+ {:global_entity_type => 'Base'}
464
+ end
465
+
466
+ before do
467
+ mock_eloqua_request(:describe_entity_type, :success).\
468
+ with(:service, :describe_entity_type, request_hash).once
469
+
470
+ @result = subject.describe_type(:entity, 'Base')
471
+ end
472
+
473
+ it_behaves_like 'will return collection of types'
474
+ end
475
+
476
+ end
477
+
478
+ context "#self.handle_exception" do
479
+ context 'duplicate error' do
480
+
481
+ let(:response) do
482
+ {:errors=>
483
+ {:error=>
484
+ {:error_code=>"DuplicateValue",
485
+ :message=>"You are attempting to create a duplicate entity."}},
486
+ :id=>"-1",
487
+ :entity_type=>{:type=>"Base", :name=>"Contact", :id=>"0"}
488
+ }
489
+ end
490
+
491
+ it 'should raise duplicate exception' do
492
+ lambda { subject.handle_exception(response) }.should raise_exception(Eloqua::DuplicateRecordError)
493
+ end
494
+
495
+ end
496
+ end
497
+
498
+ end