marketo-api-ruby 0.8
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.
- checksums.yaml +15 -0
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +2 -0
- data/.gemtest +0 -0
- data/Contributing.rdoc +65 -0
- data/Gemfile +9 -0
- data/History.rdoc +3 -0
- data/Licence.rdoc +24 -0
- data/Manifest.txt +32 -0
- data/README.rdoc +105 -0
- data/Rakefile +65 -0
- data/lib/marketo-api-ruby.rb +1 -0
- data/lib/marketo_api.rb +39 -0
- data/lib/marketo_api/campaigns.rb +194 -0
- data/lib/marketo_api/client.rb +169 -0
- data/lib/marketo_api/client_proxy.rb +104 -0
- data/lib/marketo_api/lead.rb +277 -0
- data/lib/marketo_api/leads.rb +150 -0
- data/lib/marketo_api/lists.rb +109 -0
- data/lib/marketo_api/mobject.rb +272 -0
- data/lib/marketo_api/mobjects.rb +115 -0
- data/spec/marketo/authentication_header_spec.rb +66 -0
- data/spec/marketo/client_spec.rb +363 -0
- data/spec/marketo/lead_key_spec.rb +40 -0
- data/spec/marketo/lead_record_spec.rb +86 -0
- data/spec/spec_helper.rb +4 -0
- data/test/marketo_api/test_campaigns.rb +173 -0
- data/test/marketo_api/test_client.rb +83 -0
- data/test/marketo_api/test_lead.rb +158 -0
- data/test/marketo_api/test_leads.rb +133 -0
- data/test/marketo_api/test_lists.rb +95 -0
- data/test/marketo_api/test_mobject.rb +273 -0
- data/test/marketo_api/test_mobjects.rb +158 -0
- data/test/minitest_helper.rb +69 -0
- data/test/test_marketo_api.rb +38 -0
- metadata +302 -0
- metadata.gz.sig +3 -0
@@ -0,0 +1,115 @@
|
|
1
|
+
require_relative 'client_proxy'
|
2
|
+
require_relative 'mobject'
|
3
|
+
|
4
|
+
# MarketoAPI operations on Marketo objects (MObject).
|
5
|
+
class MarketoAPI::MObjects < MarketoAPI::ClientProxy
|
6
|
+
|
7
|
+
# :call-seq:
|
8
|
+
# delete(mobject, mobject, ...) -> status_list
|
9
|
+
#
|
10
|
+
# Implements
|
11
|
+
# {+deleteMObjects+}[http://developers.marketo.com/documentation/soap/deletemobjects/],
|
12
|
+
# returning the deletion success status for each object provided.
|
13
|
+
#
|
14
|
+
# Only works with Opportunity or OpportunityPersonRole MObjects.
|
15
|
+
#
|
16
|
+
# To delete an Opportunity:
|
17
|
+
#
|
18
|
+
# marketo.mobjects.delete MarketoAPI::MObject.opportunity(75)
|
19
|
+
def delete(*mobjects)
|
20
|
+
if mobjects.empty?
|
21
|
+
raise ArgumentError, "must provide one or more MObjects to delete"
|
22
|
+
end
|
23
|
+
response = call(
|
24
|
+
:delete_m_objects,
|
25
|
+
m_object_list: transform_param_list(__method__, mobjects)
|
26
|
+
)
|
27
|
+
extract_mobject_status_list(response)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Implements
|
31
|
+
# {+listMObjects+}[http://developers.marketo.com/documentation/soap/listmobjects/],
|
32
|
+
# returning the type names of the available Marketo objects. The type
|
33
|
+
# names can be passed to #describe.
|
34
|
+
def list
|
35
|
+
extract_from_response(
|
36
|
+
call(:list_m_objects, nil),
|
37
|
+
:objects
|
38
|
+
)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Implements
|
42
|
+
# {+describeMObject+}[http://developers.marketo.com/documentation/soap/describemobject/],
|
43
|
+
# returning the description of the Marketo object.
|
44
|
+
def describe(name)
|
45
|
+
unless MarketoAPI::MObject::DESCRIBE_TYPES.include?(name.to_sym)
|
46
|
+
raise ArgumentError, "invalid type #{name} to describe"
|
47
|
+
end
|
48
|
+
|
49
|
+
extract_from_response(
|
50
|
+
call(:describe_m_object, object_name: name),
|
51
|
+
:metadata
|
52
|
+
)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Implements
|
56
|
+
# {+getMObjects+}[http://developers.marketo.com/documentation/soap/getmobjects/],
|
57
|
+
# returning one or more Marketo objects, up to 100 in a page. It also
|
58
|
+
# returns the current current stream position to continue working with the
|
59
|
+
# pages on subsequent calls to #get.
|
60
|
+
#
|
61
|
+
# See MObject#criteria and MObject#association on how to build criteria
|
62
|
+
# and association filters for #get queries.
|
63
|
+
def get(mobject)
|
64
|
+
call(:get_m_objects, transform_param(__method__, mobject)) { |list|
|
65
|
+
Get.new(list)
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
def sync(operation, *mobjects) #:nodoc:
|
70
|
+
# http://developers.marketo.com/documentation/soap/sync-mobjects/
|
71
|
+
raise NotImplementedError,
|
72
|
+
":sync_m_objects is not implemented in this version."
|
73
|
+
response = call(
|
74
|
+
:sync_m_objects,
|
75
|
+
transform_param_list(__method__, mobjects)
|
76
|
+
)
|
77
|
+
extract_mobject_status_list(response)
|
78
|
+
end
|
79
|
+
|
80
|
+
# A response object to MObjects#get that includes the return count, the
|
81
|
+
# new stream position, and the list of MObject records.
|
82
|
+
class Get
|
83
|
+
# The number of MObjects returned from MObjects#get.
|
84
|
+
attr_reader :return_count
|
85
|
+
# The stream position used for paging in MObjects#get.
|
86
|
+
# This may be shared with each MObject in #mobjects.
|
87
|
+
attr_reader :stream_position
|
88
|
+
# The list of Marketo objects.
|
89
|
+
attr_reader :mobjects
|
90
|
+
|
91
|
+
def initialize(hash)
|
92
|
+
@return_count = hash[:return_count].to_i
|
93
|
+
@more = hash[:has_more]
|
94
|
+
@stream_position = hash[:new_stream_position]
|
95
|
+
objects = MarketoAPI.array(hash[:m_object_list])
|
96
|
+
|
97
|
+
@mobjects = objects.map { |object|
|
98
|
+
MarketoAPI::MObject.from_soap_hash(object[:m_object])
|
99
|
+
}
|
100
|
+
end
|
101
|
+
|
102
|
+
# Returns +true+ if there are more objects to be returned.
|
103
|
+
def more?
|
104
|
+
!!@more
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
def extract_mobject_status_list(response)
|
110
|
+
response = extract_from_response(response, :m_obj_status_list) { |resp|
|
111
|
+
resp.map { |e| e[:m_object_status].values_at(:id, :status) }
|
112
|
+
}.flatten
|
113
|
+
Hash[*response]
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require File.expand_path('../spec_helper', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
module Rapleaf
|
4
|
+
module Marketo
|
5
|
+
ACCESS_KEY = 'ACCESS_KEY'
|
6
|
+
SECRET_KEY = 'SECRET_KEY'
|
7
|
+
|
8
|
+
describe AuthenticationHeader do
|
9
|
+
it "should set mktowsUserId to access key" do
|
10
|
+
header = Rapleaf::Marketo::AuthenticationHeader.new(ACCESS_KEY, SECRET_KEY)
|
11
|
+
header.get_mktows_user_id.should == ACCESS_KEY
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should set requestSignature" do
|
15
|
+
header = Rapleaf::Marketo::AuthenticationHeader.new(ACCESS_KEY, SECRET_KEY)
|
16
|
+
header.get_request_signature.should_not be_nil
|
17
|
+
header.get_request_signature.should_not == ''
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should set requestTimestamp in correct format" do
|
21
|
+
header = Rapleaf::Marketo::AuthenticationHeader.new(ACCESS_KEY, SECRET_KEY)
|
22
|
+
time = DateTime.new(1998, 1, 17, 20, 15, 1)
|
23
|
+
header.set_time(time)
|
24
|
+
header.get_request_timestamp().should == '1998-01-17T20:15:01+00:00'
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should calculate encrypted signature" do
|
28
|
+
# I got this example of the marketo API docs
|
29
|
+
|
30
|
+
access_key = 'bigcorp1_461839624B16E06BA2D663'
|
31
|
+
secret_key = '899756834129871744AAEE88DDCC77CDEEDEC1AAAD66'
|
32
|
+
|
33
|
+
header = Rapleaf::Marketo::AuthenticationHeader.new(access_key, secret_key)
|
34
|
+
header.set_time(DateTime.new(2010, 4, 9, 14, 4, 55, -7/24.0))
|
35
|
+
|
36
|
+
header.get_request_timestamp.should == '2010-04-09T14:04:54-07:00'
|
37
|
+
header.get_request_signature.should == 'ffbff4d4bef354807481e66dc7540f7890523a87'
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should cope if no date is given" do
|
41
|
+
header = Rapleaf::Marketo::AuthenticationHeader.new(ACCESS_KEY, SECRET_KEY)
|
42
|
+
expected = DateTime.now
|
43
|
+
actual = DateTime.parse(header.get_request_timestamp)
|
44
|
+
|
45
|
+
expected.year.should == actual.year
|
46
|
+
expected.hour.should == actual.hour
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should to_hash correctly" do
|
50
|
+
# I got this example from the marketo API docs
|
51
|
+
|
52
|
+
access_key = 'bigcorp1_461839624B16E06BA2D663'
|
53
|
+
secret_key = '899756834129871744AAEE88DDCC77CDEEDEC1AAAD66'
|
54
|
+
|
55
|
+
header = Rapleaf::Marketo::AuthenticationHeader.new(access_key, secret_key)
|
56
|
+
header.set_time(DateTime.new(2010, 4, 9, 14, 4, 55, -7/24.0))
|
57
|
+
|
58
|
+
header.to_hash.should == {
|
59
|
+
'mktowsUserId' => header.get_mktows_user_id,
|
60
|
+
'requestSignature' => header.get_request_signature,
|
61
|
+
'requestTimestamp' => header.get_request_timestamp,
|
62
|
+
}
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,363 @@
|
|
1
|
+
require File.expand_path('../spec_helper', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
module Rapleaf
|
4
|
+
module Marketo
|
5
|
+
|
6
|
+
describe Client do
|
7
|
+
EMAIL = "some@email.com"
|
8
|
+
IDNUM = 29
|
9
|
+
FIRST = 'Joe'
|
10
|
+
LAST = 'Smith'
|
11
|
+
COMPANY = 'Rapleaf'
|
12
|
+
MOBILE = '415 123 456'
|
13
|
+
API_KEY = 'API123KEY'
|
14
|
+
|
15
|
+
context 'Exception handling' do
|
16
|
+
it "should return nil if any exception is raised on get_lead request" do
|
17
|
+
savon_client = mock('savon_client').as_null_object
|
18
|
+
authentication_header = mock('authentication_header').as_null_object
|
19
|
+
client = Rapleaf::Marketo::Client.new(savon_client, authentication_header)
|
20
|
+
savon_client.should_receive(:request).and_raise Exception
|
21
|
+
client.get_lead_by_email(EMAIL).should be_nil
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should return nil if any exception is raised on sync_lead request" do
|
25
|
+
savon_client = mock('savon_client').as_null_object
|
26
|
+
authentication_header = mock('authentication_header').as_null_object
|
27
|
+
client = Rapleaf::Marketo::Client.new(savon_client, authentication_header)
|
28
|
+
savon_client.should_receive(:request).and_raise Exception
|
29
|
+
client.sync_lead(EMAIL, FIRST, LAST, COMPANY, MOBILE).should be_nil
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'Client interaction' do
|
34
|
+
it "should have the correct body format on get_lead_by_idnum" do
|
35
|
+
savon_client = mock('savon_client')
|
36
|
+
authentication_header = mock('authentication_header')
|
37
|
+
client = Rapleaf::Marketo::Client.new(savon_client, authentication_header)
|
38
|
+
response_hash = {
|
39
|
+
:success_get_lead => {
|
40
|
+
:result => {
|
41
|
+
:count => 1,
|
42
|
+
:lead_record_list => {
|
43
|
+
:lead_record => {
|
44
|
+
:email => EMAIL,
|
45
|
+
:lead_attribute_list => {
|
46
|
+
:attribute => [
|
47
|
+
{:attr_name => 'name1', :attr_type => 'string', :attr_value => 'val1'},
|
48
|
+
{:attr_name => 'name2', :attr_type => 'string', :attr_value => 'val2'},
|
49
|
+
{:attr_name => 'name3', :attr_type => 'string', :attr_value => 'val3'},
|
50
|
+
{:attr_name => 'name4', :attr_type => 'string', :attr_value => 'val4'}
|
51
|
+
]
|
52
|
+
},
|
53
|
+
:foreign_sys_type => nil,
|
54
|
+
:foreign_sys_person_id => nil,
|
55
|
+
:id => IDNUM.to_s
|
56
|
+
}
|
57
|
+
}
|
58
|
+
}
|
59
|
+
}
|
60
|
+
}
|
61
|
+
expect_request(savon_client,
|
62
|
+
authentication_header,
|
63
|
+
equals_matcher(:lead_key => {
|
64
|
+
:key_value => IDNUM,
|
65
|
+
:key_type => LeadKeyType::IDNUM
|
66
|
+
}),
|
67
|
+
'ns1:paramsGetLead',
|
68
|
+
response_hash)
|
69
|
+
expected_lead_record = LeadRecord.new(EMAIL, IDNUM)
|
70
|
+
expected_lead_record.set_attribute('name1', 'val1')
|
71
|
+
expected_lead_record.set_attribute('name2', 'val2')
|
72
|
+
expected_lead_record.set_attribute('name3', 'val3')
|
73
|
+
expected_lead_record.set_attribute('name4', 'val4')
|
74
|
+
client.get_lead_by_idnum(IDNUM).should == expected_lead_record
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should have the correct body format on get_lead_by_email" do
|
78
|
+
savon_client = mock('savon_client')
|
79
|
+
authentication_header = mock('authentication_header')
|
80
|
+
client = Rapleaf::Marketo::Client.new(savon_client, authentication_header)
|
81
|
+
response_hash = {
|
82
|
+
:success_get_lead => {
|
83
|
+
:result => {
|
84
|
+
:count => 1,
|
85
|
+
:lead_record_list => {
|
86
|
+
:lead_record => {
|
87
|
+
:email => EMAIL,
|
88
|
+
:lead_attribute_list => {
|
89
|
+
:attribute => [
|
90
|
+
{:attr_name => 'name1', :attr_type => 'string', :attr_value => 'val1'},
|
91
|
+
{:attr_name => 'name2', :attr_type => 'string', :attr_value => 'val2'},
|
92
|
+
{:attr_name => 'name3', :attr_type => 'string', :attr_value => 'val3'},
|
93
|
+
{:attr_name => 'name4', :attr_type => 'string', :attr_value => 'val4'}
|
94
|
+
]
|
95
|
+
},
|
96
|
+
:foreign_sys_type => nil,
|
97
|
+
:foreign_sys_person_id => nil,
|
98
|
+
:id => IDNUM.to_s
|
99
|
+
}
|
100
|
+
}
|
101
|
+
}
|
102
|
+
}
|
103
|
+
}
|
104
|
+
expect_request(savon_client,
|
105
|
+
authentication_header,
|
106
|
+
equals_matcher({:lead_key => {
|
107
|
+
:key_value => EMAIL,
|
108
|
+
:key_type => LeadKeyType::EMAIL}}),
|
109
|
+
'ns1:paramsGetLead',
|
110
|
+
response_hash)
|
111
|
+
expected_lead_record = LeadRecord.new(EMAIL, IDNUM)
|
112
|
+
expected_lead_record.set_attribute('name1', 'val1')
|
113
|
+
expected_lead_record.set_attribute('name2', 'val2')
|
114
|
+
expected_lead_record.set_attribute('name3', 'val3')
|
115
|
+
expected_lead_record.set_attribute('name4', 'val4')
|
116
|
+
client.get_lead_by_email(EMAIL).should == expected_lead_record
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should have the correct body format on sync_lead_record" do
|
120
|
+
savon_client = mock('savon_client')
|
121
|
+
authentication_header = mock('authentication_header')
|
122
|
+
client = Rapleaf::Marketo::Client.new(savon_client, authentication_header)
|
123
|
+
response_hash = {
|
124
|
+
:success_sync_lead => {
|
125
|
+
:result => {
|
126
|
+
:lead_id => IDNUM,
|
127
|
+
:sync_status => {
|
128
|
+
:error => nil,
|
129
|
+
:status => 'UPDATED',
|
130
|
+
:lead_id => IDNUM
|
131
|
+
},
|
132
|
+
:lead_record => {
|
133
|
+
:email => EMAIL,
|
134
|
+
:lead_attribute_list => {
|
135
|
+
:attribute => [
|
136
|
+
{:attr_name => 'name1', :attr_type => 'string', :attr_value => 'val1'},
|
137
|
+
{:attr_name => 'name2', :attr_type => 'string', :attr_value => 'val2'},
|
138
|
+
{:attr_name => 'name3', :attr_type => 'string', :attr_value => 'val3'},
|
139
|
+
{:attr_name => 'name4', :attr_type => 'string', :attr_value => 'val4'}
|
140
|
+
]
|
141
|
+
},
|
142
|
+
:foreign_sys_type => nil,
|
143
|
+
:foreign_sys_person_id => nil,
|
144
|
+
:id => IDNUM.to_s
|
145
|
+
}
|
146
|
+
}
|
147
|
+
}
|
148
|
+
}
|
149
|
+
expect_request(savon_client,
|
150
|
+
authentication_header,
|
151
|
+
(Proc.new do |actual|
|
152
|
+
retval = true
|
153
|
+
retval = false unless actual[:return_lead]
|
154
|
+
retval = false unless actual[:lead_record][:email].equal?(EMAIL)
|
155
|
+
retval = false unless actual[:lead_record][:lead_attribute_list][:attribute].size == 5
|
156
|
+
retval = false unless actual[:lead_record][:lead_attribute_list][:attribute].include?({:attr_value => EMAIL, :attr_name => "Email", :attr_type => "string"})
|
157
|
+
retval = false unless actual[:lead_record][:lead_attribute_list][:attribute].include?({:attr_value => "val1", :attr_name => "name1", :attr_type => "string"})
|
158
|
+
retval = false unless actual[:lead_record][:lead_attribute_list][:attribute].include?({:attr_value => "val2", :attr_name => "name2", :attr_type => "string"})
|
159
|
+
retval = false unless actual[:lead_record][:lead_attribute_list][:attribute].include?({:attr_value => "val3", :attr_name => "name3", :attr_type => "string"})
|
160
|
+
retval = false unless actual[:lead_record][:lead_attribute_list][:attribute].include?({:attr_value => "val4", :attr_name => "name4", :attr_type => "string"})
|
161
|
+
retval.should == true
|
162
|
+
end),
|
163
|
+
'ns1:paramsSyncLead',
|
164
|
+
response_hash)
|
165
|
+
lead_record = LeadRecord.new(EMAIL, IDNUM)
|
166
|
+
lead_record.set_attribute('name1', 'val1')
|
167
|
+
lead_record.set_attribute('name2', 'val2')
|
168
|
+
lead_record.set_attribute('name3', 'val3')
|
169
|
+
lead_record.set_attribute('name4', 'val4')
|
170
|
+
|
171
|
+
client.sync_lead_record(lead_record).should == lead_record
|
172
|
+
end
|
173
|
+
|
174
|
+
it "should have the correct body format on sync_lead" do
|
175
|
+
savon_client = mock('savon_client')
|
176
|
+
authentication_header = mock('authentication_header')
|
177
|
+
client = Rapleaf::Marketo::Client.new(savon_client, authentication_header)
|
178
|
+
response_hash = {
|
179
|
+
:success_sync_lead => {
|
180
|
+
:result => {
|
181
|
+
:lead_id => IDNUM,
|
182
|
+
:sync_status => {
|
183
|
+
:error => nil,
|
184
|
+
:status => 'UPDATED',
|
185
|
+
:lead_id => IDNUM
|
186
|
+
},
|
187
|
+
:lead_record => {
|
188
|
+
:email => EMAIL,
|
189
|
+
:lead_attribute_list => {
|
190
|
+
:attribute => [
|
191
|
+
{:attr_name => 'name1', :attr_type => 'string', :attr_value => 'val1'},
|
192
|
+
{:attr_name => 'name2', :attr_type => 'string', :attr_value => 'val2'},
|
193
|
+
{:attr_name => 'name3', :attr_type => 'string', :attr_value => 'val3'},
|
194
|
+
{:attr_name => 'name4', :attr_type => 'string', :attr_value => 'val4'}
|
195
|
+
]
|
196
|
+
},
|
197
|
+
:foreign_sys_type => nil,
|
198
|
+
:foreign_sys_person_id => nil,
|
199
|
+
:id => IDNUM.to_s
|
200
|
+
}
|
201
|
+
}
|
202
|
+
}
|
203
|
+
}
|
204
|
+
|
205
|
+
expect_request(savon_client,
|
206
|
+
authentication_header,
|
207
|
+
Proc.new { |actual|
|
208
|
+
actual_attribute_list = actual[:lead_record][:lead_attribute_list][:attribute]
|
209
|
+
actual[:lead_record][:lead_attribute_list][:attribute] = nil
|
210
|
+
expected = {
|
211
|
+
:return_lead => true,
|
212
|
+
:lead_record => {
|
213
|
+
:email => "some@email.com",
|
214
|
+
:lead_attribute_list =>
|
215
|
+
{
|
216
|
+
:attribute => nil}}
|
217
|
+
}
|
218
|
+
actual.should == expected
|
219
|
+
actual_attribute_list.should =~ [
|
220
|
+
{:attr_value => FIRST,
|
221
|
+
:attr_name => "FirstName",
|
222
|
+
:attr_type => "string"},
|
223
|
+
{:attr_value => LAST,
|
224
|
+
:attr_name => "LastName",
|
225
|
+
:attr_type => "string"},
|
226
|
+
{:attr_value => EMAIL,
|
227
|
+
:attr_name =>"Email",
|
228
|
+
:attr_type => "string"},
|
229
|
+
{:attr_value => COMPANY,
|
230
|
+
:attr_name => "Company",
|
231
|
+
:attr_type => "string"},
|
232
|
+
{:attr_value => MOBILE,
|
233
|
+
:attr_name => "MobilePhone",
|
234
|
+
:attr_type => "string"}
|
235
|
+
]
|
236
|
+
},
|
237
|
+
'ns1:paramsSyncLead',
|
238
|
+
response_hash)
|
239
|
+
expected_lead_record = LeadRecord.new(EMAIL, IDNUM)
|
240
|
+
expected_lead_record.set_attribute('name1', 'val1')
|
241
|
+
expected_lead_record.set_attribute('name2', 'val2')
|
242
|
+
expected_lead_record.set_attribute('name3', 'val3')
|
243
|
+
expected_lead_record.set_attribute('name4', 'val4')
|
244
|
+
client.sync_lead(EMAIL, FIRST, LAST, COMPANY, MOBILE).should == expected_lead_record
|
245
|
+
end
|
246
|
+
|
247
|
+
context "list operations" do
|
248
|
+
LIST_KEY = 'awesome leads list'
|
249
|
+
|
250
|
+
before(:each) do
|
251
|
+
@savon_client = mock('savon_client')
|
252
|
+
@authentication_header = mock('authentication_header')
|
253
|
+
@client = Rapleaf::Marketo::Client.new(@savon_client, @authentication_header)
|
254
|
+
end
|
255
|
+
|
256
|
+
it "should have the correct body format on add_to_list" do
|
257
|
+
response_hash = {} # TODO
|
258
|
+
expect_request(@savon_client,
|
259
|
+
@authentication_header,
|
260
|
+
equals_matcher({
|
261
|
+
:list_operation => ListOperationType::ADD_TO,
|
262
|
+
:list_key => LIST_KEY,
|
263
|
+
:strict => 'false',
|
264
|
+
:list_member_list => {
|
265
|
+
:lead_key => [
|
266
|
+
{
|
267
|
+
:key_type => 'EMAIL',
|
268
|
+
:key_value => EMAIL
|
269
|
+
}
|
270
|
+
]
|
271
|
+
}
|
272
|
+
}),
|
273
|
+
'ns1:paramsListOperation',
|
274
|
+
response_hash)
|
275
|
+
|
276
|
+
@client.add_to_list(LIST_KEY, EMAIL).should == response_hash
|
277
|
+
end
|
278
|
+
|
279
|
+
it "should have the correct body format on remove_from_list" do
|
280
|
+
response_hash = {} # TODO
|
281
|
+
expect_request(@savon_client,
|
282
|
+
@authentication_header,
|
283
|
+
equals_matcher({
|
284
|
+
:list_operation => ListOperationType::REMOVE_FROM,
|
285
|
+
:list_key => LIST_KEY,
|
286
|
+
:strict => 'false',
|
287
|
+
:list_member_list => {
|
288
|
+
:lead_key => [
|
289
|
+
{
|
290
|
+
:key_type => 'EMAIL',
|
291
|
+
:key_value => EMAIL
|
292
|
+
}
|
293
|
+
]
|
294
|
+
}
|
295
|
+
}),
|
296
|
+
'ns1:paramsListOperation',
|
297
|
+
response_hash)
|
298
|
+
|
299
|
+
@client.remove_from_list(LIST_KEY, EMAIL).should == response_hash
|
300
|
+
end
|
301
|
+
|
302
|
+
it "should have the correct body format on is_member_of_list?" do
|
303
|
+
response_hash = {} # TODO
|
304
|
+
expect_request(@savon_client,
|
305
|
+
@authentication_header,
|
306
|
+
equals_matcher({
|
307
|
+
:list_operation => ListOperationType::IS_MEMBER_OF,
|
308
|
+
:list_key => LIST_KEY,
|
309
|
+
:strict => 'false',
|
310
|
+
:list_member_list => {
|
311
|
+
:lead_key => [
|
312
|
+
{
|
313
|
+
:key_type => 'EMAIL',
|
314
|
+
:key_value => EMAIL
|
315
|
+
}
|
316
|
+
]
|
317
|
+
}
|
318
|
+
}),
|
319
|
+
'ns1:paramsListOperation',
|
320
|
+
response_hash)
|
321
|
+
|
322
|
+
@client.is_member_of_list?(LIST_KEY, EMAIL).should == response_hash
|
323
|
+
end
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
private
|
328
|
+
|
329
|
+
def equals_matcher(expected)
|
330
|
+
Proc.new { |actual|
|
331
|
+
actual.should == expected
|
332
|
+
}
|
333
|
+
end
|
334
|
+
|
335
|
+
def expect_request(savon_client, authentication_header, expected_body_matcher, expected_namespace, response_hash)
|
336
|
+
header_hash = stub('header_hash')
|
337
|
+
soap_response = stub('soap_response')
|
338
|
+
request_namespace = mock('namespace')
|
339
|
+
request_header = mock('request_header')
|
340
|
+
soap_request = mock('soap_request')
|
341
|
+
authentication_header.should_receive(:set_time)
|
342
|
+
authentication_header.should_receive(:to_hash).and_return(header_hash)
|
343
|
+
request_namespace.should_receive(:[]=).with("xmlns:ns1", "http://www.marketo.com/mktows/")
|
344
|
+
request_header.should_receive(:[]=).with("ns1:AuthenticationHeader", header_hash)
|
345
|
+
soap_request.should_receive(:namespaces).and_return(request_namespace)
|
346
|
+
soap_request.should_receive(:header).and_return(request_header)
|
347
|
+
soap_request.should_receive(:body=) do |actual_body|
|
348
|
+
expected_body_matcher.call(actual_body)
|
349
|
+
end
|
350
|
+
soap_response.should_receive(:to_hash).and_return(response_hash)
|
351
|
+
savon_client.should_receive(:request).with(expected_namespace).and_yield(soap_request).and_return(soap_response)
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
describe ListOperationType do
|
356
|
+
it 'should define the correct types' do
|
357
|
+
ListOperationType::ADD_TO.should == 'ADDTOLIST'
|
358
|
+
ListOperationType::IS_MEMBER_OF.should == 'ISMEMBEROFLIST'
|
359
|
+
ListOperationType::REMOVE_FROM.should == 'REMOVEFROMLIST'
|
360
|
+
end
|
361
|
+
end
|
362
|
+
end
|
363
|
+
end
|