amorail 0.3.4 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +19 -1
  3. data/README.md +7 -1
  4. data/Rakefile +7 -3
  5. data/amorail.gemspec +4 -3
  6. data/lib/amorail.rb +3 -0
  7. data/lib/amorail/client.rb +8 -4
  8. data/lib/amorail/config.rb +2 -0
  9. data/lib/amorail/entities/company.rb +2 -0
  10. data/lib/amorail/entities/contact.rb +3 -0
  11. data/lib/amorail/entities/contact_link.rb +2 -0
  12. data/lib/amorail/entities/elementable.rb +39 -0
  13. data/lib/amorail/entities/lead.rb +4 -1
  14. data/lib/amorail/entities/leadable.rb +3 -0
  15. data/lib/amorail/entities/note.rb +19 -0
  16. data/lib/amorail/entities/task.rb +11 -23
  17. data/lib/amorail/entities/webhook.rb +44 -0
  18. data/lib/amorail/entity.rb +17 -9
  19. data/lib/amorail/entity/finders.rb +19 -14
  20. data/lib/amorail/entity/params.rb +2 -0
  21. data/lib/amorail/entity/{persistance.rb → persistence.rb} +24 -0
  22. data/lib/amorail/exceptions.rb +2 -0
  23. data/lib/amorail/property.rb +8 -0
  24. data/lib/amorail/railtie.rb +4 -1
  25. data/lib/amorail/version.rb +3 -1
  26. data/lib/tasks/amorail.rake +2 -0
  27. data/spec/client_spec.rb +2 -0
  28. data/spec/company_spec.rb +2 -0
  29. data/spec/contact_link_spec.rb +2 -0
  30. data/spec/contact_spec.rb +17 -0
  31. data/spec/entity_spec.rb +2 -0
  32. data/spec/fixtures/{account_response.json → accounts/response_1.json} +5 -5
  33. data/spec/fixtures/{account2_response.json → accounts/response_2.json} +1 -1
  34. data/spec/fixtures/{contact_create.json → contacts/create.json} +1 -1
  35. data/spec/fixtures/{contact_find_query.json → contacts/find_many.json} +3 -5
  36. data/spec/fixtures/{contact_find.json → contacts/find_one.json} +5 -6
  37. data/spec/fixtures/contacts/links.json +16 -0
  38. data/spec/fixtures/{my_contact_find.json → contacts/my_contact_find.json} +2 -3
  39. data/spec/fixtures/contacts/update.json +13 -0
  40. data/spec/fixtures/leads/create.json +13 -0
  41. data/spec/fixtures/leads/find_many.json +73 -0
  42. data/spec/fixtures/leads/links.json +16 -0
  43. data/spec/fixtures/leads/update.json +13 -0
  44. data/spec/fixtures/leads/update_errors.json +12 -0
  45. data/spec/fixtures/webhooks/list.json +24 -0
  46. data/spec/fixtures/webhooks/subscribe.json +17 -0
  47. data/spec/fixtures/webhooks/unsubscribe.json +17 -0
  48. data/spec/helpers/webmock_helpers.rb +92 -13
  49. data/spec/lead_spec.rb +30 -0
  50. data/spec/my_contact_spec.rb +2 -0
  51. data/spec/note_spec.rb +28 -0
  52. data/spec/property_spec.rb +2 -0
  53. data/spec/spec_helper.rb +4 -2
  54. data/spec/support/elementable_example.rb +54 -0
  55. data/spec/support/entity_class_example.rb +2 -0
  56. data/spec/support/leadable_example.rb +2 -0
  57. data/spec/support/my_contact.rb +2 -0
  58. data/spec/support/my_entity.rb +2 -0
  59. data/spec/task_spec.rb +8 -28
  60. data/spec/webhook_spec.rb +61 -0
  61. metadata +60 -33
  62. data/.hound.yml +0 -12
  63. data/spec/fixtures/contact_update.json +0 -5
  64. data/spec/fixtures/contacts_links.json +0 -15
  65. data/spec/fixtures/leads.json +0 -69
  66. data/spec/fixtures/leads_links.json +0 -15
