capsule_crm 1.2.0 → 1.3.0

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 (91) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -0
  3. data/lib/capsule_crm/address.rb +4 -3
  4. data/lib/capsule_crm/associations/belongs_to.rb +2 -1
  5. data/lib/capsule_crm/associations/belongs_to_association.rb +19 -2
  6. data/lib/capsule_crm/associations/belongs_to_finder.rb +46 -0
  7. data/lib/capsule_crm/associations/has_many_association.rb +23 -9
  8. data/lib/capsule_crm/associations/has_many_proxy.rb +38 -4
  9. data/lib/capsule_crm/case.rb +33 -236
  10. data/lib/capsule_crm/configuration.rb +1 -1
  11. data/lib/capsule_crm/connection.rb +3 -0
  12. data/lib/capsule_crm/contactable.rb +1 -1
  13. data/lib/capsule_crm/country.rb +7 -13
  14. data/lib/capsule_crm/currency.rb +7 -13
  15. data/lib/capsule_crm/custom_field.rb +14 -54
  16. data/lib/capsule_crm/custom_field_definition.rb +36 -0
  17. data/lib/capsule_crm/email.rb +4 -3
  18. data/lib/capsule_crm/gettable.rb +11 -0
  19. data/lib/capsule_crm/hash_helper.rb +5 -0
  20. data/lib/capsule_crm/history.rb +37 -252
  21. data/lib/capsule_crm/milestone.rb +9 -9
  22. data/lib/capsule_crm/normalizer.rb +85 -0
  23. data/lib/capsule_crm/opportunity.rb +30 -271
  24. data/lib/capsule_crm/organization.rb +19 -197
  25. data/lib/capsule_crm/party.rb +13 -26
  26. data/lib/capsule_crm/persistence/configuration.rb +25 -0
  27. data/lib/capsule_crm/persistence/deletable.rb +14 -0
  28. data/lib/capsule_crm/persistence/persistable.rb +76 -0
  29. data/lib/capsule_crm/persistence.rb +3 -0
  30. data/lib/capsule_crm/person.rb +19 -194
  31. data/lib/capsule_crm/phone.rb +4 -3
  32. data/lib/capsule_crm/querying/configuration.rb +21 -0
  33. data/lib/capsule_crm/querying/find_all.rb +16 -0
  34. data/lib/capsule_crm/querying/find_one.rb +14 -0
  35. data/lib/capsule_crm/querying/findable.rb +14 -0
  36. data/lib/capsule_crm/querying.rb +4 -0
  37. data/lib/capsule_crm/serializable.rb +38 -0
  38. data/lib/capsule_crm/serializer.rb +54 -7
  39. data/lib/capsule_crm/task.rb +16 -96
  40. data/lib/capsule_crm/track.rb +5 -10
  41. data/lib/capsule_crm/user.rb +3 -15
  42. data/lib/capsule_crm/version.rb +1 -1
  43. data/lib/capsule_crm/website.rb +4 -2
  44. data/lib/capsule_crm.rb +15 -5
  45. data/spec/fabricators/case_fabricator.rb +1 -0
  46. data/spec/fabricators/history_fabricator.rb +1 -0
  47. data/spec/fabricators/opportunity_fabricator.rb +1 -0
  48. data/spec/lib/capsule_crm/associations/belongs_to_finder_spec.rb +48 -0
  49. data/spec/lib/capsule_crm/associations/belongs_to_spec.rb +34 -0
  50. data/spec/lib/capsule_crm/associations/has_many_proxy_spec.rb +54 -14
  51. data/spec/lib/capsule_crm/associations/has_many_spec.rb +15 -2
  52. data/spec/lib/capsule_crm/case_spec.rb +20 -330
  53. data/spec/lib/capsule_crm/country_spec.rb +1 -16
  54. data/spec/lib/capsule_crm/currency_spec.rb +1 -18
  55. data/spec/lib/capsule_crm/custom_field_definition_spec.rb +59 -0
  56. data/spec/lib/capsule_crm/custom_field_spec.rb +2 -27
  57. data/spec/lib/capsule_crm/history_spec.rb +14 -389
  58. data/spec/lib/capsule_crm/milestone_spec.rb +1 -23
  59. data/spec/lib/capsule_crm/normalizer_spec.rb +11 -0
  60. data/spec/lib/capsule_crm/opportunity_spec.rb +22 -341
  61. data/spec/lib/capsule_crm/organization_spec.rb +39 -60
  62. data/spec/lib/capsule_crm/party_spec.rb +37 -59
  63. data/spec/lib/capsule_crm/person_spec.rb +49 -247
  64. data/spec/lib/capsule_crm/serializer_spec.rb +25 -4
  65. data/spec/lib/capsule_crm/task_spec.rb +21 -250
  66. data/spec/lib/capsule_crm/track_spec.rb +1 -15
  67. data/spec/lib/capsule_crm/user_spec.rb +1 -14
  68. data/spec/support/{countries.json → all_countries.json} +0 -0
  69. data/spec/support/{currencies.json → all_currencies.json} +0 -0
  70. data/spec/support/{milestones.json → all_milestones.json} +0 -0
  71. data/spec/support/{tracks.json → all_tracks.json} +0 -0
  72. data/spec/support/custom_field_definitions.json +19 -0
  73. data/spec/support/helpers.rb +3 -2
  74. data/spec/support/no_cases.json +5 -0
  75. data/spec/support/no_countries.json +5 -0
  76. data/spec/support/no_currencies.json +5 -0
  77. data/spec/support/no_milestones.json +5 -0
  78. data/spec/support/no_opportunities.json +5 -0
  79. data/spec/support/no_tasks.json +5 -0
  80. data/spec/support/no_tracks.json +5 -0
  81. data/spec/support/no_users.json +5 -0
  82. data/spec/support/shared_examples/deletable.rb +15 -0
  83. data/spec/support/shared_examples/find_all.rb +34 -0
  84. data/spec/support/shared_examples/find_one.rb +23 -0
  85. data/spec/support/shared_examples/persistable.rb +318 -0
  86. data/spec/support/single_person.json +16 -0
  87. metadata +60 -15
  88. data/lib/capsule_crm/attributes.rb +0 -11
  89. data/lib/capsule_crm/capsule_jsonable.rb +0 -13
  90. data/lib/capsule_crm/collection.rb +0 -9
  91. data/spec/support/single_user.json +0 -25
