mrkt 0.9.0 → 1.0.1

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.
Files changed (40) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +59 -5
  3. data/.travis.yml +19 -10
  4. data/Gemfile.lock +68 -63
  5. data/LICENSE +21 -0
  6. data/README.md +4 -1
  7. data/lib/mrkt.rb +14 -3
  8. data/lib/mrkt/concerns/authentication.rb +27 -12
  9. data/lib/mrkt/concerns/connection.rb +13 -7
  10. data/lib/mrkt/concerns/crud_activities.rb +12 -9
  11. data/lib/mrkt/concerns/crud_asset_folders.rb +43 -0
  12. data/lib/mrkt/concerns/crud_asset_static_lists.rb +30 -0
  13. data/lib/mrkt/concerns/crud_campaigns.rb +2 -4
  14. data/lib/mrkt/concerns/crud_custom_activities.rb +3 -2
  15. data/lib/mrkt/concerns/crud_custom_objects.rb +13 -14
  16. data/lib/mrkt/concerns/crud_helpers.rb +7 -0
  17. data/lib/mrkt/concerns/crud_leads.rb +35 -20
  18. data/lib/mrkt/concerns/crud_lists.rb +13 -10
  19. data/lib/mrkt/concerns/crud_programs.rb +6 -5
  20. data/lib/mrkt/concerns/import_custom_objects.rb +1 -1
  21. data/lib/mrkt/concerns/import_leads.rb +8 -5
  22. data/lib/mrkt/errors.rb +3 -2
  23. data/lib/mrkt/faraday.rb +4 -0
  24. data/lib/mrkt/faraday/params_encoder.rb +20 -0
  25. data/lib/mrkt/faraday_middleware.rb +3 -7
  26. data/lib/mrkt/version.rb +1 -1
  27. data/mrkt.gemspec +11 -12
  28. data/spec/concerns/authentication_spec.rb +57 -5
  29. data/spec/concerns/crud_activities_spec.rb +46 -7
  30. data/spec/concerns/crud_asset_folders_spec.rb +273 -0
  31. data/spec/concerns/crud_asset_static_lists_spec.rb +183 -0
  32. data/spec/concerns/crud_custom_activities_spec.rb +3 -1
  33. data/spec/concerns/crud_custom_objects_spec.rb +1 -1
  34. data/spec/concerns/crud_leads_spec.rb +104 -2
  35. data/spec/concerns/crud_lists_spec.rb +33 -0
  36. data/spec/concerns/import_leads_spec.rb +3 -3
  37. data/spec/faraday/params_encoder_spec.rb +24 -0
  38. data/spec/spec_helper.rb +3 -1
  39. data/spec/support/webmock.rb +1 -7
  40. metadata +44 -46
@@ -1,11 +1,7 @@
1
- require 'faraday'
1
+ require 'mrkt/faraday_middleware/response'
2
2
 
3
3
  module Mrkt
4
- module FaradayMiddleware
5
- autoload :Response, 'mrkt/faraday_middleware/response'
6
- end
7
-
8
- if Faraday::Middleware.respond_to? :register_middleware
9
- Faraday::Response.register_middleware mkto: -> { Mrkt::FaradayMiddleware::Response }
4
+ if ::Faraday::Middleware.respond_to?(:register_middleware)
5
+ ::Faraday::Response.register_middleware(mkto: Mrkt::FaradayMiddleware::Response)
10
6
  end
11
7
  end
@@ -1,3 +1,3 @@
1
1
  module Mrkt
2
- VERSION = '0.9.0'
2
+ VERSION = '1.0.1'.freeze
3
3
  end
@@ -1,5 +1,4 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
1
+ lib = File.expand_path('lib', __dir__)
3
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
3
  require 'mrkt/version'
5
4
 
@@ -16,19 +15,19 @@ Gem::Specification.new do |spec|
16
15
  spec.files = `git ls-files`.split($RS)
17
16
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
17
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
- spec.require_paths = %w(lib)
18
+ spec.require_paths = %w[lib]
20
19
 
21
- spec.required_ruby_version = '~> 2.0'
20
+ spec.required_ruby_version = '~> 2.5'
22
21
 
23
- spec.add_dependency 'faraday', '> 0.9.0', '< 0.14.0'
24
- spec.add_dependency 'faraday_middleware', '> 0.9.0', '< 0.13.0'
22
+ spec.add_dependency 'faraday', '~> 1.0'
23
+ spec.add_dependency 'faraday_middleware', '~> 1.0'
25
24
 