@@ -0,0 +1,24 @@
1
+ {
2
+ "response": {
3
+ "webhooks": [
4
+ {
5
+ "id": "1",
6
+ "url": "http://example.org",
7
+ "events": [
8
+ "add_contact"
9
+ ],
10
+ "disabled": false
11
+ },
12
+ {
13
+ "id": "2",
14
+ "url": "http://example.com",
15
+ "events": [
16
+ "add_contact",
17
+ "add_company"
18
+ ],
19
+ "disabled": true
20
+ }
21
+ ],
22
+ "server_time": 1539938502
23
+ }
24
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "response": {
3
+ "webhooks": {
4
+ "subscribe": [
5
+ {
6
+ "url": "http://example.org",
7
+ "result": true
8
+ },
9
+ {
10
+ "url": "http://example.com",
11
+ "result": true
12
+ }
13
+ ]
14
+ },
15
+ "server_time": 1539941636
16
+ }
17
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "response": {
3
+ "webhooks": {
4
+ "unsubscribe": [
5
+ {
6
+ "url": "http://example.org",
7
+ "result": true
8
+ },
9
+ {
10
+ "url": "http://example.com",
11
+ "result": true
12
+ }
13
+ ]
14
+ },
15
+ "server_time": 1539941911
16
+ }
17
+ }
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # rubocop: disable Metrics/ModuleLength
2
4
  module AmoWebMock
3
5
  def mock_api
@@ -9,7 +11,7 @@ module AmoWebMock
9
11
  account_info_stub(Amorail.config.api_endpoint)
10
12
  end
11
13
 
12
- def mock_custom_api(endpoint, usermail, api_key, properties = 'account2_response.json')
14
+ def mock_custom_api(endpoint, usermail, api_key, properties = 'response_2.json')
13
15
  authorize_stub(
14
16
  endpoint,
15
17
  usermail,
@@ -33,10 +35,10 @@ module AmoWebMock
33
35
  })
34
36
  end
35
37
 
36
- def account_info_stub(endpoint, properties = 'account_response.json')
38
+ def account_info_stub(endpoint, properties = 'response_1.json')
37
39
  stub_request(:get, endpoint + '/private/api/v2/json/accounts/current')
38
40
  .to_return(
39
- body: File.read("./spec/fixtures/#{properties}"),
41
+ body: File.read("./spec/fixtures/accounts/#{properties}"),
40
42
  headers: { 'Content-Type' => 'application/json' },
41
43
  status: 200
42
44
  )
@@ -61,7 +63,7 @@ module AmoWebMock
61
63
  def contact_create_stub(endpoint)
62
64
  stub_request(:post, endpoint + '/private/api/v2/json/contacts/set')
63
65
  .to_return(
64
- body: File.read('./spec/fixtures/contact_create.json'),
66
+ body: File.read('./spec/fixtures/contacts/create.json'),
65
67
  headers: { 'Content-Type' => 'application/json' },
66
68
  status: 200
67
69
  )
@@ -70,7 +72,7 @@ module AmoWebMock
70
72
  def contact_update_stub(endpoint)
71
73
  stub_request(:post, endpoint + '/private/api/v2/json/contacts/set')
72
74
  .to_return(
73
- body: File.read('./spec/fixtures/contact_update.json'),
75
+ body: File.read('./spec/fixtures/contacts/update.json'),
74
76
  headers: {
75
77
  'Content-Type' => 'application/json'
76
78
  },
@@ -84,7 +86,7 @@ module AmoWebMock
84
86
  :get,
85
87
  "#{endpoint}/private/api/v2/json/contacts/list?id=#{id}")
86
88
  .to_return(
87
- body: File.read('./spec/fixtures/contact_find.json'),
89
+ body: File.read('./spec/fixtures/contacts/find_one.json'),
88
90
  headers: { 'Content-Type' => 'application/json' },
89
91
  status: 200
90
92
  )