@@ -3,6 +3,21 @@ require 'spec_helper'
3
3
  describe CapsuleCRM::Case do
4
4
  before { configure }
5
5
 
6
+ it_behaves_like 'persistable', 'https://sample.capsulecrm.com/api/kase/1001', 1001 do
7
+ let(:attributes) { Fabricate.attributes_for(:case).merge(party: party) }
8
+ let(:party) { Fabricate.build(:person, id: Random.rand(1..10)) }
9
+ end
10
+
11
+ it_behaves_like 'deletable'
12
+
13
+ it_behaves_like 'listable', '/kase', 'cases', 1
14
+
15
+ it_behaves_like 'findable', '/api/kase/43', 43, 'case' do
16
+ let(:attributes) do
17
+ { name: 'Consulting' }
18
+ end
19
+ end
20
+
6
21
  before do
7
22
  stub_request(:get, /\/api\/users$/).
8
23
  to_return(body: File.read('spec/support/all_users.json'))
@@ -40,337 +55,12 @@ describe CapsuleCRM::Case do
40
55
  it { subject.first.detail.should eql('Go and get drunk') }
41
56
  end
42
57
 
43
- describe '.all' do
44
- before do
45
- stub_request(:get, 'https://1234:@company.capsulecrm.com/api/kase').
46
- to_return(body: File.read('spec/support/all_cases.json'))
47
- end
48
-
49
- subject { CapsuleCRM::Case.all }
50
-
51
- it { should be_a(Array) }
52
-
53
- it { subject.length.should eql(1) }
54
-
55
- it { subject.all? { |item| item.is_a?(CapsuleCRM::Case) }.should be_true }
56
- end
57
-
58
- describe '.find' do
59
- before do
60
- stub_request(:get, 'https://1234:@company.capsulecrm.com/api/kase/43').
61
- to_return(body: File.read('spec/support/case.json'))
62
- end
63
-
64
- subject { CapsuleCRM::Case.find(43) }
65
-
66
- it { should be_a(CapsuleCRM::Case) }
67
-
68
- it { subject.name.should eql('Consulting') }
69
- end
70
-
71
- describe '.create' do
72
- let(:request_uri) do
73
- 'https://1234:@company.capsulecrm.com/api/party/1/kase'
74
- end
75
-
76
- let(:party) { CapsuleCRM::Person.new(id: 1, first_name: 'Matt') }
77
-
78
- context 'when the case is valid' do
79
- before do
80
- stub_request(:post, request_uri).to_return(
81
- headers: { 'Location' => 'https://sample.capsulecrm.com/api/kase/59' }
82
- )
83
- end
84
-
85
- subject { CapsuleCRM::Case.create name: 'Test Case', party: party }
86
-
87
- it { should be_a(CapsuleCRM::Case) }
88
-
89
- it { subject.id.should eql(59) }
90
- end
91
-
92
- context 'when the case is invalid' do
93
- let(:kase) { CapsuleCRM::Case.create name: 'Test Case' }
94
-
95
- it { kase.errors.should_not be_blank }
96
- end
97
-
98
- context 'when the case has a track' do
99
- before do
100
- stub_request(:post, "#{request_uri}?trackId=#{track.id}").to_return(
101
- headers: { 'Location' => 'https://sample.capsulecrm.com/api/kase/59' }
102
- )
103
- end
104
-
105
- let(:track) { CapsuleCRM::Track.new(id: rand(10)) }
106
-
107
- subject do
108
- CapsuleCRM::Case.create(name: 'Test Case', party: party, track: track)
109
- end
110
-
111
- it { expect(subject).to be_a(CapsuleCRM::Case) }
112
-
113
- it { expect(subject).to be_persisted }
114
-
115
- it 'should add the trackId to the URI' do
116
- subject
117
- expect(WebMock).
118
- to have_requested(:post, "#{request_uri}?trackId=#{track.id}")
119
- end
120
- end
121
- end
122
-
123
- describe '.create!' do
124
- context 'when the case is valid' do
125
- before do
126
- stub_request(
127
- :post, 'https://1234:@company.capsulecrm.com/api/party/1/kase'
128
- ).to_return(
129
- headers: { 'Location' => 'https://sample.capsulecrm.com/api/kase/61' }
130
- )
131
- end
132
-
133
- let(:party) { CapsuleCRM::Person.new(id: 1, first_name: 'Matt') }
134
-
135
- subject { CapsuleCRM::Case.create! name: 'Test Case', party: party }
136
-
137
- it { should be_a(CapsuleCRM::Case) }
138
-
139
- it { subject.id.should eql(61) }
140
- end
141
-
142
- context 'when the case is invalid' do
143
- let(:kase) { CapsuleCRM::Case.create! name: 'Test Case' }
144
-
145
- it 'should raise an error' do
146
- expect { kase }.to raise_error(CapsuleCRM::Errors::RecordInvalid)
147
- end
148
- end
149
- end
150
-
151
- describe '#update_attributes' do
152
- context 'when the case is valid' do
153
- let(:party) { CapsuleCRM::Person.new(id: 10) }
154
-
155
- let(:kase) do
156
- CapsuleCRM::Case.new(id: 1, name: 'Test Case', party: party)
157
- end
158
-
159
- before do
160
- stub_request(
161
- :put, 'https://1234:@company.capsulecrm.com/api/kase/1'
162
- ).to_return(status: 200)
163
- kase.update_attributes name: 'changed name'
164
- end
165
-
166
- it { kase.name.should eql('changed name') }
167
-
168
- it { kase.id.should eql(1) }
169
- end
170
-
171
- context 'when the case is not valid' do
172
- let(:kase) { CapsuleCRM::Case.new(id: 2, name: 'Test Case') }
173
-
174
- before do
175
- kase.update_attributes name: 'changed name'
176
- end
177
-
178
- it { kase.errors.should_not be_blank }
179
-
180
- it { kase.name.should eql('changed name') }
181
- end
182
- end
183
-
184
- describe '#update_attributes!' do
185
- context 'when the case is valid' do
186
- let(:party) { CapsuleCRM::Person.new(id: 1, first_name: 'Matt') }
187
-
188
- let(:kase) do
189
- CapsuleCRM::Case.new(id: 1, name: 'Test Case', party: party)
190
- end
191
-
192
- before do
193
- stub_request(
194
- :put, 'https://1234:@company.capsulecrm.com/api/kase/1'
195
- ).to_return(status: 200)
196
- kase.update_attributes! name: 'changed name'
197
- end
198
-
199
- it { kase.name.should eql('changed name') }
200
-
201
- it { kase.id.should eql(1) }
202
- end
203
-
204
- context 'when the case is invalid' do
205
- let(:kase) { CapsuleCRM::Case.new(id: 1, name: 'Test Case') }
206
-
207
- subject { kase.update_attributes! name: 'changed name' }
208
-
209
- it do
210
- expect { subject }.to raise_error(CapsuleCRM::Errors::RecordInvalid)
211
- end
212
- end
213
- end
214
-
215
- describe '#save' do
216
- let(:party) { CapsuleCRM::Person.new(id: 1) }
217
-
218
- context 'when it is a new record' do
219
- context 'when it is valid' do
220
- let(:kase) { CapsuleCRM::Case.new(name: 'Test', party: party) }
221
-
222
- before do
223
- stub_request(
224
- :post, 'https://1234:@company.capsulecrm.com/api/party/1/kase'
225
- ).to_return(
226
- headers: { 'Location' => 'https://sample.capsulecrm.com/api/kase/2' }
227
- )
228
- kase.save
229
- end
230
-
231
- subject { kase }
232
-
233
- it { should be_persisted }
234
-
235
- it { kase.id.should eql(2) }
236
- end
237
-
238
- context 'when it is invalid' do
239
- let(:kase) { CapsuleCRM::Case.new(name: 'Test') }
240
-
241
- before { kase.save }
242
-
243
- it { kase.errors.should_not be_blank }
244
-
245
- it { kase.should_not be_persisted }
246
- end
247
- end
248
-
249
- context 'when it is an existing record' do
250
- let(:party) { CapsuleCRM::Person.new(id: 1) }
251
-
252
- context 'when it is valid' do
253
- let(:kase) { CapsuleCRM::Case.new(id: 2, name: 'Test', party: party) }
254
-
255
- before do
256
- stub_request(
257
- :put, 'https://1234:@company.capsulecrm.com/api/kase/2'
258
- ).to_return(status: 200)
259
- kase.name = 'changed name'
260
- kase.save
261
- end
262
-
263
- it { kase.should be_persisted }
264
-
265
- it { kase.name.should eql('changed name') }
266
- end
267
-
268
- context 'when it is invalid' do
269
- let(:kase) { CapsuleCRM::Case.new(id: 2, name: 'Test') }
270
-
271
- before { kase.save }
272
-
273
- it { kase.should be_persisted }
274
-
275
- it { kase.errors.should_not be_blank }
276
- end
277
- end
278
- end
279
-
280
- describe '#save!' do
281
- let(:party) { CapsuleCRM::Person.new(id: 1) }
282
-
283
- context 'when it is a new record' do
284
- context 'when it is valid' do
285
- let(:kase) { CapsuleCRM::Case.new(name: 'Test Case', party: party) }
286
-
287
- before do
288
- stub_request(:post, /^https.*\/api\/party\/1\/kase$/).
289
- to_return(headers: {
290
- 'Location' => 'https://sample.capsulecrm.com/api/kase/59'
291
- })
292
- kase.save!
293
- end
294
-
295
- it { kase.should be_persisted }
296
- end
297
-
298
- context 'when it is invalid' do
299
- let(:kase) { CapsuleCRM::Case.new(name: 'Test Case') }
300
-
301
- it do
302
- expect { kase.save! }.
303
- to raise_error(CapsuleCRM::Errors::RecordInvalid)
304
- end
305
- end
306
- end
307
-
308
- context 'when it is not a new record' do
309
- context 'when it is valid' do
310
- let(:kase) do
311
- CapsuleCRM::Case.new(id: 1, name: 'Test Case', party: party)
312
- end
313
-
314
- before do
315
- stub_request(:put, /^.*\/api\/kase\/1$/).to_return(status: 200)
316
- kase.save!
317
- end
318
-
319
- it { kase.should be_persisted }
320
- end
321
-
322
- context 'when it is invalid' do
323
- let(:kase) do
324
- CapsuleCRM::Case.new(id: 1, name: 'Test Case')
325
- end
326
-
327
- it do
328
- expect { kase.save! }.
329
- to raise_error(CapsuleCRM::Errors::RecordInvalid)
330
- end
331
- end
332
- end
333
- end
334
-
335
- describe '#destroy' do
336
- let(:party) { CapsuleCRM::Person.new(id: 2) }
337
-
338
- let(:kase) { CapsuleCRM::Case.new(id: 1, party: party, name: 'Test Case') }
339
-
340
- before do
341
- stub_request(:delete, /^.*\/api\/kase\/1$/).to_return(status: 200)
342
- kase.destroy
343
- end
344
-
345
- it { kase.should_not be_persisted }
346
- end
347
-
348
- describe '#new_record?' do
349
- describe 'when it is a new record' do
350
-
351
- subject { CapsuleCRM::Case.new }
352
-
353
- it { should be_new_record }
354
- end
355
-
356
- describe 'when it is not a new record' do
357
- subject { CapsuleCRM::Case.new(id: 1) }
358
-
359
- it { should_not be_new_record }
360
- end
361
- end
362
-
363
- describe '#persisted?' do
364
- context 'when it is persisted' do
365
- subject { CapsuleCRM::Case.new(id: 1) }
366
-
367
- it { should be_persisted }
368
- end
369
-
370
- context 'when it is not persisted' do
371
- subject { CapsuleCRM::Case.new }
58
+ describe '#to_capsule_json' do
59
+ let(:kase) { CapsuleCRM::Case.new }
60
+ subject { kase.to_capsule_json }
372
61
 
