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,171 @@
1
+ require 'spec_helper'
2
+
3
+ class EloquaSpecReceving
4
+ class << self
5
+ def one_argument(from_delg, arg)
6
+
7
+ end
8
+
9
+ def one_argument2(from_delg, arg)
10
+
11
+ end
12
+
13
+ def three_argument(from_delg1, from_delg2, arg)
14
+
15
+ end
16
+
17
+ def three_argument2(from_delg1, from_delg2, arg)
18
+
19
+ end
20
+
21
+ end
22
+ end
23
+
24
+ describe Eloqua do
25
+
26
+ context '#self.configure' do
27
+ it 'should provide self' do
28
+ save = nil
29
+ Eloqua.configure do |config|
30
+ config.should == Eloqua
31
+ end
32
+ end
33
+ end
34
+
35
+ context '#self.authenticate' do
36
+ before do
37
+ Eloqua.authenticate('user', 'pass')
38
+ end
39
+
40
+ it 'should have set username to user' do
41
+ Eloqua.user.should == 'user'
42
+ end
43
+
44
+ it 'should have set password to pass' do
45
+ Eloqua.password.should == 'pass'
46
+ end
47
+
48
+ end
49
+
50
+ context "#self.format_results_for_array" do
51
+ context "level 1 depth ending in single" do
52
+ let(:input) do
53
+ {
54
+ :one => :hit
55
+ }
56
+ end
57
+
58
+ let(:expected) { [:hit] }
59
+
60
+ it 'should return expected' do
61
+ result = subject.format_results_for_array(input, :one)
62
+ result.should == expected
63
+ end
64
+
65
+ end
66
+
67
+ context "level 3 depth ending in multiple" do
68
+
69
+ let(:input) do
70
+ {
71
+ :one => {
72
+ :two => {
73
+ :three => [:hit, :hit]
74
+ }
75
+ }
76
+ }
77
+ end
78
+
79
+ let(:expected) { [:hit, :hit] }
80
+
81
+ it 'should return expected' do
82
+ result = subject.format_results_for_array(input, :one, :two, :three)
83
+ result.should == expected
84
+ end
85
+ end
86
+
87
+ context "level 3 depth ending in single" do
88
+
89
+ let(:input) do
90
+ {
91
+ :one => {
92
+ :two => {
93
+ :three => [:hit]
94
+ }
95
+ }
96
+ }
97
+ end
98
+
99
+ let(:expected) { [:hit] }
100
+
101
+ it 'should return expected' do
102
+ result = subject.format_results_for_array(input, :one, :two, :three)
103
+ result.should == expected
104
+ end
105
+ end
106
+ end
107
+
108
+ context "#self.delegate_with_args" do
109
+
110
+ let(:receiving) do
111
+ EloquaSpecReceving
112
+ end
113
+
114
+ let(:sending) do
115
+ Class.new do
116
+ class << self
117
+ def one
118
+ 1
119
+ end
120
+
121
+ def two
122
+ 2
123
+ end
124
+ end
125
+ end
126
+ end
127
+
128
+ context 'with multiple delegated methods and single argument method' do
129
+ before do
130
+ Eloqua.delegate_with_args(sending, receiving, [:one_argument, :one_argument1], [:two])
131
+ end
132
+
133
+ specify { sending.should respond_to(:one_argument) }
134
+ specify { sending.should respond_to(:one_argument1) }
135
+
136
+ it 'should delegate method arguments to receiving' do
137
+ flexmock(receiving).should_receive(:one_argument).with(2, 'arg').once
138
+ sending.one_argument('arg')
139
+ end
140
+
141
+ it 'should delegate method arguments to receiving on other methods' do
142
+ flexmock(receiving).should_receive(:one_argument1).with(2, 'arg').once
143
+ sending.one_argument1('arg')
144
+ end
145
+
146
+ end
147
+
148
+ context 'with multiple delegated methods and arguments' do
149
+ before do
150
+ Eloqua.delegate_with_args(sending, receiving, [:three_argument, :three_argument1], [:one, :two])
151
+ end
152
+
153
+ specify { sending.should respond_to(:three_argument) }
154
+ specify { sending.should respond_to(:three_argument1) }
155
+
156
+ it 'should delegate method arguments to receiving' do
157
+ flexmock(receiving).should_receive(:three_argument).with(1, 2, 'arg').once
158
+ sending.three_argument('arg')
159
+ end
160
+
161
+ it 'should delegate method arguments to receiving on other methods' do
162
+ flexmock(receiving).should_receive(:three_argument1).with(1, 2, 'arg').once
163
+ sending.three_argument1('arg')
164
+ end
165
+
166
+ end
167
+
168
+
169
+ end
170
+
171
+ end
@@ -0,0 +1,173 @@
1
+ shared_examples_for "uses attribute map" do
2
+
3
+
4
+ context "#self.map_attribute" do
5
+
6
+ before do
7
+ @class = Class.new(subject) do
8
+ map :name => 'C_Name', :id => 'ContactID'
9
+ end
10
+ end
11
+
12
+ it 'should return value in attribute_map when given a key exists' do
13
+ @class.map_attribute(:name).should == :C_Name
14
+ end
15
+
16
+ it 'should return given value when key does not exist within attribute_map' do
17
+ @class.map_attribute(:Cezar).should == 'Cezar'
18
+ end
19
+
20
+ end
21
+
22
+ context "#self.attribute_map" do
23
+ specify { subject.attribute_map.class == Hash }
24
+
25
+ context "when inherited entity attribute map is cloned by not the same object" do
26
+ before do
27
+ @super = Class.new(subject)
28
+ @super.attribute_map[:id] = 'ContactID'
29
+ @child = Class.new(@super)
30
+ end
31
+
32
+ it 'should have all the same keys' do
33
+ @child.attribute_map.keys.should == @super.attribute_map.keys
34
+ end
35
+
36
+ it 'should have all the same values' do
37
+ @child.attribute_map.values.should == @super.attribute_map.values
38
+ end
39
+
40
+ it 'should not be the same object as parent' do
41
+ @child.attribute_map.object_id.should_not === @super.attribute_map.object_id
42
+ end
43
+
44
+ end
45
+
46
+ end
47
+
48
+
49
+ context "#self.map" do
50
+
51
+ before do
52
+ @class = Class.new(Eloqua::RemoteObject) do
53
+ self.remote_type = Eloqua::Api.remote_type('Contact')
54
+ end
55
+ end
56
+
57
+ it 'should be able to use map on the class level to map attributes' do
58
+ @class.map :id => 'C_Attribute'
59
+ @class.attribute_map[:id].should == :C_Attribute
60
+ end
61
+
62
+ it 'should be able to override existing maps' do
63
+ @class.map :id => 'not_me'
64
+ @class.map :id => 'me'
65
+ @class.attribute_map[:id].should == :me
66
+ end
67
+
68
+ context 'when reverse' do
69
+ it 'should also add the reverse to attribute_map_reverse' do
70
+ @class.map :Contact => 'name'
71
+ @class.map :IDC => 'id', :Real => 'email'
72
+
73
+ reverse = {
74
+ :name => :Contact,
75
+ :id => :IDC,
76
+ :email => :Real
77
+ }.with_indifferent_access
78
+ @class.attribute_map_reverse.should == reverse
79
+ end
80
+ end
81
+
82
+ end
83
+
84
+ context "#map_attributes" do
85
+ let(:input) do
86
+ {
87
+ :C_EmailAddress => 'email@address.com',
88
+ :ContactID => '1',
89
+ :normal_id => 'wow'
90
+ }.with_indifferent_access
91
+ end
92
+
93
+ let(:expected) do
94
+ {
95
+ :email_address => 'email@address.com',
96
+ :id => '1',
97
+ :normal_id => 'wow'
98
+ }.with_indifferent_access
99
+ end
100
+
101
+ let(:reverse) do
102
+ {
103
+ :email_address => 'C_EmailAddress',
104
+ :id => 'ContactID',
105
+ :normal_id => 'normal_id'
106
+ }.with_indifferent_access
107
+ end
108
+
109
+ before do
110
+ klass_object = Class.new(subject) do
111
+ map :ContactID => 'id'
112
+ end
113
+ @klass = klass_object.new
114
+ @result = @klass.send(:map_attributes, input)
115
+ end
116
+
117
+ it 'should map attributes from CamelCase format to snake_case format' do
118
+ @result.should == expected
119
+ end
120
+
121
+ it 'should store the original key names in attribute_keys_to_eloqua' do
122
+ @klass.instance_reverse_keys.should == reverse
123
+ end
124
+
125
+ context "#reverse_map_attributes" do
126
+
127
+ context "when given valid input" do
128
+ before do
129
+ @reversed = @klass.send(:reverse_map_attributes, @result)
130
+ end
131
+
132
+ it 'should be able to reverse map_attributes back into input' do
133
+ @reversed.should == input
134
+ end
135
+ end
136
+
137
+ context "when given invalid input" do
138
+ let(:input) do
139
+ {
140
+ :id => '1',
141
+ :phone_field => 'phoney'
142
+ }
143
+ end
144
+
145
+ let(:expected) do
146
+ {
147
+ :ContactID => '1',
148
+ :phone_field => 'phoney'
149
+ }.with_indifferent_access
150
+ end
151
+
152
+ let(:klass) do
153
+ Class.new(subject) do
154
+ map :ContactID => 'id'
155
+ end
156
+ end
157
+
158
+ before do
159
+ object = klass.new
160
+ object.send(:map_attributes, {})
161
+ @result = object.send(:reverse_map_attributes, input)
162
+ end
163
+
164
+ it "should use given key when it is not known" do
165
+ @result.should == expected
166
+ end
167
+
168
+ end
169
+
170
+ end
171
+
172
+ end
173
+ end
@@ -0,0 +1,50 @@
1
+ # This is for testing the xml syntax given to the remote objects
2
+ # Actual response tests (with fixtures) should be done in the
3
+ # Entity or Asset spec's
4
+
5
+ shared_examples_for "class level delegation of remote operations for" do |remote_group|
6
+
7
+ before do
8
+ @remote_group = remote_group
9
+ end
10
+
11
+ let(:email) { 'test@email.com' }
12
+
13
+ let(:dynamic_key) { ("dynamic_#{remote_group}".to_sym) }
14
+ let(:field_key) { "#{remote_group}_fields".to_sym }
15
+
16
+ group_delegation = Eloqua::Api::Service.group_methods
17
+ type_delegation = Eloqua::Api::Service.type_methods
18
+ group_type_delegation = Eloqua::Api::Service.group_type_methods
19
+
20
+ group_delegation.each do |method|
21
+ context "#self.#{method}" do
22
+ it "should delegate #{method} to Eloqua::Api::Service with group name" do
23
+ flexmock(Eloqua::Api::Service).should_receive(method).\
24
+ with(subject.remote_group).once
25
+ subject.send(method)
26
+ end
27
+ end
28
+ end
29
+
30
+ group_type_delegation.each do |method|
31
+ context "#self.#{method}" do
32
+ it "should delegate #{method} to Eloqua::Api::Service with group name" do
33
+ flexmock(Eloqua::Api::Service).should_receive(method).\
34
+ with(subject.remote_group, subject.remote_type).once
35
+ subject.send(method)
36
+ end
37
+ end
38
+ end
39
+
40
+ type_delegation.each do |method|
41
+ context "#self.#{method}" do
42
+ it "should delegate #{method} to Eloqua::Api::Service with group name" do
43
+ flexmock(Eloqua::Api::Service).should_receive(method).\
44
+ with(subject.remote_type).once
45
+ subject.send(method)
46
+ end
47
+ end
48
+ end
49
+
50
+ end
@@ -0,0 +1,48 @@
1
+ require 'rubygems'
2
+ require "bundler/setup"
3
+ require 'flexmock'
4
+
5
+ require 'net/http'
6
+ require 'net/https'
7
+
8
+ Bundler.require :default, :test
9
+
10
+ require 'rspec'
11
+ require 'timecop'
12
+ require 'eloqua'
13
+ require 'savon_spec'
14
+
15
+ unless defined?(ELOQUA_LIB)
16
+ ELOQUA_LIB = File.dirname(__FILE__) + '/../lib'
17
+ $: << ELOQUA_LIB
18
+ end
19
+
20
+ Dir[File.dirname(__FILE__) + '/support/**/*.rb'].each {|support| require support}
21
+ Dir[File.dirname(__FILE__) + '/shared/**/*.rb'].each {|support| require support}
22
+
23
+ Savon.configure do |config|
24
+ config.log = false
25
+ config.raise_errors = false
26
+ end
27
+
28
+ RSpec.configure do |config|
29
+
30
+ include Eloqua::RSpec::Helper
31
+ Savon::Spec::Fixture.path = File.dirname(__FILE__) + '/fixtures/'
32
+
33
+ config.mock_with :flexmock
34
+
35
+ config.before do
36
+ # This is for adding actual authentication details.
37
+ # The core tests do not actually need to login as they
38
+ # operate on fixtures but we need to get the fixture data
39
+ # in the first place and for that valid authenticate is needed
40
+ initializer = File.dirname(__FILE__) + '/../eloqua_initializer.rb'
41
+ if(File.exist?(initializer))
42
+ load initializer
43
+ else
44
+ Eloqua.authenticate('company\\user', 'pass')
45
+ end
46
+ end
47
+
48
+ end
@@ -0,0 +1,73 @@
1
+ module Eloqua
2
+ module RSpec
3
+ module Helper
4
+
5
+ def soap_fixture(type, name, code = 200, headers = {})
6
+ body = Savon::Spec::Fixture.load(type, name)
7
+ httpi = HTTPI::Response.new(code, headers, body)
8
+ Savon::SOAP::Response.new(httpi)
9
+ end
10
+
11
+ def mock_eloqua_request(type, name, code = 200, headers = {})
12
+ mock = soap_fixture(type, name, code, headers)
13
+ flexmock(Eloqua::Api).should_receive(:send_remote_request).and_return(mock)
14
+ end
15
+
16
+ def mock_response(type, name, code = 200, headers = {})
17
+ body = Savon::Spec::Fixture.load(type, name)
18
+ mock = HTTPI::Response.new(code, headers, body)
19
+ flexmock(HTTPI).should_receive(:post).and_return(mock)
20
+ end
21
+
22
+
23
+ def mock_api_request(method = nil, xml_body = nil, result = nil)
24
+ mocked_object = subject
25
+
26
+ if(mocked_object.respond_to?(:api))
27
+ mocked_object = mocked_object.api
28
+ end
29
+
30
+ if(!xml_body && !result)
31
+ # No with expectation
32
+ result = method
33
+ flexmock(mocked_object).should_receive(:request).\
34
+ and_return(result).once
35
+ else
36
+ # with expectation
37
+ flexmock(mocked_object).should_receive(:request).\
38
+ with(method, xml_body).\
39
+ and_return(result).once
40
+ end
41
+ end
42
+
43
+ def xml!(&block)
44
+ Eloqua::Api.builder(&block)
45
+ end
46
+
47
+ def group_name
48
+ (respond_to?(:remote_group))? remote_group : group
49
+ end
50
+
51
+ def remote_type
52
+ "#{group_name}Type"
53
+ end
54
+
55
+ def dynamic_type
56
+ "Dynamic#{group_name.to_s.camelize}"
57
+ end
58
+
59
+ def tag_with_type(tag)
60
+ "#{tag}_#{group_name}".to_sym
61
+ end
62
+
63
+ def remote_method(method)
64
+ if(group_name == :entity)
65
+ method.to_sym
66
+ else
67
+ ("#{method}_#{group_name}").to_sym
68
+ end
69
+ end
70
+
71
+ end
72
+ end
73
+ end