@@ -102,7 +104,7 @@ module AmoWebMock
102
104
  :get,
103
105
  "#{endpoint}/private/api/v2/json/contacts/list?id=#{id}")
104
106
  .to_return(
105
- body: File.read('./spec/fixtures/my_contact_find.json'),
107
+ body: File.read('./spec/fixtures/contacts/my_contact_find.json'),
106
108
  headers: { 'Content-Type' => 'application/json' },
107
109
  status: 200
108
110
  )
@@ -120,7 +122,7 @@ module AmoWebMock
120
122
  :get,
121
123
  "#{endpoint}/private/api/v2/json/contacts/list?query=#{query}")
122
124
  .to_return(
123
- body: File.read('./spec/fixtures/contact_find_query.json'),
125
+ body: File.read('./spec/fixtures/contacts/find_many.json'),
124
126
  headers: { 'Content-Type' => 'application/json' },
125
127
  status: 200
126
128
  )
@@ -138,7 +140,7 @@ module AmoWebMock
138
140
  :get,
139
141
  "#{endpoint}/private/api/v2/json/contacts/list?#{ids.to_query('id')}")
140
142
  .to_return(
141
- body: File.read('./spec/fixtures/contact_find_query.json'),
143
+ body: File.read('./spec/fixtures/contacts/find_many.json'),
142
144
  headers: { 'Content-Type' => 'application/json' },
143
145
  status: 200
144
146
  )
@@ -150,10 +152,30 @@ module AmoWebMock
150
152
  end
151
153
  end
152
154
 
155
+ def contacts_where_stub(endpoint, success = true, **params)
156
+ if success
157
+ stub_request(
158
+ :get,
159
+ "#{endpoint}/private/api/v2/json/contacts/list"
160
+ ).with(
161
+ query: params
162
+ ).to_return(
163
+ body: File.read('./spec/fixtures/contacts/find_many.json'),
164
+ headers: { 'Content-Type' => 'application/json' },
165
+ status: 200
166
+ )
167
+ else
168
+ stub_request(
169
+ :get,
170
+ "#{endpoint}/private/api/v2/json/contacts/list?query=#{query}")
171
+ .to_return(status: 204)
172
+ end
173
+ end
174
+
153
175
  def company_create_stub(endpoint)
154
176
  stub_request(:post, endpoint + '/private/api/v2/json/company/set')
155
177
  .to_return(
156
- body: File.read('./spec/fixtures/contact_create.json'),
178
+ body: File.read('./spec/fixtures/contacts/create.json'),
157
179
  headers: { 'Content-Type' => 'application/json' },
158
180
  status: 200
159
181
  )
@@ -165,7 +187,7 @@ module AmoWebMock
165
187
  :get,
166
188
  "#{endpoint}/private/api/v2/json/leads/list?#{ids.to_query('id')}")
167
189
  .to_return(
168
- body: File.read('./spec/fixtures/leads.json'),
190
+ body: File.read('./spec/fixtures/leads/find_many.json'),
169
191
  headers: { 'Content-Type' => 'application/json' },
170
192
  status: 200
171
193
  )
@@ -177,10 +199,37 @@ module AmoWebMock
177
199
  end
178
200
  end
179
201
 
202
+ def lead_create_stub(endpoint)
203
+ stub_request(:post, endpoint + '/private/api/v2/json/leads/set')
204
+ .to_return(
205
+ body: File.read('./spec/fixtures/leads/create.json'),
206
+ headers: { 'Content-Type' => 'application/json' },
207
+ status: 200
208
+ )
209
+ end
210
+
211
+ def lead_update_stub(endpoint, success = true)
212
+ fixture_file =
213
+ if success
214
+ './spec/fixtures/leads/update.json'
215
+ else
216
+ './spec/fixtures/leads/update_errors.json'
217
+ end
218
+
219
+ stub_request(:post, endpoint + '/private/api/v2/json/leads/set')
220
+ .to_return(
221
+ body: File.read(fixture_file),
222
+ headers: {
223
+ 'Content-Type' => 'application/json'
224
+ },
225
+ status: 200
226
+ )
227
+ end
228
+
180
229
  def contacts_links_stub(endpoint, ids)