373
- it { should_not be_persisted }
62
+ it 'should have a root of "kase"' do
63
+ expect(subject.keys.first).to eql('kase')
374
64
  end
375
65
  end
376
66
  end
@@ -3,20 +3,5 @@ require 'spec_helper'
3
3
  describe CapsuleCRM::Country do
4
4
  before { configure }
5
5
 
6
- describe '.all' do
7
- before do
8
- stub_request(:get, /\/api\/countries$/).
9
- to_return(body: File.read('spec/support/countries.json'))
10
- end
11
-
12
- subject { CapsuleCRM::Country.all }
13
-
14
- it { should be_a(Array) }
15
-
16
- it { subject.count.should eql(2) }
17
-
18
- it do
19
- subject.all? { |item| item.is_a?(CapsuleCRM::Country) }.should be_true
20
- end
21
- end
6
+ it_behaves_like 'listable', '/countries', 'countries', 2
22
7
  end
@@ -3,22 +3,5 @@ require 'spec_helper'
3
3
  describe CapsuleCRM::Currency do
4
4
  before { configure }
5
5
 
6
- describe '.all' do
7
- before do
8
- stub_request(:get, /\/api\/currencies$/).
9
- to_return(body: File.read('spec/support/currencies.json'))
10
- end
11
-
12
- subject { CapsuleCRM::Currency.all }
13
-
14
- it { should be_a(Array) }
15
-
16
- it { subject.length.should eql(3) }
17
-
18
- it do
19
- subject.all? { |item| item.is_a?(CapsuleCRM::Currency) }.should be_true
20
- end
21
-
22
- it { subject.first.code.should eql('AUD') }
23
- end
6
+ it_behaves_like 'listable', '/currencies', 'currencies', 3
24
7
  end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ describe CapsuleCRM::CustomFieldDefinition do
