mrkt 0.9.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
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