181
230
  stub_request(:get, endpoint + "/private/api/v2/json/contacts/links?#{ids.to_query('contacts_link')}")
182
231
  .to_return(
183
- body: File.read('./spec/fixtures/contacts_links.json'),
232
+ body: File.read('./spec/fixtures/contacts/links.json'),
184
233
  headers: { 'Content-Type' => 'application/json' },
185
234
  status: 200
186
235
  )
@@ -190,7 +239,7 @@ module AmoWebMock
190
239
  if success
191
240
  stub_request(:get, endpoint + "/private/api/v2/json/contacts/links?#{ids.to_query('deals_link')}")
192
241
  .to_return(
193
- body: File.read('./spec/fixtures/leads_links.json'),
242
+ body: File.read('./spec/fixtures/leads/links.json'),
194
243
  headers: { 'Content-Type' => 'application/json' },
195
244
  status: 200
196
245
  )
@@ -199,4 +248,34 @@ module AmoWebMock
199
248
  .to_return(status: 204)
200
249
  end
201
250
  end
251
+
252
+ def webhooks_list_stub(endpoint, empty: false)
253
+ body = empty ? '' : File.read('./spec/fixtures/webhooks/list.json')
254
+ stub_request(:get, "#{endpoint}/private/api/v2/json/webhooks/list")
255
+ .to_return(
256
+ body: body,
257
+ headers: { 'Content-Type' => 'application/json' },
258
+ status: 200
259
+ )
260
+ end
261
+
262
+ def webhooks_subscribe_stub(endpoint, webhooks)
263
+ stub_request(:post, "#{endpoint}/private/api/v2/json/webhooks/subscribe")
264
+ .with(body: { request: { webhooks: { subscribe: webhooks } } }.to_json)
265
+ .to_return(
266
+ body: File.read('./spec/fixtures/webhooks/subscribe.json'),
267
+ headers: { 'Content-Type' => 'application/json' },
268
+ status: 200
269
+ )
270
+ end
271
+
272
+ def webhooks_unsubscribe_stub(endpoint, webhooks)
273
+ stub_request(:post, "#{endpoint}/private/api/v2/json/webhooks/unsubscribe")
274
+ .with(body: { request: { webhooks: { unsubscribe: webhooks } } }.to_json)
275
+ .to_return(
276
+ body: File.read('./spec/fixtures/webhooks/unsubscribe.json'),
277
+ headers: { 'Content-Type' => 'application/json' },
278
+ status: 200
279
+ )
280
+ end
202
281
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "spec_helper"
2
4
 
3
5
  describe Amorail::Lead do
@@ -18,6 +20,7 @@ describe Amorail::Lead do
18
20
  :name,
19
21
  :price,
20
22
  :status_id,
23
+ :pipeline_id,
21
24
  :tags
22
25
  )
23
26
  end
@@ -29,6 +32,7 @@ describe Amorail::Lead do
29
32
  name: 'Test',
30
33
  price: 100,
31
34
  status_id: 2,
35
+ pipeline_id: 17,
32
36
  tags: 'test lead'
33
37
  )
34
38
  end
@@ -39,6 +43,7 @@ describe Amorail::Lead do
39
43
  specify { is_expected.to include(name: 'Test') }
40
44
  specify { is_expected.to include(price: 100) }
41
45
  specify { is_expected.to include(status_id: 2) }
46
+ specify { is_expected.to include(pipeline_id: 17) }
42
47
  specify { is_expected.to include(tags: 'test lead') }
43
48
  end
44
49
 
@@ -70,4 +75,29 @@ describe Amorail::Lead do
70
75
  end
71
76
  end
72
77
  end