4
+ before { configure }
5
+
6
+ describe '.for_parties' do
7
+ context 'when some definitions are returned' do
8
+ before do
9
+ stub_request(:get, /.*/).
10
+ to_return(body: File.read('spec/support/custom_field_definitions.json'))
11
+ end
12
+ subject { described_class.for_parties }
13
+
14
+ it 'should be an array' do
15
+ expect(subject).to be_a(Array)
16
+ end
17
+
18
+ it 'should contain 2 items' do
19
+ expect(subject.length).to eql(2)
20
+ end
21
+ end
22
+ end
23
+
24
+ describe '.for_opportunities' do
25
+ context 'when some definitions are returned' do
26
+ before do
27
+ stub_request(:get, /.*/).
28
+ to_return(body: File.read('spec/support/custom_field_definitions.json'))
29
+ end
30
+ subject { described_class.for_opportunities }
31
+
32
+ it 'should be an array' do
33
+ expect(subject).to be_a(Array)
34
+ end
35
+
36
+ it 'should contain 2 items' do
37
+ expect(subject.length).to eql(2)
38
+ end
39
+ end
40
+ end
41
+
42
+ describe '.for_cases' do
43
+ context 'when some definitions are returned' do
44
+ before do
45
+ stub_request(:get, /.*/).
46
+ to_return(body: File.read('spec/support/custom_field_definitions.json'))
47
+ end
48
+ subject { described_class.for_cases }
49
+
50
+ it 'should be an array' do
51
+ expect(subject).to be_a(Array)
52
+ end
53
+
54
+ it 'should contain 2 items' do
55
+ expect(subject.length).to eql(2)
56
+ end
57
+ end
58
+ end
59
+ end
@@ -7,7 +7,7 @@ describe CapsuleCRM::CustomField do
7
7
  stub_request(:get, /\/api\/users$/).