26
25
  spec.add_development_dependency 'bundler', '~> 1.3'
27
- spec.add_development_dependency 'rake', '~> 10.0'
26
+ spec.add_development_dependency 'gem-release', '~> 2.1'
27
+ spec.add_development_dependency 'pry-byebug', '~> 3.7'
28
+ spec.add_development_dependency 'rake', '~> 12.3'
28
29
  spec.add_development_dependency 'rspec', '~> 3.2'
29
- spec.add_development_dependency 'webmock', '~> 1.21.0'
30
- spec.add_development_dependency 'simplecov', '~> 0.14.1'
31
- spec.add_development_dependency 'pry-byebug', '~> 3.4.0'
32
- spec.add_development_dependency 'codeclimate-test-reporter', '~> 1.0.0'
33
- spec.add_development_dependency 'rubocop', '~> 0.45.0'
30
+ spec.add_development_dependency 'rubocop', '~> 0.87.1'
31
+ spec.add_development_dependency 'simplecov', '~> 0.17.1'
32
+ spec.add_development_dependency 'webmock', '~> 3.1'
34
33
  end
@@ -29,9 +29,49 @@ describe Mrkt::Authentication do
29
29
  expect(client.authenticated?).to be true
30
30
  end
31
31
 
32
+ context 'with optional partner_id client option' do
33
+ before { remove_request_stub(@authentication_request_stub) }
34
+
35
+ let(:partner_id) { SecureRandom.uuid }
36
+
37
+ let(:client_options) do
38
+ {
39
+ host: host,
40
+ client_id: client_id,
41
+ client_secret: client_secret,
42
+ partner_id: partner_id
43
+ }
44
+ end
45
+
46
+ let(:query) do
47
+ {
48
+ client_id: client_id,
49
+ client_secret: client_secret,
50
+ partner_id: partner_id,
51
+ grant_type: 'client_credentials'
52
+ }
53
+ end
54
+
55
+ subject(:client) { Mrkt::Client.new(client_options) }
56
+
57
+ before do
58
+ stub_request(:get, "https://#{host}/identity/oauth/token")
59
+ .with(query: query)
60
+ .to_return(json_stub(authentication_stub))
61
+ end
62
+
63
+ it 'should authenticate and then be authenticated?' do
64
+ expect(client.authenticated?).to_not be true
65
+ client.authenticate!
66
+ expect(client.authenticated?).to be true
67
+ end
68
+ end
69
+
32
70
  context 'when the token has expired and @retry_authentication = true' do
33
71
  before { remove_request_stub(@authentication_request_stub) }
34
72
 
73
+ let(:retry_count) { 3 }
74
+
35
75
  let(:expired_authentication_stub) do
36
76
  { access_token: SecureRandom.uuid, token_type: 'bearer', expires_in: 0, scope: 'RestClient' }
37
77
  end
@@ -40,7 +80,17 @@ describe Mrkt::Authentication do
40
80
  { access_token: SecureRandom.uuid, token_type: 'bearer', expires_in: 1234, scope: 'RestClient' }
41
81
  end
42
82
 
43
- subject(:client) { Mrkt::Client.new(host: host, client_id: client_id, client_secret: client_secret, retry_authentication: true) }
83
+ let(:client_options) do
84
+ {
85
+ host: host,
86
+ client_id: client_id,
87
+ client_secret: client_secret,
88
+ retry_authentication: true,
89
+ retry_authentication_count: retry_count
90
+ }
91
+ end
92
+
93
+ subject(:client) { Mrkt::Client.new(client_options) }
44
94
 
45
95
  before do
46
96
  stub_request(:get, "https://#{host}/identity/oauth/token")
@@ -55,12 +105,14 @@ describe Mrkt::Authentication do
55
105
  expect(client.authenticated?).to be true
56
106
  end
57
107
 
58
- it 'should stop retrying after @retry_authentication_count tries and then raise an error' do
59
- client = Mrkt::Client.new(host: host, client_id: client_id, client_secret: client_secret, retry_authentication: true, retry_authentication_count: 2)
108
+ context 'when retry_authentication_count is low' do
109
+ let(:retry_count) { 2 }
60
110
 