78
+
79
+ describe "#update" do
80
+ subject { lead.update }
81
+
82
+ let(:lead) { described_class.new(name: 'RSpec lead', status_id: 142) }
83
+
84
+ before do
85
+ lead_create_stub(Amorail.config.api_endpoint)
86
+ lead.save!
87
+ end
88
+
89
+ context 'with errors in response' do
90
+ before do
91
+ lead_update_stub(Amorail.config.api_endpoint, false)
92
+ lead.name = 'Updated name'
93
+ end
94
+
95
+ it { is_expected.to be_falsey }
96
+
97
+ specify do
98
+ subject
99
+ expect(lead.errors[:base]).to include('Last modified date is older than in database')
100
+ end
101
+ end
102
+ end
73
103
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "spec_helper"
2
4
 
3
5
  describe MyContact do
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Amorail::Note do
6
+ before { mock_api }
7
+
8
+ it_behaves_like 'elementable'
9
+
10
+ describe 'validations' do
11
+ it { is_expected.to validate_presence_of(:text) }
12
+ it { is_expected.to validate_presence_of(:note_type) }
13
+ it { is_expected.to validate_inclusion_of(:element_type).in_range(1..4) }
14
+ end
15
+
16
+ describe '.attributes' do
17
+ subject { described_class.attributes }
18
+
19
+ it_behaves_like 'entity_class'
20
+
21
+ specify do
22
+ is_expected.to include(
23
+ :text,
24
+ :note_type
25
+ )
26
+ end
27
+ end
28
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "spec_helper"
2
4
  require "webmock/rspec"
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
4
  $LOAD_PATH.unshift(File.dirname(__FILE__))
3
5
 
@@ -10,9 +12,9 @@ require 'helpers/webmock_helpers'
10
12
 
11
13
  # Cleanup Amorail env
12
14
  ENV.delete_if { |k, _| k =~ /amorail/i }
13
- ENV["AMORAIL_CONF"] = File.expand_path("../fixtures/amorail_test.yml", __FILE__)
15
+ ENV["AMORAIL_CONF"] = File.expand_path("fixtures/amorail_test.yml", __dir__)
14
16
 
15
- Dir[File.expand_path("../support/**/*.rb", __FILE__)].each { |f| require f }
17
+ Dir[File.expand_path("support/**/*.rb", __dir__)].each { |f| require f }
16
18
 
17
19
  RSpec.configure do |config|
18
20
  config.mock_with :rspec
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ shared_examples 'elementable' do
4
+ describe 'validations' do
5
+ it { is_expected.to validate_presence_of(:element_id) }
6
+ it { is_expected.to validate_presence_of(:element_type) }
7
+ end
8
+
9
+ describe '.attributes' do
10
+ subject { described_class.attributes }
11
+
12
+ specify do
13
+ is_expected.to include(
14
+ :element_type,
15
+ :element_id
16
+ )
17
+ end
18
+ end
19
+
20
+ describe '#params' do
21
+ subject { elementable.params }
22
+
23
+ let(:elementable) do
24
+ described_class.new(
25
+ element_id: 1,
26
+ element_type: 2
27
+ )
28
+ end
29
+
30
+ it { is_expected.to include(element_id: 1) }
31
+ it { is_expected.to include(element_type: 2) }
32
+ end
33
+
34
+ describe 'element type behaviour' do
35
+ let(:elementable) { described_class.new }
36
+
37
+ it 'set element_type on initialize' do
38
+ expect(described_class.new(lead: true).element_type).to eq 2
39
+ expect(described_class.new(lead: false).element_type).to be_nil
40
+ expect(described_class.new(contact: true).contact?).to be_truthy
41
+ end
42
+
43
+ it 'set element_type with bang method' do
44
+ elementable.contact!
45
+ expect(elementable.element_type).to eq 1
46
+
47
+ elementable.lead!
48
+ expect(elementable.element_type).to eq 2
49
+
50
+ elementable.company!
51
+ expect(elementable.element_type).to eq 3
52
+ end
53
+ end
54
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  shared_examples 'entity_class' do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  shared_examples 'leadable' do