8
8
  to_return(body: File.read('spec/support/all_users.json'))
9
9
  stub_request(:get, /\/api\/opportunity\/milestones$/).
10
- to_return(body: File.read('spec/support/milestones.json'))
10
+ to_return(body: File.read('spec/support/all_milestones.json'))
11
11
  end
12
12
 
13
13
  describe 'validations' do
@@ -41,27 +41,6 @@ describe CapsuleCRM::CustomField do
41
41
  end
42
42
  end
43
43
 
44
- describe '.create' do
45
- context 'when it belongs to a party' do
46
- let(:organization) { Fabricate.build(:organization, id: 1) }
47
- let(:location) do
48
- 'https://sample.capsulecrm.com/api/party/#{organization.id}/customfields'
49
- end
50
- subject do
51
- CapsuleCRM::CustomField.create(
52
- id: 100, tag: 'The tag', label: 'A field', text: 'Some text',
53
- date: Date.today, boolean: true, party: organization
54
- )
55
- end
56
- before do
57
- stub_request(:post, /\/api\/party\/#{organization.id}\/customfields$/).
58
- to_return(headers: { 'Location' => location})
59
- end
60
-
61
- it { expect(subject.id).to eql(100) }
62
- end
63
- end
64
-
65
44
  describe '#to_capsule_json' do
66
45
  let(:custom_field) { Fabricate.build(:custom_field) }
67
46
  subject { custom_field.to_capsule_json }
@@ -71,11 +50,7 @@ describe CapsuleCRM::CustomField do
71
50
  end
72
51
 
73
52
  it 'should have a root element of "customField"' do
74
- expect(subject.keys.first).to eql('customFields')
75
- end
76
-
77
- it 'should have an element named "customField"' do
78
- expect(subject['customFields'].keys.first).to eql('customField')
53
+ expect(subject.keys.first).to eql('customField')
79
54
  end
80
55
  end
81
56
  end