61
- expect(client.authenticated?).to_not be true
111
+ it 'should stop retrying after @retry_authentication_count tries and then raise an error' do
112
+ expect(client.authenticated?).to_not be true
62
113
 
63
- expect { client.authenticate! }.to raise_error(Mrkt::Errors::Error, 'Client not authenticated')
114
+ expect { client.authenticate! }.to raise_error(Mrkt::Errors::Error, 'Client not authenticated')
115
+ end
64
116
  end
65
117
  end
66
118
  end
@@ -110,7 +110,7 @@ describe Mrkt::CrudActivities do
110
110
 
111
111
  before do
112
112
  stub_request(:get, "https://#{host}/rest/v1/activities.json")
113
- .with(query: { nextPageToken: URI.encode(token) })
113
+ .with(query: { nextPageToken: token })
114
114
  .to_return(json_stub(response_stub))
115
115
  end
116
116
 
@@ -152,7 +152,7 @@ describe Mrkt::CrudActivities do
152
152
  before do
153
153
  stub_request(:get, "https://#{host}/rest/v1/activities.json")
154
154
  .with(query: {
155
- nextPageToken: URI.encode(token),
155
+ nextPageToken: token,
156
156
  activityTypeIds: activity_type_ids.join(',')
157
157
  })
158
158
  .to_return(json_stub(response_stub))
@@ -196,7 +196,7 @@ describe Mrkt::CrudActivities do
196
196
 
197
197
  before do
198
198
  stub_request(:get, "https://#{host}/rest/v1/activities.json")
199
- .with(query: { nextPageToken: URI.encode(token), leadIds: lead_ids.join(',') })
199
+ .with(query: { nextPageToken: token, leadIds: lead_ids.join(',') })
200
200
  .to_return(json_stub(response_stub))
201
201
  end
202
202
 
@@ -204,15 +204,15 @@ describe Mrkt::CrudActivities do
204
204
  end
205
205
 
206
206
  context 'specifying arrays values as empty strings' do
207
- let(:activity_type_ids) { "" }
208
- let(:lead_ids) { "" }
207
+ let(:activity_type_ids) { '' }
208
+ let(:lead_ids) { '' }
209
209
  subject do
210
210
  client.get_activities(token, activity_type_ids: activity_type_ids, lead_ids: lead_ids)
211
211
  end
212
212
 
213
213
  before do
214
214
  stub_request(:get, "https://#{host}/rest/v1/activities.json")
215
- .with(query: { nextPageToken: URI.encode(token) })
215
+ .with(query: { nextPageToken: token })
216
216
  .to_return(json_stub(response_stub))
217
217
  end
218
218
 
@@ -227,7 +227,7 @@ describe Mrkt::CrudActivities do
227
227
  before do
228
228
  stub_request(:get, "https://#{host}/rest/v1/activities.json")
229
229
  .with(query: {
230
- nextPageToken: URI.encode(token),
230
+ nextPageToken: token,
231
231
  activityTypeIds: activity_type_ids.join(','),
232
232
  leadIds: lead_ids.join(',')
233
233
  })
@@ -237,4 +237,43 @@ describe Mrkt::CrudActivities do
237
237
  it { is_expected.to eq(response_stub) }
238
238
  end
239
239
  end
240
+
241
+ describe '#get_deleted_leads' do
242
+ let(:token) { '4GAX7YNCIJKO2VAED5LH5PQIYPUM7WCVKTQWEDMP2L24AXZT54LA====' }
243
+ let(:response_stub) do
244
+ {
245
+ requestId: '8105#1650074c30c',
246
+ result: [
247
+ {
248
+ id: 12_751,
249
+ marketoGUID: '12751',
250
+ leadId: 277,
251
+ activityDate: '2018-08-03T14:58:53Z',
252
+ activityTypeId: 37,
253
+ campaignId: 5227,
254
+ primaryAttributeValueId: 277,
255
+ primaryAttributeValue: 'Delete Me',
256
+ attributes: [
257
+ {
258
+ name: 'Campaign',
259
+ value: 'Run Action Delete Lead 2018-08-03 04:58:50 pm'
260
+ }
261
+ ]
262
+ }
263
+ ],
264
+ success: true,
265
+ nextPageToken: 'XQH6SLHODNIM7CY6MKJ6GAOR3JYOQXIN3THAHKYZXSOYN4HOPR2Q====',
266
+ moreResult: false
267
+ }
268
+ end
269
+ subject { client.get_deleted_leads(token) }
270
+
271
+ before do
272
+ stub_request(:get, "https://#{host}/rest/v1/activities/deletedleads.json")
273
+ .with(query: { nextPageToken: token })
274
+ .to_return(json_stub(response_stub))
275
+ end
276
+
277
+ it { is_expected.to eq(response_stub) }
278
+ end
240
279
  end
