marketo 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/marketo.rb ADDED
@@ -0,0 +1,16 @@
1
+ require 'rubygems'
2
+ require 'savon'
3
+
4
+ Savon.configure do |config|
5
+ config.log = false # disable logging
6
+ end
7
+
8
+ require File.expand_path('marketo/client', File.dirname(__FILE__))
9
+ require File.expand_path('marketo/authentication_header', File.dirname(__FILE__))
10
+ require File.expand_path('marketo/enums', File.dirname(__FILE__))
11
+ require File.expand_path('marketo/lead_key', File.dirname(__FILE__))
12
+ require File.expand_path('marketo/lead_record', File.dirname(__FILE__))
13
+
14
+
15
+
16
+
@@ -0,0 +1,48 @@
1
+ module Rapleaf
2
+ module Marketo
3
+ # This class exists only to encapsulate the authentication header part of a soap request to marketo
4
+ # Marketo requires a somewhat complex calculation of an encrypted signature and so it seemed sensible to pull this code out here
5
+ class AuthenticationHeader
6
+ DIGEST = OpenSSL::Digest::Digest.new('sha1')
7
+
8
+ def initialize(access_key, secret_key, time = DateTime.now)
9
+ @access_key = access_key
10
+ @secret_key = secret_key
11
+ @time = time
12
+ end
13
+
14
+ public
15
+ # time should be a DateTime instance
16
+ def set_time(time)
17
+ @time = time
18
+ end
19
+
20
+ def get_mktows_user_id
21
+ @access_key
22
+ end
23
+
24
+ def get_request_signature
25
+ calculate_signature
26
+ end
27
+
28
+ def get_request_timestamp
29
+ @time.to_s
30
+ end
31
+
32
+ def to_hash
33
+ {
34
+ "mktowsUserId" => get_mktows_user_id,
35
+ "requestSignature" => get_request_signature,
36
+ "requestTimestamp" => get_request_timestamp
37
+ }
38
+ end
39
+
40
+ private
41
+ def calculate_signature
42
+ request_timestamp = get_request_timestamp
43
+ string_to_encrypt = request_timestamp + @access_key
44
+ OpenSSL::HMAC.hexdigest(DIGEST, @secret_key, string_to_encrypt)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,126 @@
1
+ require File.expand_path('authentication_header', File.dirname(__FILE__))
2
+
3
+ module Rapleaf
4
+ module Marketo
5
+ def self.new_client(access_key, secret_key)
6
+ client = Savon::Client.new do
7
+ wsdl.endpoint = "https://na-i.marketo.com/soap/mktows/1_5"
8
+ wsdl.document = "http://app.marketo.com/soap/mktows/1_4?WSDL"
9
+ http.read_timeout = 90
10
+ http.open_timeout = 90
11
+ http.headers = {"Connection" => "Keep-Alive"}
12
+ end
13
+
14
+ Client.new(client, Rapleaf::Marketo::AuthenticationHeader.new(access_key, secret_key))
15
+ end
16
+
17
+ # = The client for talking to marketo
18
+ # based on the SOAP wsdl file: <i>http://app.marketo.com/soap/mktows/1_4?WSDL</i>
19
+ #
20
+ # Usage:
21
+ #
22
+ # client = Rapleaf::Marketo.new_client(<access_key>, <secret_key>)
23
+ #
24
+ # client.sync_lead('john@gmail.com', 'john', 'smith', 'rapleaf', '1122 334 455', 'api')
25
+ class Client
26
+ def initialize(savon_client, authentication_header)
27
+ @client = savon_client
28
+ @header = authentication_header
29
+ end
30
+
31
+ public
32
+
33
+ def get_lead_by_idnum(idnum)
34
+ get_lead(LeadKey.new(LeadKeyType::IDNUM, idnum))
35
+ end
36
+
37
+
38
+ def get_lead_by_email(email)
39
+ get_lead(LeadKey.new(LeadKeyType::EMAIL, email))
40
+ end
41
+
42
+ # create (if new) or update (if existing) a lead
43
+ #
44
+ # * email - email address of lead
45
+ # * first - first name of lead
46
+ # * last - surname/last name of lead
47
+ # * company - company the lead is associated with
48
+ # * mobile - mobile/cell phone number
49
+ # * api_key - rapleaf API key
50
+ def sync_lead(email, first, last, company, mobile, api_key)
51
+ begin
52
+ response = send_request("ns1:paramsSyncLead", {
53
+ :return_lead => true,
54
+ :lead_record =>
55
+ {:email => email,
56
+ :lead_attribute_list => {
57
+ :attribute => [
58
+ {:attr_name => 'FirstName', :attr_type => 'string', :attr_value => first},
59
+ {:attr_name => 'LastName', :attr_type => 'string', :attr_value => last},
60
+ {:attr_name => 'Email', :attr_type => 'string', :attr_value => email},
61
+ {:attr_name => 'Company', :attr_type => 'string', :attr_value => company},
62
+ {:attr_name => 'MobilePhone', :attr_type => 'string', :attr_value => mobile},
63
+ {:attr_name => 'API_Key__c', :attr_type => 'string', :attr_value => api_key}
64
+ ]}}})
65
+ return response
66
+ rescue Exception => e
67
+ return nil
68
+ end
69
+ end
70
+
71
+ def add_to_list(list_key, email)
72
+ list_operation(list_key, ListOperationType::ADD_TO, email)
73
+ end
74
+
75
+ def remove_from_list(list_key, email)
76
+ list_operation(list_key, ListOperationType::REMOVE_FROM, email)
77
+ end
78
+
79
+ def is_member_of_list?(list_key, email)
80
+ list_operation(list_key, ListOperationType::IS_MEMBER_OF, email)
81
+ end
82
+
83
+ private
84
+ def list_operation(list_key, list_operation_type, email)
85
+ begin
86
+ response = send_request("ns1:paramsListOperation", {
87
+ :list_operation => list_operation_type,
88
+ :list_key => list_key,
89
+ :strict => 'false',
90
+ :list_member_list => {
91
+ :lead_key => [
92
+ {:key_type => 'EMAIL', :key_value => email}
93
+ ]
94
+ }
95
+ })
96
+ return response
97
+ rescue Exception => e
98
+ return nil
99
+ end
100
+ end
101
+
102
+ def get_lead(lead_key)
103
+ begin
104
+ response = send_request("ns1:paramsGetLead", {:lead_key => lead_key.to_hash})
105
+ return LeadRecord.from_hash(response[:success_get_lead][:result][:lead_record_list][:lead_record])
106
+ rescue Exception => e
107
+ return nil
108
+ end
109
+ end
110
+
111
+ def send_request(namespace, body)
112
+ @header.set_time(DateTime.now)
113
+ response = request(namespace, body, @header.to_hash)
114
+ response.to_hash
115
+ end
116
+
117
+ def request(namespace, body, header)
118
+ @client.request namespace do |soap|
119
+ soap.namespaces["xmlns:ns1"] = "http://www.marketo.com/mktows/"
120
+ soap.body = body
121
+ soap.header["ns1:AuthenticationHeader"] = header
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,23 @@
1
+ module Rapleaf
2
+ module Marketo
3
+ # Types of operations you can do on a marketo list
4
+ module ListOperationType
5
+ ADD_TO = 'ADDTOLIST'
6
+ REMOVE_FROM = 'REMOVEFROMLIST'
7
+ IS_MEMBER_OF = 'ISMEMBEROFLIST'
8
+ end
9
+
10
+ # Types of keys that can be used to look up a lead
11
+ module LeadKeyType
12
+ IDNUM = "IDNUM"
13
+ COOKIE = "COOKIE"
14
+ EMAIL = "EMAIL"
15
+ LEADOWNEREMAIL = "LEADOWNEREMAIL"
16
+ SFDCACCOUNTID = "SFDCACCOUNTID"
17
+ SFDCCONTACTID = "SFDCCONTACTID"
18
+ SFDCLEADID = "SFDCLEADID"
19
+ SFDCLEADOWNERID = "SFDCLEADOWNERID"
20
+ SFDCOPPTYID = "SFDCOPPTYID"
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,31 @@
1
+ module Rapleaf
2
+ module Marketo
3
+ # Encapsulates a key used to look up or describe a specific marketo lead.
4
+ class LeadKey
5
+ # - *key_type* the type of key to use see LeadKeyType
6
+ # - *key_value* normally a string value for the given type
7
+ def initialize(key_type, key_value)
8
+ @key_type = key_type
9
+ @key_value = key_value
10
+ end
11
+
12
+ # get the key type
13
+ def key_type
14
+ @key_type
15
+ end
16
+
17
+ # get the key value
18
+ def key_value
19
+ @key_value
20
+ end
21
+
22
+ # create a hash from this instance, for sending this object to marketo using savon
23
+ def to_hash
24
+ {
25
+ :key_type => @key_type,
26
+ :key_value => @key_value
27
+ }
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,58 @@
1
+ module Rapleaf
2
+ module Marketo
3
+ # Represents a record of the data known about a lead within marketo
4
+ class LeadRecord
5
+ def initialize(email, idnum)
6
+ @email = email
7
+ @idnum = idnum
8
+ @attributes = {}
9
+ end
10
+
11
+ # hydrates an instance from a savon hash returned form the marketo API
12
+ def self.from_hash(savon_hash)
13
+ lead_record = LeadRecord.new(savon_hash[:email], savon_hash[:id].to_i)
14
+ savon_hash[:lead_attribute_list][:attribute].each do |attribute|
15
+ lead_record.set_attribute(attribute[:attr_name], attribute[:attr_value])
16
+ end
17
+ lead_record
18
+ end
19
+
20
+ # get the record idnum
21
+ def idnum
22
+ @idnum
23
+ end
24
+
25
+ # get the record email
26
+ def email
27
+ @email
28
+ end
29
+
30
+ def attributes
31
+ @attributes
32
+ end
33
+
34
+ # update the value of the named attribute
35
+ def set_attribute(name, value)
36
+ @attributes[name] = value
37
+ end
38
+
39
+ # get the value for the named attribute
40
+ def get_attribute(name)
41
+ @attributes[name]
42
+ end
43
+
44
+ # will yield pairs of |attribute_name, attribute_value|
45
+ def each_attribute_pair(&block)
46
+ @attributes.each_pair do |name, value|
47
+ block.call(name, value)
48
+ end
49
+ end
50
+
51
+ def ==(other)
52
+ @attributes == other.attributes &&
53
+ @idnum == other.idnum &&
54
+ @email == other.email
55
+ end
56
+ end
57
+ end
58
+ 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,263 @@
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, API_KEY).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
+ {:lead_key => {
64
+ :key_value => IDNUM,
65
+ :key_type => LeadKeyType::IDNUM}},
66
+ 'ns1:paramsGetLead',
67
+ response_hash)
68
+ expected_lead_record = LeadRecord.new(EMAIL, IDNUM)
69
+ expected_lead_record.set_attribute('name1', 'val1')
70
+ expected_lead_record.set_attribute('name2', 'val2')
71
+ expected_lead_record.set_attribute('name3', 'val3')
72
+ expected_lead_record.set_attribute('name4', 'val4')
73
+ client.get_lead_by_idnum(IDNUM).should == expected_lead_record
74
+ end
75
+
76
+ it "should have the correct body format on get_lead_by_email" do
77
+ savon_client = mock('savon_client')
78
+ authentication_header = mock('authentication_header')
79
+ client = Rapleaf::Marketo::Client.new(savon_client, authentication_header)
80
+ response_hash = {
81
+ :success_get_lead => {
82
+ :result => {
83
+ :count => 1,
84
+ :lead_record_list => {
85
+ :lead_record => {
86
+ :email => EMAIL,
87
+ :lead_attribute_list => {
88
+ :attribute => [
89
+ {:attr_name => 'name1', :attr_type => 'string', :attr_value => 'val1'},
90
+ {:attr_name => 'name2', :attr_type => 'string', :attr_value => 'val2'},
91
+ {:attr_name => 'name3', :attr_type => 'string', :attr_value => 'val3'},
92
+ {:attr_name => 'name4', :attr_type => 'string', :attr_value => 'val4'}
93
+ ]
94
+ },
95
+ :foreign_sys_type => nil,
96
+ :foreign_sys_person_id => nil,
97
+ :id => IDNUM.to_s
98
+ }
99
+ }
100
+ }
101
+ }
102
+ }
103
+ expect_request(savon_client,
104
+ authentication_header,
105
+ {:lead_key => {
106
+ :key_value => EMAIL,
107
+ :key_type => LeadKeyType::EMAIL}},
108
+ 'ns1:paramsGetLead',
109
+ response_hash)
110
+ expected_lead_record = LeadRecord.new(EMAIL, IDNUM)
111
+ expected_lead_record.set_attribute('name1', 'val1')
112
+ expected_lead_record.set_attribute('name2', 'val2')
113
+ expected_lead_record.set_attribute('name3', 'val3')
114
+ expected_lead_record.set_attribute('name4', 'val4')
115
+ client.get_lead_by_email(EMAIL).should == expected_lead_record
116
+ end
117
+
118
+ it "should have the correct body format on sync_lead" do
119
+ savon_client = mock('savon_client')
120
+ authentication_header = mock('authentication_header')
121
+ client = Rapleaf::Marketo::Client.new(savon_client, authentication_header)
122
+ response_hash = {} # TODO
123
+ expect_request(savon_client,
124
+ authentication_header,
125
+ {
126
+ :return_lead => true,
127
+ :lead_record => {
128
+ :email => "some@email.com",
129
+ :lead_attribute_list =>
130
+ {
131
+ :attribute => [
132
+ {:attr_value => "Joe",
133
+ :attr_name => "FirstName",
134
+ :attr_type => "string"},
135
+ {:attr_value => "Smith",
136
+ :attr_name => "LastName",
137
+ :attr_type => "string"},
138
+ {:attr_value => "some@email.com",
139
+ :attr_name =>"Email",
140
+ :attr_type => "string"},
141
+ {:attr_value => "Rapleaf",
142
+ :attr_name =>"Company",
143
+ :attr_type =>"string"},
144
+ {:attr_value =>"415 123 456",
145
+ :attr_name =>"MobilePhone",
146
+ :attr_type =>"string"},
147
+ {:attr_value =>"API123KEY",
148
+ :attr_name =>"API_Key__c",
149
+ :attr_type =>"string"}
150
+ ]}}},
151
+ 'ns1:paramsSyncLead',
152
+ response_hash)
153
+ client.sync_lead(EMAIL, FIRST, LAST, COMPANY, MOBILE, API_KEY).should == response_hash
154
+ end
155
+
156
+ context "list operations" do
157
+ before(:each) do
158
+ LIST_KEY = 'awesome leads list'
159
+ @savon_client = mock('savon_client')
160
+ @authentication_header = mock('authentication_header')
161
+ @client = Rapleaf::Marketo::Client.new(@savon_client, @authentication_header)
162
+ end
163
+
164
+ it "should have the correct body format on add_to_list" do
165
+ response_hash = {} # TODO
166
+ expect_request(@savon_client,
167
+ @authentication_header,
168
+ {
169
+ :list_operation => ListOperationType::ADD_TO,
170
+ :list_key => LIST_KEY,
171
+ :strict => 'false',
172
+ :list_member_list => {
173
+ :lead_key => [
174
+ {
175
+ :key_type => 'EMAIL',
176
+ :key_value => EMAIL
177
+ }
178
+ ]
179
+ }
180
+ },
181
+ 'ns1:paramsListOperation',
182
+ response_hash)
183
+
184
+ @client.add_to_list(LIST_KEY, EMAIL).should == response_hash
185
+ end
186
+
187
+ it "should have the correct body format on remove_from_list" do
188
+ response_hash = {} # TODO
189
+ expect_request(@savon_client,
190
+ @authentication_header,
191
+ {
192
+ :list_operation => ListOperationType::REMOVE_FROM,
193
+ :list_key => LIST_KEY,
194
+ :strict => 'false',
195
+ :list_member_list => {
196
+ :lead_key => [
197
+ {
198
+ :key_type => 'EMAIL',
199
+ :key_value => EMAIL
200
+ }
201
+ ]
202
+ }
203
+ },
204
+ 'ns1:paramsListOperation',
205
+ response_hash)
206
+
207
+ @client.remove_from_list(LIST_KEY, EMAIL).should == response_hash
208
+ end
209
+
210
+ it "should have the correct body format on is_member_of_list?" do
211
+ response_hash = {} # TODO
212
+ expect_request(@savon_client,
213
+ @authentication_header,
214
+ {
215
+ :list_operation => ListOperationType::IS_MEMBER_OF,
216
+ :list_key => LIST_KEY,
217
+ :strict => 'false',
218
+ :list_member_list => {
219
+ :lead_key => [
220
+ {
221
+ :key_type => 'EMAIL',
222
+ :key_value => EMAIL
223
+ }
224
+ ]
225
+ }
226
+ },
227
+ 'ns1:paramsListOperation',
228
+ response_hash)
229
+
230
+ @client.is_member_of_list?(LIST_KEY, EMAIL).should == response_hash
231
+ end
232
+ end
233
+ end
234
+
235
+ private
236
+
237
+ def expect_request(savon_client, authentication_header, expected_body, expected_namespace, response_hash)
238
+ header_hash = stub('header_hash')
239
+ soap_response = stub('soap_response')
240
+ request_namespace = mock('namespace')
241
+ request_header = mock('request_header')
242
+ soap_request = mock('soap_request')
243
+ authentication_header.should_receive(:set_time)
244
+ authentication_header.should_receive(:to_hash).and_return(header_hash)
245
+ request_namespace.should_receive(:[]=).with("xmlns:ns1", "http://www.marketo.com/mktows/")
246
+ request_header.should_receive(:[]=).with("ns1:AuthenticationHeader", header_hash)
247
+ soap_request.should_receive(:namespaces).and_return(request_namespace)
248
+ soap_request.should_receive(:header).and_return(request_header)
249
+ soap_request.should_receive(:body=).with(expected_body)
250
+ soap_response.should_receive(:to_hash).and_return(response_hash)
251
+ savon_client.should_receive(:request).with(expected_namespace).and_yield(soap_request).and_return(soap_response)
252
+ end
253
+ end
254
+
255
+ describe ListOperationType do
256
+ it 'should define the correct types' do
257
+ ListOperationType::ADD_TO.should == 'ADDTOLIST'
258
+ ListOperationType::IS_MEMBER_OF.should == 'ISMEMBEROFLIST'
259
+ ListOperationType::REMOVE_FROM.should == 'REMOVEFROMLIST'
260
+ end
261
+ end
262
+ end
263
+ end
@@ -0,0 +1,40 @@
1
+ require File.expand_path('../spec_helper', File.dirname(__FILE__))
2
+
3
+ module Rapleaf
4
+ module Marketo
5
+ describe LeadKeyType do
6
+ it "should define the correct types" do
7
+ LeadKeyType::IDNUM.should == 'IDNUM'
8
+ LeadKeyType::COOKIE.should == 'COOKIE'
9
+ LeadKeyType::EMAIL.should == 'EMAIL'
10
+ LeadKeyType::LEADOWNEREMAIL.should == 'LEADOWNEREMAIL'
11
+ LeadKeyType::SFDCACCOUNTID.should == 'SFDCACCOUNTID'
12
+ LeadKeyType::SFDCCONTACTID.should == 'SFDCCONTACTID'
13
+ LeadKeyType::SFDCLEADID.should == 'SFDCLEADID'
14
+ LeadKeyType::SFDCLEADOWNERID.should == 'SFDCLEADOWNERID'
15
+ LeadKeyType::SFDCOPPTYID.should == 'SFDCOPPTYID'
16
+ end
17
+ end
18
+
19
+ describe LeadKey do
20
+ it "should store type and value on construction" do
21
+ KEY_VALUE = 'a value'
22
+ KEY_TYPE = LeadKeyType::IDNUM
23
+ lead_key = LeadKey.new(KEY_TYPE, KEY_VALUE)
24
+ lead_key.key_type.should == KEY_TYPE
25
+ lead_key.key_value.should == KEY_VALUE
26
+ end
27
+
28
+ it "should to_hash correctly" do
29
+ KEY_VALUE = 'a value'
30
+ KEY_TYPE = LeadKeyType::IDNUM
31
+ lead_key = LeadKey.new(KEY_TYPE, KEY_VALUE)
32
+
33
+ lead_key.to_hash.should == {
34
+ :key_type => KEY_TYPE,
35
+ :key_value => KEY_VALUE
36
+ }
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,88 @@
1
+ require File.expand_path('../spec_helper', File.dirname(__FILE__))
2
+
3
+ module Rapleaf
4
+ module Marketo
5
+ EMAIL = 'some@email.com'
6
+ IDNUM = 93480938
7
+
8
+ describe LeadRecord do
9
+ it "should store the idnum" do
10
+ LeadRecord.new(EMAIL, IDNUM).idnum.should == IDNUM
11
+ end
12
+
13
+ it "should store the email" do
14
+ LeadRecord.new(EMAIL, IDNUM).email.should == EMAIL
15
+ end
16
+
17
+ it "should implement == sensibly" do
18
+ lead_record1 = LeadRecord.new(EMAIL, IDNUM)
19
+ lead_record1.set_attribute('favourite color', 'red')
20
+ lead_record1.set_attribute('age', '100')
21
+
22
+ lead_record2 = LeadRecord.new(EMAIL, IDNUM)
23
+ lead_record2.set_attribute('favourite color', 'red')
24
+ lead_record2.set_attribute('age', '100')
25
+
26
+ lead_record1.should == lead_record2
27
+ end
28
+
29
+ it "should store when attributes are set" do
30
+ lead_record = LeadRecord.new(EMAIL, IDNUM)
31
+ lead_record.set_attribute('favourite color', 'red')
32
+ lead_record.get_attribute('favourite color').should == 'red'
33
+ end
34
+
35
+ it "should store when attributes are updated" do
36
+ lead_record = LeadRecord.new(EMAIL, IDNUM)
37
+ lead_record.set_attribute('favourite color', 'red')
38
+ lead_record.set_attribute('favourite color', 'green')
39
+ lead_record.get_attribute('favourite color').should == 'green'
40
+ end
41
+
42
+ it "should yield all attributes through each_attribute_pair" do
43
+ lead_record = LeadRecord.new(EMAIL, IDNUM)
44
+ lead_record.set_attribute('favourite color', 'red')
45
+ lead_record.set_attribute('favourite color', 'green')
46
+ lead_record.set_attribute('age', '99')
47
+
48
+ pairs = []
49
+ lead_record.each_attribute_pair do |attribute_name, attribute_value|
50
+ pairs << [attribute_name, attribute_value]
51
+ end
52
+
53
+ pairs.size.should == 2
54
+ pairs.should include(['favourite color', 'green'])
55
+ pairs.should include(['age', '99'])
56
+ end
57
+
58
+ it "should be instantiable from a savon hash" do
59
+ savon_hash = {
60
+ :email => EMAIL,
61
+ :foreign_sys_type => nil,
62
+ :lead_attribute_list => {
63
+ :attribute => [
64
+ { :attr_name => 'Company', :attr_type => 'string', :attr_value => 'Rapleaf'},
65
+ { :attr_name => 'FirstName', :attr_type => 'string', :attr_value => 'James'},
66
+ { :attr_name => 'LastName', :attr_type => 'string', :attr_value => 'O\'Brien'}
67
+ ]
68
+ },
69
+ :foreign_sys_person_id => nil,
70
+ :id => IDNUM
71
+ }
72
+
73
+ actual = LeadRecord.from_hash(savon_hash)
74
+
75
+ actual.email.should == EMAIL
76
+ actual.idnum.should == IDNUM
77
+ pairs = []
78
+ actual.each_attribute_pair do |attribute_name, attribute_value|
79
+ pairs << [attribute_name, attribute_value]
80
+ end
81
+ pairs.size.should == 3
82
+ pairs.should include(['Company', 'Rapleaf'])
83
+ pairs.should include(['FirstName', 'James'])
84
+ pairs.should include(['LastName', 'O\'Brien'])
85
+ end
86
+ end
87
+ end
88
+ end
metadata ADDED
@@ -0,0 +1,109 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: marketo
3
+ version: !ruby/object:Gem::Version
4
+ hash: 19
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 1
9
+ - 0
10
+ version: 1.1.0
11
+ platform: ruby
12
+ authors:
13
+ - James O'Brien
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-01-31 00:00:00 -08:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: rspec
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :development
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: savon
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :runtime
48
+ version_requirements: *id002
49
+ description: Allows easy integration with marketo from ruby. You can synchronize leads and fetch them back by email.
50
+ email: james@rapleaf.com
51
+ executables: []
52
+
53
+ extensions: []
54
+
55
+ extra_rdoc_files: []
56
+
57
+ files:
58
+ - lib/marketo/authentication_header.rb
59
+ - lib/marketo/client.rb
60
+ - lib/marketo/enums.rb
61
+ - lib/marketo/lead_key.rb
62
+ - lib/marketo/lead_record.rb
63
+ - lib/marketo.rb
64
+ - spec/marketo/authentication_header_spec.rb
65
+ - spec/marketo/client_spec.rb
66
+ - spec/marketo/lead_key_spec.rb
67
+ - spec/marketo/lead_record_spec.rb
68
+ has_rdoc: true
69
+ homepage: http://www.rapleaf.com
70
+ licenses:
71
+ - - Rapleaf internal - do not use without permission
72
+ post_install_message:
73
+ rdoc_options:
74
+ - --title
75
+ - Marketo Client Gem
76
+ - --main
77
+ - Rapleaf::Marketo::Client
78
+ require_paths:
79
+ - - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ hash: 3
86
+ segments:
87
+ - 0
88
+ version: "0"
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ hash: 3
95
+ segments:
96
+ - 0
97
+ version: "0"
98
+ requirements: []
99
+
100
+ rubyforge_project:
101
+ rubygems_version: 1.3.7
102
+ signing_key:
103
+ specification_version: 3
104
+ summary: A client for using the marketo API within Rapleaf
105
+ test_files:
106
+ - spec/marketo/authentication_header_spec.rb
107
+ - spec/marketo/client_spec.rb
108
+ - spec/marketo/lead_key_spec.rb
109
+ - spec/marketo/lead_record_spec.rb