marketo-api-ruby 0.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,86 @@
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
+ lead_record = LeadRecord.new(EMAIL, IDNUM)
11
+ lead_record.idnum.should == IDNUM
12
+ end
13
+
14
+ it "should store the email" do
15
+ LeadRecord.new(EMAIL, IDNUM).email.should == EMAIL
16
+ end
17
+
18
+ it "should implement == sensibly" do
19
+ lead_record1 = LeadRecord.new(EMAIL, IDNUM)
20
+ lead_record1.set_attribute('favourite color', 'red')
21
+ lead_record1.set_attribute('age', '100')
22
+
23
+ lead_record2 = LeadRecord.new(EMAIL, IDNUM)
24
+ lead_record2.set_attribute('favourite color', 'red')
25
+ lead_record2.set_attribute('age', '100')
26
+
27
+ lead_record1.should == lead_record2
28
+ end
29
+
30
+ it "should store when attributes are set" do
31
+ lead_record = LeadRecord.new(EMAIL, IDNUM)
32
+ lead_record.set_attribute('favourite color', 'red')
33
+ lead_record.get_attribute('favourite color').should == 'red'
34
+ end
35
+
36
+ it "should store when attributes are updated" do
37
+ lead_record = LeadRecord.new(EMAIL, IDNUM)
38
+ lead_record.set_attribute('favourite color', 'red')
39
+ lead_record.set_attribute('favourite color', 'green')
40
+ lead_record.get_attribute('favourite color').should == 'green'
41
+ end
42
+
43
+ it "should yield all attributes through each_attribute_pair" do
44
+ lead_record = LeadRecord.new(EMAIL, IDNUM)
45
+ lead_record.set_attribute('favourite color', 'red')
46
+ lead_record.set_attribute('favourite color', 'green')
47
+ lead_record.set_attribute('age', '99')
48
+
49
+ pairs = []
50
+ lead_record.each_attribute_pair do |attribute_name, attribute_value|
51
+ pairs << [attribute_name, attribute_value]
52
+ end
53
+
54
+ pairs.size.should == 3
55
+ pairs.should include(['favourite color', 'green'])
56
+ pairs.should include(['age', '99'])
57
+ pairs.should include(['Email', EMAIL])
58
+ end
59
+
60
+ it "should be instantiable from a savon hash" do
61
+ savon_hash = {
62
+ :email => EMAIL,
63
+ :foreign_sys_type => nil,
64
+ :lead_attribute_list => {
65
+ :attribute => [
66
+ { :attr_name => 'Company', :attr_type => 'string', :attr_value => 'Rapleaf'},
67
+ { :attr_name => 'FirstName', :attr_type => 'string', :attr_value => 'James'},
68
+ { :attr_name => 'LastName', :attr_type => 'string', :attr_value => 'O\'Brien'}
69
+ ]
70
+ },
71
+ :foreign_sys_person_id => nil,
72
+ :id => IDNUM
73
+ }
74
+
75
+ actual = LeadRecord.from_hash(savon_hash)
76
+
77
+ expected = LeadRecord.new(EMAIL, IDNUM)
78
+ expected.set_attribute('Company', 'Rapleaf')
79
+ expected.set_attribute('FirstName', 'James')
80
+ expected.set_attribute('LastName', 'O\'Brien')
81
+
82
+ actual.should == expected
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,4 @@
1
+ require "rubygems"
2
+ require "rspec"
3
+
4
+ require File.expand_path('../lib/marketo', File.dirname(__FILE__))
@@ -0,0 +1,173 @@
1
+ require "minitest_helper"
2
+
3
+ class TestMarketoAPICampaigns < Minitest::Test
4
+ include MarketoTestHelper
5
+
6
+ def setup
7
+ super
8
+ @subject = @client.campaigns
9
+ end
10
+
11
+ def test_for_marketo
12
+ assert subject.respond_to? :for_marketo
13
+ stub_specialized :for_source do
14
+ assert_equal :MKTOWS, subject.for_marketo.first
15
+ end
16
+ stub_soap_call do
17
+ method, options = subject.for_marketo
18
+ assert_equal :get_campaigns_for_source, method
19
+ assert_equal({ source: :MKTOWS }, options)
20
+ end
21
+ end
22
+
23
+ def test_for_sales
24
+ assert subject.respond_to? :for_sales
25
+ stub_specialized :for_source do
26
+ assert_equal :SALES, subject.for_sales.first
27
+ end
28
+ stub_soap_call do
29
+ method, options = subject.for_sales
30
+ assert_equal :get_campaigns_for_source, method
31
+ assert_equal({ source: :SALES }, options)
32
+ end
33
+ end
34
+
35
+ def test_for_source_bad_source
36
+ assert_raises(ArgumentError) { subject.for_source :bad_source }
37
+ end
38
+
39
+ def test_for_source_marketo_name
40
+ stub_soap_call do
41
+ method, options = subject.for_source :marketo, 'John'
42
+ assert_equal :get_campaigns_for_source, method
43
+ assert_equal({ source: :MKTOWS, name: 'John' }, options)
44
+ end
45
+ end
46
+
47
+ def test_for_source_sales_name_exact
48
+ stub_soap_call do
49
+ method, options = subject.for_source :marketo, 'John', true
50
+ assert_equal :get_campaigns_for_source, method
51
+ assert_equal({ source: :MKTOWS, name: 'John', exact_name: true },
52
+ options)
53
+ end
54
+ end
55
+
56
+ def test_request_marketo
57
+ assert subject.respond_to? :request_marketo
58
+ stub_specialized :request do
59
+ options = subject.request_marketo.first
60
+ assert_equal({ source: :MKTOWS }, options)
61
+ end
62
+ end
63
+
64
+ def test_request_sales
65
+ assert subject.respond_to? :request_sales
66
+ stub_specialized :request do
67
+ options = subject.request_sales.first
68
+ assert_equal({ source: :SALES }, options)
69
+ end
70
+ end
71
+
72
+ def test_request_missing_leads
73
+ assert_raises(ArgumentError) {
74
+ subject.request
75
+ }
76
+ end
77
+
78
+ def test_request_missing_campaign_or_program
79
+ assert_raises(ArgumentError) {
80
+ subject.request(lead: :foo)
81
+ }
82
+ end
83
+
84
+ def test_request_program_token_with_no_program_name
85
+ assert_raises(KeyError) {
86
+ subject.request(lead: :foo, campaign_id: 5, program_tokens: [ 3 ])
87
+ }
88
+ end
89
+
90
+ def test_request_with_campaign_id_and_name
91
+ assert_raises(ArgumentError) {
92
+ subject.request(lead: :foo, campaign_id: 5, campaign_name: 'Five')
93
+ }
94
+ end
95
+
96
+ def test_request_bad_source
97
+ assert_raises(ArgumentError) {
98
+ subject.request(lead: :foo, campaign_id: 5, source: :bad_source)
99
+ }
100
+ end
101
+
102
+ def test_request_merged_leads_campaign_id_default_source
103
+ stub_soap_call do
104
+ method, options = subject.request(lead: lead_key(3),
105
+ leads: lead_keys(4, 5),
106
+ campaign_id: 3)
107
+ assert_equal :request_campaign, method
108
+ assert_equal :MKTOWS, options[:source]
109
+ assert_equal lead_keys(4, 5, 3), options[:lead_list]
110
+ assert_equal 3, options[:campaign_id]
111
+ assert_missing_keys options, :campaign_name, :program_name,
112
+ :program_tokens
113
+ end
114
+ end
115
+
116
+ def test_request_using_campaign_name
117
+ stub_soap_call do
118
+ method, options = subject.request(lead: lead_key(3),
119
+ campaign_name: 'earthday')
120
+ assert_equal :request_campaign, method
121
+ assert_equal :MKTOWS, options[:source]
122
+ assert_equal [ lead_key(3) ], options[:lead_list]
123
+ assert_equal 'earthday', options[:campaign_name]
124
+ assert_missing_keys options, :campaign_id, :program_name,
125
+ :program_tokens
126
+ end
127
+ end
128
+
129
+ def test_request_using_program_name
130
+ stub_soap_call do
131
+ method, options = subject.request(lead: lead_key(3),
132
+ program_name: 'earthday')
133
+ assert_equal :request_campaign, method
134
+ assert_equal :MKTOWS, options[:source]
135
+ assert_equal [ lead_key(3) ], options[:lead_list]
136
+ assert_equal 'earthday', options[:program_name]
137
+ assert_missing_keys options, :campaign_name, :campaign_id,
138
+ :program_tokens
139
+ end
140
+ end
141
+
142
+ def test_schedule
143
+ stub_soap_call do
144
+ method, options = subject.schedule('program', 'campaign')
145
+ assert_equal :schedule_campaign, method
146
+ assert_equal({ program_name: 'program', campaign_name: 'campaign' }, options)
147
+ end
148
+ end
149
+
150
+ def test_schedule_with_run_at
151
+ stub_soap_call do
152
+ method, options = subject.schedule('program', 'campaign', run_at: 3)
153
+ assert_equal :schedule_campaign, method
154
+ assert_equal({
155
+ program_name: 'program',
156
+ campaign_name: 'campaign',
157
+ campaign_run_at: 3
158
+ }, options)
159
+ end
160
+ end
161
+
162
+ def test_schedule_with_program_tokens
163
+ stub_soap_call do
164
+ method, options = subject.schedule('program', 'campaign', program_tokens: [ :x ])
165
+ assert_equal :schedule_campaign, method
166
+ assert_equal({
167
+ program_name: 'program',
168
+ campaign_name: 'campaign',
169
+ program_token_list: [ :x ]
170
+ }, options)
171
+ end
172
+ end
173
+ end
@@ -0,0 +1,83 @@
1
+ require "minitest_helper"
2
+
3
+ class TestMarketoAPIClient < Minitest::Test
4
+ include MarketoTestHelper
5
+
6
+ def setup
7
+ super
8
+ @subject = @client
9
+ end
10
+
11
+ def test_api_version
12
+ assert_equal '2_3', subject.api_version
13
+ assert_equal '2_4', setup_client(api_version: '2_4').api_version
14
+ end
15
+
16
+ def test_subdomain
17
+ assert_equal '123-ABC-456', subject.subdomain
18
+ assert_equal 'testable', setup_client(api_subdomain: 'testable').subdomain
19
+ end
20
+
21
+ def test_wsdl
22
+ assert_equal "http://app.marketo.com/soap/mktows/2_3?WSDL",
23
+ subject.wsdl
24
+ assert_equal "http://app.marketo.com/soap/mktows/2_4?WSDL",
25
+ setup_client(api_version: '2_4').wsdl
26
+ end
27
+
28
+ def test_endpoint
29
+ assert_equal "https://123-ABC-456.mktoapi.com/soap/mktows/2_3",
30
+ subject.endpoint
31
+ assert_equal "https://testable.mktoapi.com/soap/mktows/2_4",
32
+ setup_client(api_subdomain: 'testable', api_version: '2_4').endpoint
33
+ end
34
+
35
+ def test_generated_methods
36
+ assert subject.respond_to? :campaigns
37
+ assert subject.respond_to? :leads
38
+ assert subject.respond_to? :lists
39
+ assert subject.respond_to? :mobjects
40
+ refute subject.respond_to? :customobjects
41
+ end
42
+
43
+ def stub_savon callable = nil, &block
44
+ callable ||= ARGS_STUB
45
+ subject.instance_variable_get(:@savon).stub :call, callable do
46
+ block.call if block
47
+ end
48
+ end
49
+
50
+ def test_call_exception_suppressed
51
+ stub_savon -> { raise ArgumentError } do
52
+ assert_nil subject.call(:web_method, {})
53
+ assert subject.error?
54
+ refute_nil subject.error
55
+ assert_instance_of ArgumentError, subject.error
56
+ end
57
+ end
58
+
59
+ def test_call_with_auth
60
+ time = Time.now.to_i
61
+
62
+ signature = {
63
+ mktowsUserId: 'user',
64
+ requestTimestamp: time.to_s,
65
+ requestSignature: OpenSSL::HMAC.hexdigest(
66
+ OpenSSL::Digest.new('sha1'),
67
+ 'key',
68
+ "#{time}user"
69
+ )
70
+ }
71
+
72
+ Time.stub :now, -> { time } do
73
+ stub_savon do
74
+ method, params = subject.call(:web_method, {})
75
+ assert_equal :web_method, method
76
+ assert_equal({
77
+ message: {},
78
+ soap_header: { 'ns1:AuthenticationHeader' => signature }
79
+ }, params)
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,158 @@
1
+ require "minitest_helper"
2
+
3
+ class TestMarketoAPILead < Minitest::Test
4
+ include MarketoTestHelper
5
+
6
+ def setup
7
+ super
8
+ @id = 99
9
+ @date = DateTime.new(2014, 01, 01)
10
+ @email = 'great@gretzky.com'
11
+ @attributes = {
12
+ String: 'string',
13
+ Int: 5,
14
+ Date: @date
15
+ }
16
+ @subject = MarketoAPI::Lead.new(id: @id, email: @email) do |lead|
17
+ @attributes.each { |k, v| lead[k] = v }
18
+ end
19
+ end
20
+
21
+ def test_id
22
+ assert_equal 99, subject.id
23
+ end
24
+
25
+ def test_cookie
26
+ assert_nil subject.cookie
27
+ subject.cookie = 'cookie'
28
+ refute_nil subject.cookie
29
+ assert_equal 'cookie', subject.cookie
30
+ end
31
+
32
+ def test_attributes
33
+ assert_equal @attributes.merge(Email: @email), subject.attributes
34
+ end
35
+
36
+ def test_types
37
+ types = Hash[*@attributes.merge(Email: @email).map { |(k, v)|
38
+ [ k, subject.send(:infer_value_type, v) ]
39
+ }.flatten]
40
+ assert_equal types, subject.types
41
+ end
42
+
43
+ def test_proxy_bad_assignment
44
+ assert_raises(ArgumentError) { subject.proxy = :invalid }
45
+ end
46
+
47
+ def test_proxy_leads_assignment
48
+ assert_same @client.leads, subject.proxy = @client.leads
49
+ end
50
+
51
+ def test_proxy_proxy_assignment
52
+ subject.proxy = @client.campaigns
53
+ assert_same @client.leads, subject.proxy
54
+ end
55
+
56
+ def test_proxy_client_assignment
57
+ subject.proxy = @client
58
+ assert_same @client.leads, subject.proxy
59
+ end
60
+
61
+ def test_forwarded_methods
62
+ [
63
+ :[], :each, :each_pair, :each_key, :each_value, :keys, :values
64
+ ].each do |m|
65
+ assert subject.respond_to? m
66
+ end
67
+ end
68
+
69
+ def test_index_assignment
70
+ subject[:Test] = 33
71
+ assert subject.attributes.has_key? :Test
72
+ assert subject.types.has_key? :Test
73
+ assert_equal 33, subject.attributes[:Test]
74
+ assert_equal 'integer', subject.types[:Test]
75
+ end
76
+
77
+ def test_foreign
78
+ assert_equal({ type: :id, id: 3 }, subject.foreign('id', 3))
79
+ end
80
+
81
+ def test_sync_no_proxy
82
+ assert_raises(ArgumentError) { subject.sync }
83
+ assert_raises(ArgumentError) { subject.sync! }
84
+ end
85
+
86
+ def test_sync_with_proxy
87
+ @client.leads.stub :sync, ->(lead) { lead.dup } do
88
+ subject.proxy = @client.leads
89
+ assert_equal subject, subject.sync
90
+ refute_same subject, subject.sync
91
+ end
92
+ end
93
+
94
+ def test_sync_bang_failed
95
+ @client.leads.stub :sync, ->(lead) { nil } do
96
+ subject.proxy = @client.leads
97
+ assert_nil subject.sync!
98
+ end
99
+ end
100
+
101
+ def test_sync_bang_success
102
+ @client.leads.stub :sync, ->(lead) { lead.dup } do
103
+ subject.proxy = @client.leads
104
+ assert_same subject, subject.sync!
105
+ end
106
+ end
107
+
108
+ def test_params_for_get
109
+ assert_equal MarketoAPI::Lead.key(:IDNUM, @id), subject.params_for_get
110
+ end
111
+
112
+ def test_params_for_sync
113
+ result = {
114
+ return_lead: true,
115
+ lead_record: {
116
+ email: @email,
117
+ id: @id,
118
+ lead_attribute_list: {
119
+ attribute: [
120
+ { attr_name: 'Email', attr_type: 'string', attr_value: @email },
121
+ { attr_name: 'String', attr_type: 'string', attr_value: 'string' },
122
+ { attr_name: 'Int', attr_type: 'integer', attr_value: 5 },
123
+ { attr_name: 'Date', attr_type: 'datetime', attr_value: @date }
124
+ ]
125
+ }
126
+ }
127
+ }
128
+
129
+ assert_equal result, subject.params_for_sync
130
+ end
131
+
132
+ def test_class_key
133
+ subject.class::NAMED_KEYS.each { |k, v|
134
+ result = { lead_key: { key_type: v, key_value: 'value' } }
135
+
136
+ assert_equal result, subject.class.key(k, 'value')
137
+ assert_equal result, subject.class.key(v, 'value')
138
+ }
139
+
140
+ assert_raises(ArgumentError) { subject.class.key('invalid', 'value') }
141
+ end
142
+
143
+ def test_class_from_soap_hash
144
+ hash = {
145
+ id: @id.to_s,
146
+ email: @email,
147
+ lead_attribute_list: {
148
+ attribute: [
149
+ { attr_name: 'Email', attr_type: 'string', attr_value: @email },
150
+ { attr_name: 'String', attr_type: 'string', attr_value: 'string' },
151
+ { attr_name: 'Int', attr_type: 'integer', attr_value: 5 },
152
+ { attr_name: 'Date', attr_type: 'datetime', attr_value: @date }
153
+ ]
154
+ }
155
+ }
156
+ assert_equal subject, subject.class.from_soap_hash(hash)
157
+ end
158
+ end