@@ -0,0 +1,273 @@
1
+ describe Mrkt::CrudAssetFolders do
2
+ include_context 'initialized client'
3
+
4
+ let(:response_folder_result) do
5
+ {
6
+ name: 'Test Folder Name',
7
+ description: 'Optional folder description',
8
+ createdAt: '2019-03-15T23:31:00Z+0000',
9
+ updatedAt: '2019-03-15T23:31:00Z+0000',
10
+ url: 'https://app-devlocal1.marketo.com/#ML0A1ZN75',
11
+ folderId: {
12
+ id: 75,
13
+ type: 'Folder'
14
+ },
15
+ folderType: 'Zone',
16
+ parent: {
17
+ id: 5,
18
+ type: 'Folder'
19
+ },
20
+ path: '/Lead Database/Default/Test Folder Name',
21
+ isArchive: false,
22
+ isSystem: false,
23
+ accessZoneId: 1,
24
+ workspace: 'Default',
25
+ id: 75
26
+ }
27
+ end
28
+
29
+ describe '#create_folder' do
30
+ subject { client.create_folder(name, parent, description: description) }
31
+
32
+ let(:name) { 'Test Folder Name' }
33
+ let(:parent) do
34
+ { id: 5, type: 'Folder' }
35
+ end
36
+ let(:description) { 'Optional folder description' }
37
+ let(:response_stub) do
38
+ {
39
+ requestId: 'bf7d#16983b1c7e3',
40
+ result: [
41
+ response_folder_result
42
+ ],
43
+ success: true,
44
+ errors: [],
45
+ warnings: []
46
+ }
47
+ end
48
+
49
+ let(:json_parent) { JSON.generate(parent) }
50
+ let(:request_body) do
51
+ {
52
+ name: name,
53
+ parent: json_parent,
54
+ description: description
55
+ }
56
+ end
57
+
58
+ before do
59
+ stub_request(:post, "https://#{host}/rest/asset/v1/folders.json")
60
+ .with(body: request_body)
61
+ .to_return(json_stub(response_stub))
62
+ end
63
+
64
+ it { is_expected.to eq(response_stub) }
65
+ end
66
+
67
+ describe '#get_folder_by_id' do
68
+ subject { client.get_folder_by_id(id, type: type) }
69
+
70
+ let(:id) { 77 }
71
+
72
+ before do
73
+ stub_request(:get, "https://#{host}/rest/asset/v1/folder/#{id}.json?type=#{type}")
74
+ .to_return(json_stub(response_stub))
75
+ end
76
+
77
+ context 'when a folder with the given id exists' do
78
+ let(:type) { 'Folder' }
79
+ let(:response_stub) do
80
+ {
81
+ requestId: '12756#16983bd0ee5',
82
+ result: [
83
+ response_folder_result
84
+ ],
85
+ success: true,
86
+ errors: [],
87
+ warnings: []
88
+ }
89
+ end
90
+
91
+ it { is_expected.to eq(response_stub) }
92
+ end
93
+
94
+ context 'when a folder with the given id does not exist' do
95
+ let(:type) { 'Folder' }
96
+ let(:response_stub) do
97
+ {
98
+ requestId: '18087#16983c04cdf',
99
+ success: true,
100
+ errors: [],
101
+ warnings: [
102
+ 'No assets found for the given search criteria.'
103
+ ]
104
+ }
105
+ end
106
+
107
+ it { is_expected.to eq(response_stub) }
108
+ end
109
+
110
+ context 'when the given type is not acceptable' do
111
+ let(:type) { 'Unacceptable' }
112
+ let(:response_stub) do
113
+ {
114
+ requestId: '12776#16983c25b1d',
115
+ success: false,
116
+ warnings: [],
117
+ errors: [
118
+ {
119
+ code: '1001',
120
+ message: "Invalid value 'Unacceptable'. Required of type 'FolderVariantType'"
121
+ }
122
+ ]
123
+ }
124
+ end
125
+
126
+ it 'should raise an Error' do
127
+ expect { subject }.to raise_error(Mrkt::Errors::TypeMismatch)
128
+ end
129
+ end
130
+ end
131
+
132
+ describe '#get_folder_by_name' do
133
+ subject { client.get_folder_by_name(name, type: type, root: root, work_space: work_space) }
134
+
135
+ let(:name) { 'Test Folder Name' }
136
+ let(:type) { 'Folder' }
137
+ let(:root) do
138
+ {
139
+ id: 5,
140
+ type: 'Folder'
141
+ }
142
+ end
143
+ let(:work_space) { 'Default' }
144
+
145
+ let(:json_root) { JSON.generate(root) }
146
+ let(:request_query) { "name=#{name}&type=#{type}&root=#{json_root}&workSpace=#{work_space}" }
147
+
148
+ before do
149
+ stub_request(:get, "https://#{host}/rest/asset/v1/folder/byName.json?#{request_query}")
150
+ .to_return(json_stub(response_stub))
151
+ end
152
+
153
+ context 'when a folder with the given name exists' do
154
+ let(:response_stub) do
155
+ {
156
+ requestId: '541#16983d2f549',
157
+ result: [
158
+ response_folder_result
159
+ ],
160
+ success: true,
161
+ errors: [],
162
+ warnings: []
163
+ }
164
+ end
165
+
166
+ it { is_expected.to eq(response_stub) }
167
+ end
168
+
169
+ context 'when a folder with the given name does not exist' do
170
+ let(:response_stub) do
171
+ {
172
+ requestId: '105ad#16983d557c5',
173
+ success: true,
174
+ errors: [],
175
+ warnings: [
176
+ 'No assets found for the given search criteria.'
177
+ ]
178
+ }
179
+ end
180
+
181
+ it { is_expected.to eq(response_stub) }
182
+ end
183
+
184
+ context 'when the given work_space does not exist' do
185
+ let(:response_stub) do
186
+ {
187
+ requestId: '17af3#16983da0349',
188
+ success: false,
189
+ warnings: [],
190
+ errors: [
191
+ {
192
+ code: '611',
193
+ message: 'Unable to get folder'
194
+ }
195
+ ]
196
+ }
197
+ end
198
+
199
+ it 'should raise an Error' do
200
+ expect { subject }.to raise_error(Mrkt::Errors::System)
201
+ end
202
+ end
203
+
204
+ context 'when the given type is not acceptable' do
205
+ let(:response_stub) do
206
+ {
207
+ requestId: '2225#16983db0b71',
208
+ success: false,
209
+ warnings: [],
210
+ errors: [
211
+ {
212
+ code: '1003',
213
+ message: 'Invalid request. Please check and try again.'
214
+ }
215
+ ]
216
+ }
217
+ end
218
+
219
+ it 'should raise an Error' do
220
+ expect { subject }.to raise_error(Mrkt::Errors::UnspecifiedAction)
221
+ end
222
+ end
223
+ end
224
+
225
+ describe '#delete_folder' do
226
+ subject { client.delete_folder(id) }
227
+
228
+ let(:id) { 75 }
229
+
230
+ before do
231
+ stub_request(:post, "https://#{host}/rest/asset/v1/folder/#{id}/delete.json")
232
+ .to_return(json_stub(response_stub))
233
+ end
234
+
235
+ context 'when a folder with the given id exists' do
236
+ let(:response_stub) do
237
+ {
238
+ requestId: '1a1a#16983eaa800',
239
+ result: [
240
+ {
241
+ id: 75
242
+ }
243
+ ],
244
+ success: true,
245
+ errors: [],
246
+ warnings: []
247
+ }
248
+ end
249
+
250
+ it { is_expected.to eq(response_stub) }
251
+ end
252
+
253
+ context 'when a folder with the given id does not exist' do
254
+ let(:response_stub) do
255
+ {
256
+ requestId: '102ee#16983f320fb',
257
+ success: false,
258
+ warnings: [],
259
+ errors: [
260
+ {
261
+ code: '702',
262
+ message: '75 Folder not found'
263
+ }
264
+ ]
265
+ }
266
+ end
267
+
268
+ it 'should raise an Error' do
269
+ expect { subject }.to raise_error(Mrkt::Errors::RecordNotFound)
270
+ end
271
+ end
272
+ end
273
+ end