capsule_crm 0.0.3 → 0.0.4
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.
- checksums.yaml +4 -4
- data/README.md +9 -0
- data/capsule_crm.gemspec +2 -0
- data/lib/capsule_crm/opportunity.rb +310 -0
- data/lib/capsule_crm/version.rb +1 -1
- data/lib/capsule_crm.rb +1 -0
- data/spec/lib/capsule_crm/opportunity_spec.rb +317 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/support/all_opportunities.json +23 -0
- data/spec/support/opportunity.json +19 -0
- metadata +37 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b34d51c3ab9b172d2a66614669997440124ef98f
|
4
|
+
data.tar.gz: b013fae49cc19fa5dc83f9cabdde9b2ddfd4572f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8cf73a243482203d5408a5aa053b2564f90e2a645dbd051128a12fb3351996c99cc8e99b047ab4d6220795fe32ddac0dbbd7b7aa22b75bba08755ac17ac33c2f
|
7
|
+
data.tar.gz: 06388f7c87e09728859c69f6d6d0d91a0cd61a346985099e5ea89bcf5829b25536b1979530e7a95b65fd3c83f21093cd50e8ce6e2410135d67194056980f6da7
|
data/README.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
[](https://travis-ci.org/mattbeedle/capsule_crm)
|
3
|
+
|
4
|
+
[](http://badge.fury.io/rb/capsule_crm)
|
6
|
+
|
7
|
+
[](https://coveralls.io/r/mattbeedle/capsule_crm)
|
9
|
+
|
1
10
|
# CapsuleCRM
|
2
11
|
|
3
12
|
CapsuleCRM provides an ActiveModel compliant interface to the capsulecrm API
|
data/capsule_crm.gemspec
CHANGED
@@ -23,10 +23,12 @@ Gem::Specification.new do |gem|
|
|
23
23
|
gem.add_runtime_dependency('faraday_middleware')
|
24
24
|
gem.add_runtime_dependency('virtus')
|
25
25
|
|
26
|
+
gem.add_development_dependency('coveralls')
|
26
27
|
gem.add_development_dependency('cucumber')
|
27
28
|
gem.add_development_dependency('guard')
|
28
29
|
gem.add_development_dependency('guard-rspec')
|
29
30
|
gem.add_development_dependency('rb-fsevent')
|
30
31
|
gem.add_development_dependency('rspec')
|
32
|
+
gem.add_development_dependency('shoulda-matchers')
|
31
33
|
gem.add_development_dependency('webmock')
|
32
34
|
end
|
@@ -0,0 +1,310 @@
|
|
1
|
+
module CapsuleCRM
|
2
|
+
class Opportunity
|
3
|
+
include Virtus
|
4
|
+
|
5
|
+
extend ActiveModel::Naming
|
6
|
+
include ActiveModel::Conversion
|
7
|
+
include ActiveModel::Validations
|
8
|
+
|
9
|
+
attribute :id, Integer
|
10
|
+
attribute :name
|
11
|
+
attribute :description
|
12
|
+
attribute :currency
|
13
|
+
attribute :value, Float
|
14
|
+
attribute :duration_basis
|
15
|
+
attribute :duration, Integer
|
16
|
+
attribute :party_id, Integer
|
17
|
+
attribute :milestone_id, Integer
|
18
|
+
attribute :expected_close_date, DateTime
|
19
|
+
attribute :actual_close_date, DateTime
|
20
|
+
attribute :probability, Float
|
21
|
+
|
22
|
+
attr_accessor :milestone, :owner
|
23
|
+
|
24
|
+
validates :name, presence: true
|
25
|
+
validates :milestone_id, presence: { unless: :milestone }
|
26
|
+
validates :milestone, presence: { unless: :milestone_id }
|
27
|
+
|
28
|
+
# Public: Set the attributes of a opportunity
|
29
|
+
#
|
30
|
+
# attributes - The Hash of attributes (default: {}):
|
31
|
+
# :name - The String opportunity name
|
32
|
+
# :description - The String opportunity description
|
33
|
+
# :currency - The String currency code
|
34
|
+
# :value - The Float opportunity (financial) value
|
35
|
+
# :duration_basis - The String duration basis
|
36
|
+
# :duration - The Integer duration (for opportunities
|
37
|
+
# with a repeating (not FIXED) duratin basis
|
38
|
+
# :party_id - The Integer party id
|
39
|
+
# :milestone_id - The Integer milestone id
|
40
|
+
# :expected_close_date - The DateTime when the opportunity
|
41
|
+
# is expected to be closed
|
42
|
+
# :actual_close_date - The DateTime when the opportunity
|
43
|
+
# was actually closed
|
44
|
+
# :probability - The Float probability that this
|
45
|
+
# opportunity will be won
|
46
|
+
#
|
47
|
+
# Examples
|
48
|
+
#
|
49
|
+
# CapsuleCRM::Opportunity.new
|
50
|
+
#
|
51
|
+
# Returns a CapsuleCRM::Opportunity
|
52
|
+
def attributes=(attributes)
|
53
|
+
CapsuleCRM::HashHelper.underscore_keys!(attributes)
|
54
|
+
super(attributes)
|
55
|
+
self
|
56
|
+
end
|
57
|
+
|
58
|
+
# Public: Get all opportunities from Capsule. The list can be restricted
|
59
|
+
# and/or paginated with various query parameters sent through the options
|
60
|
+
# hash.
|
61
|
+
#
|
62
|
+
# options - The Hash of allowed query parameters for Capsule (default: {}):
|
63
|
+
# :milestone - The String milestone name
|
64
|
+
# :lastmodified - The Date when the opportunity was last modified
|
65
|
+
# :tag - The String tag to search for
|
66
|
+
# :start - The Integer first record to be returned in pagination.
|
67
|
+
# The results start with an index of 1
|
68
|
+
# :limit - The Integer maximum number of matching records to be
|
69
|
+
# returned
|
70
|
+
#
|
71
|
+
# Examples
|
72
|
+
#
|
73
|
+
# CapsuleCRM::Opportunity.all
|
74
|
+
#
|
75
|
+
# CapsuleCRM::Opportunity.all(start: 10, limit: 20)
|
76
|
+
#
|
77
|
+
# Returns a ResultsProxy of organisations
|
78
|
+
def self.all(options = {})
|
79
|
+
init_collection(
|
80
|
+
CapsuleCRM::Connection.
|
81
|
+
get('/api/opportunity', options)['opportunities']['opportunity']
|
82
|
+
)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Public: Find an opportunity by id
|
86
|
+
#
|
87
|
+
# id - The Integer ID
|
88
|
+
#
|
89
|
+
# Examples
|
90
|
+
#
|
91
|
+
# CapsuleCRM::Opportunity.find(id)
|
92
|
+
#
|
93
|
+
# Returns a CapsuleCRM::Opportunity
|
94
|
+
def self.find(id)
|
95
|
+
new CapsuleCRM::Connection.get("/api/opportunity/#{id}")['opportunity']
|
96
|
+
end
|
97
|
+
|
98
|
+
# Public: Create a new opportunity in capsulecrm
|
99
|
+
#
|
100
|
+
# attributes - The Hash of opportunity attributes (default: {}):
|
101
|
+
# :name - The String opportunity name
|
102
|
+
# :description - The String opportunity description
|
103
|
+
# :currency - The String currency code
|
104
|
+
# :value - The Float opportunity (financial) value
|
105
|
+
# :duration_basis - The String duration basis
|
106
|
+
# :duration - The Integer duration (for opportunities
|
107
|
+
# with a repeating (not FIXED) duratin basis
|
108
|
+
# :party_id - The Integer party id
|
109
|
+
# :milestone_id - The Integer milestone id
|
110
|
+
# :expected_close_date - The DateTime when the opportunity
|
111
|
+
# is expected to be closed
|
112
|
+
# :actual_close_date - The DateTime when the opportunity
|
113
|
+
# was actually closed
|
114
|
+
# :probability - The Float probability that this
|
115
|
+
# opportunity will be won
|
116
|
+
#
|
117
|
+
# Examples
|
118
|
+
#
|
119
|
+
# CapsuleCRM::opportunity.create(name: 'Test', milestone_id: 1)
|
120
|
+
#
|
121
|
+
# Returns a CapsuleCRM::opportunity
|
122
|
+
def self.create(attributes = {})
|
123
|
+
new(attributes).tap(&:save)
|
124
|
+
end
|
125
|
+
|
126
|
+
# Public: Create a new opportunity in capsulecrm and raise a
|
127
|
+
# CapsuleCRM::Errors::InvalidRecord error if not possible
|
128
|
+
#
|
129
|
+
# attributes - The Hash of opportunity attributes (default: {}):
|
130
|
+
# :name - The String opportunity name
|
131
|
+
# :description - The String opportunity description
|
132
|
+
# :currency - The String currency code
|
133
|
+
# :value - The Float opportunity (financial) value
|
134
|
+
# :duration_basis - The String duration basis
|
135
|
+
# :duration - The Integer duration (for opportunities
|
136
|
+
# with a repeating (not FIXED) duratin basis
|
137
|
+
# :party_id - The Integer party id
|
138
|
+
# :milestone_id - The Integer milestone id
|
139
|
+
# :expected_close_date - The DateTime when the opportunity
|
140
|
+
# is expected to be closed
|
141
|
+
# :actual_close_date - The DateTime when the opportunity
|
142
|
+
# was actually closed
|
143
|
+
# :probability - The Float probability that this
|
144
|
+
# opportunity will be won
|
145
|
+
#
|
146
|
+
# Examples
|
147
|
+
#
|
148
|
+
# CapsuleCRM::opportunity.create!(name: 'Test', milestone_id: 1)
|
149
|
+
#
|
150
|
+
# Returns a CapsuleCRM
|
151
|
+
def self.create!(attributes = {})
|
152
|
+
new(attributes).tap(&:save!)
|
153
|
+
end
|
154
|
+
|
155
|
+
# Public: If the opportunity already exists in capsule then update them,
|
156
|
+
# otherwise create a new opportunity
|
157
|
+
#
|
158
|
+
# Examples
|
159
|
+
#
|
160
|
+
# opportunity = CapsuleCRM::Opportunity.new(name: 'Test', milestone_id: 1)
|
161
|
+
# opportunity.save
|
162
|
+
#
|
163
|
+
# opportunity = CapsuleCRM::Opportunity.find(1)
|
164
|
+
# opportunity.name = 'Another Test'
|
165
|
+
# opportunity.save
|
166
|
+
#
|
167
|
+
# Returns a CapsuleCRM::opportunity
|
168
|
+
def save
|
169
|
+
if valid?
|
170
|
+
new_record? ? create_record : update_record
|
171
|
+
else
|
172
|
+
false
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
# Public: If the opportunity already exists in capsule then update them,
|
177
|
+
# otherwise create a new opportunity. If the opportunity is not valid then a
|
178
|
+
# CapsuleCRM::Errors::RecordInvalid exception is raised
|
179
|
+
#
|
180
|
+
# Examples
|
181
|
+
#
|
182
|
+
# opportunity = CapsuleCRM::Opportunity.new(name: 'Test, milestone_id: 1)
|
183
|
+
# opportunity.save
|
184
|
+
#
|
185
|
+
# opportunity = CapsuleCRM::Opportunity.find(1)
|
186
|
+
# opportunity.name = 'Another test'
|
187
|
+
# opportunity.save
|
188
|
+
#
|
189
|
+
# Returns a CapsuleCRM::opportunity
|
190
|
+
def save!
|
191
|
+
if valid?
|
192
|
+
new_record? ? create_record : update_record
|
193
|
+
else
|
194
|
+
raise CapsuleCRM::Errors::RecordInvalid.new(self)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
# Public: Determine whether this CapsuleCRM::opportunity is a new record or not
|
199
|
+
#
|
200
|
+
# Returns a Boolean
|
201
|
+
def new_record?
|
202
|
+
!id
|
203
|
+
end
|
204
|
+
|
205
|
+
# Public: Determine whether or not this CapsuleCRM::opportunity has already been
|
206
|
+
# persisted to capsulecrm
|
207
|
+
#
|
208
|
+
# Returns a Boolean
|
209
|
+
def persisted?
|
210
|
+
!new_record?
|
211
|
+
end
|
212
|
+
|
213
|
+
# Public: Update the opportunity in capsule
|
214
|
+
#
|
215
|
+
# attributes - The Hash of opportunity attributes (default: {}):
|
216
|
+
# :name - The String opportunity name
|
217
|
+
# :description - The String opportunity description
|
218
|
+
# :currency - The String currency code
|
219
|
+
# :value - The Float opportunity (financial) value
|
220
|
+
# :duration_basis - The String duration basis
|
221
|
+
# :duration - The Integer duration (for opportunities
|
222
|
+
# with a repeating (not FIXED) duratin basis
|
223
|
+
# :party_id - The Integer party id
|
224
|
+
# :milestone_id - The Integer milestone id
|
225
|
+
# :expected_close_date - The DateTime when the opportunity
|
226
|
+
# is expected to be closed
|
227
|
+
# :actual_close_date - The DateTime when the opportunity
|
228
|
+
# was actually closed
|
229
|
+
# :probability - The Float probability that this
|
230
|
+
# opportunity will be won
|
231
|
+
# Examples
|
232
|
+
#
|
233
|
+
# opportunity = CapsuleCRM::Opportunity.find(1)
|
234
|
+
# opportunity.update_attributes name: 'A New Name'
|
235
|
+
#
|
236
|
+
# Returns a CapsuleCRM::opportunity
|
237
|
+
def update_attributes(attributes = {})
|
238
|
+
self.attributes = attributes
|
239
|
+
save
|
240
|
+
end
|
241
|
+
|
242
|
+
# Public: Update the opportunity in capsule. If the person is not valid then a
|
243
|
+
# CapsuleCRM::Errors::RecordInvalid exception will be raised
|
244
|
+
#
|
245
|
+
# attributes - The Hash of opportunity attributes (default: {}):
|
246
|
+
# :name - The String opportunity name
|
247
|
+
# :description - The String opportunity description
|
248
|
+
# :currency - The String currency code
|
249
|
+
# :value - The Float opportunity (financial) value
|
250
|
+
# :duration_basis - The String duration basis
|
251
|
+
# :duration - The Integer duration (for opportunities
|
252
|
+
# with a repeating (not FIXED) duratin basis
|
253
|
+
# :party_id - The Integer party id
|
254
|
+
# :milestone_id - The Integer milestone id
|
255
|
+
# :expected_close_date - The DateTime when the opportunity
|
256
|
+
# is expected to be closed
|
257
|
+
# :actual_close_date - The DateTime when the opportunity
|
258
|
+
# was actually closed
|
259
|
+
# :probability - The Float probability that this
|
260
|
+
# opportunity will be won
|
261
|
+
#
|
262
|
+
# Examples
|
263
|
+
#
|
264
|
+
# opportunity = CapsuleCRM::Opportunity.find(1)
|
265
|
+
# opportunity.update_attributes! name: 'A New Name'
|
266
|
+
# => CapsuleCRM::Opportunity
|
267
|
+
#
|
268
|
+
# opportunity.update_attributes! name: nil
|
269
|
+
# => CapsuleCRM::Errors::RecordInvalid
|
270
|
+
#
|
271
|
+
# Returns a CapsuleCRM::opportunity
|
272
|
+
def update_attributes!(attributes = {})
|
273
|
+
self.attributes = attributes
|
274
|
+
save!
|
275
|
+
end
|
276
|
+
|
277
|
+
# Public: Build a hash of attributes and camelize the keys for capsule
|
278
|
+
#
|
279
|
+
# Examples
|
280
|
+
#
|
281
|
+
# opportunity.to_capsule_json
|
282
|
+
#
|
283
|
+
# Returns a Hash
|
284
|
+
def to_capsule_json
|
285
|
+
{
|
286
|
+
opportunity: CapsuleCRM::HashHelper.camelize_keys(
|
287
|
+
attributes.dup.delete_if { |key, value| value.blank? }
|
288
|
+
)
|
289
|
+
}.stringify_keys
|
290
|
+
end
|
291
|
+
|
292
|
+
private
|
293
|
+
|
294
|
+
def create_record
|
295
|
+
self.attributes = CapsuleCRM::Connection.post(
|
296
|
+
'/api/opportunity', to_capsule_json
|
297
|
+
)
|
298
|
+
self
|
299
|
+
end
|
300
|
+
|
301
|
+
def update_record
|
302
|
+
CapsuleCRM::Connection.put("/api/opportunity/#{id}", attributes)
|
303
|
+
self
|
304
|
+
end
|
305
|
+
|
306
|
+
def self.init_collection(collection)
|
307
|
+
CapsuleCRM::ResultsProxy.new(collection.map { |item| new item })
|
308
|
+
end
|
309
|
+
end
|
310
|
+
end
|
data/lib/capsule_crm/version.rb
CHANGED
data/lib/capsule_crm.rb
CHANGED
@@ -14,6 +14,7 @@ require 'capsule_crm/errors/record_invalid'
|
|
14
14
|
require 'capsule_crm/contacts'
|
15
15
|
require 'capsule_crm/contactable'
|
16
16
|
require 'capsule_crm/configuration'
|
17
|
+
require 'capsule_crm/opportunity'
|
17
18
|
require 'capsule_crm/organization'
|
18
19
|
require 'capsule_crm/person'
|
19
20
|
require 'capsule_crm/version'
|
@@ -0,0 +1,317 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CapsuleCRM::Opportunity do
|
4
|
+
before { configure }
|
5
|
+
|
6
|
+
it { should validate_presence_of(:name) }
|
7
|
+
|
8
|
+
it { should validate_presence_of(:milestone_id) }
|
9
|
+
|
10
|
+
it { should validate_presence_of(:milestone) }
|
11
|
+
|
12
|
+
context 'when milestone_id is set' do
|
13
|
+
subject { CapsuleCRM::Opportunity.new(milestone_id: 1) }
|
14
|
+
|
15
|
+
it { should_not validate_presence_of(:milestone) }
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'when milestone is set' do
|
19
|
+
subject { CapsuleCRM::Opportunity.new(milestone: 'a') }
|
20
|
+
|
21
|
+
it { should_not validate_presence_of(:milestone_id) }
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '.all' do
|
25
|
+
before do
|
26
|
+
stub_request(:get, /\/api\/opportunity$/).
|
27
|
+
to_return(body: File.read('spec/support/all_opportunities.json'))
|
28
|
+
end
|
29
|
+
|
30
|
+
subject { CapsuleCRM::Opportunity.all }
|
31
|
+
|
32
|
+
it { should be_a(Array) }
|
33
|
+
|
34
|
+
it { subject.length.should eql(1) }
|
35
|
+
|
36
|
+
it 'should only contain people' do
|
37
|
+
subject.all? { |item| item.is_a?(CapsuleCRM::Opportunity) }.should be_true
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '.find' do
|
42
|
+
before do
|
43
|
+
stub_request(:get, /.*/).
|
44
|
+
to_return(body: File.read('spec/support/opportunity.json'))
|
45
|
+
end
|
46
|
+
|
47
|
+
subject { CapsuleCRM::Opportunity.find(1) }
|
48
|
+
|
49
|
+
it { should be_a(CapsuleCRM::Opportunity) }
|
50
|
+
|
51
|
+
it { subject.value.should eql(500.0) }
|
52
|
+
|
53
|
+
it { subject.id.should eql(43) }
|
54
|
+
|
55
|
+
it { subject.duration_basis.should eql('DAY') }
|
56
|
+
|
57
|
+
it { subject.milestone_id.should eql(2) }
|
58
|
+
|
59
|
+
it { subject.duration.should eql(10) }
|
60
|
+
|
61
|
+
it { subject.currency.should eql('GBP') }
|
62
|
+
|
63
|
+
it do
|
64
|
+
subject.description.should eql('Scope and design web site shopping cart')
|
65
|
+
end
|
66
|
+
|
67
|
+
it { subject.name.should eql('Consulting') }
|
68
|
+
|
69
|
+
it { subject.owner.should eql('a.user') }
|
70
|
+
|
71
|
+
it { subject.milestone.should eql('Bid') }
|
72
|
+
|
73
|
+
it { subject.probability.should eql(50.0) }
|
74
|
+
|
75
|
+
it do
|
76
|
+
subject.expected_close_date.should eql(Date.parse('2012-09-30T00:00:00Z'))
|
77
|
+
end
|
78
|
+
|
79
|
+
it { subject.party_id.should eql(2) }
|
80
|
+
end
|
81
|
+
|
82
|
+
describe '#attributes=' do
|
83
|
+
let(:opportunity) { CapsuleCRM::Opportunity.new }
|
84
|
+
|
85
|
+
before do
|
86
|
+
opportunity.attributes = { partyId: '1', milestoneId: '3' }
|
87
|
+
end
|
88
|
+
|
89
|
+
it { opportunity.party_id.should eql(1) }
|
90
|
+
|
91
|
+
it { opportunity.milestone_id.should eql(3) }
|
92
|
+
end
|
93
|
+
|
94
|
+
describe '.create' do
|
95
|
+
context 'when the opportunity is valid' do
|
96
|
+
before do
|
97
|
+
stub_request(:post, /.*/).to_return(headers: {
|
98
|
+
'Location' => 'https://sample.capsulecrm.com/api/opportunity/59'
|
99
|
+
})
|
100
|
+
end
|
101
|
+
|
102
|
+
subject do
|
103
|
+
CapsuleCRM::Opportunity.create(
|
104
|
+
name: 'Test Opportunity', milestone_id: 1
|
105
|
+
)
|
106
|
+
end
|
107
|
+
|
108
|
+
it { should be_a(CapsuleCRM::Opportunity) }
|
109
|
+
|
110
|
+
it { should be_persisted }
|
111
|
+
|
112
|
+
it { subject.id.should eql(59) }
|
113
|
+
end
|
114
|
+
|
115
|
+
context 'when the opportunity is not valid' do
|
116
|
+
subject { CapsuleCRM::Opportunity.create }
|
117
|
+
|
118
|
+
it { subject.errors.should_not be_blank }
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
describe '.create!' do
|
123
|
+
context 'when the opportunity is valid' do
|
124
|
+
before do
|
125
|
+
stub_request(:post, /.*/).to_return(headers: {
|
126
|
+
'Location' => 'https://sample.capsulecrm.com/api/opportunity/71'
|
127
|
+
})
|
128
|
+
end
|
129
|
+
|
130
|
+
subject do
|
131
|
+
CapsuleCRM::Opportunity.create(
|
132
|
+
name: 'Test Opportunity', milestone_id: 1
|
133
|
+
)
|
134
|
+
end
|
135
|
+
|
136
|
+
it { should be_a(CapsuleCRM::Opportunity) }
|
137
|
+
|
138
|
+
it { should be_persisted }
|
139
|
+
|
140
|
+
it { subject.id.should eql(71) }
|
141
|
+
end
|
142
|
+
|
143
|
+
context 'when the opportunity is not valid' do
|
144
|
+
it do
|
145
|
+
expect { CapsuleCRM::Opportunity.create! }.
|
146
|
+
to raise_error(CapsuleCRM::Errors::RecordInvalid)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
describe '#update_attributes' do
|
152
|
+
context 'when the opportunity is valid' do
|
153
|
+
before do
|
154
|
+
stub_request(:put, /.*/).to_return(status: 200)
|
155
|
+
end
|
156
|
+
|
157
|
+
let(:opportunity) { CapsuleCRM::Opportunity.new(id: 1) }
|
158
|
+
|
159
|
+
before { opportunity.update_attributes name: 'renamed' }
|
160
|
+
|
161
|
+
it { opportunity.name.should eql('renamed') }
|
162
|
+
|
163
|
+
it { opportunity.id.should eql(1) }
|
164
|
+
end
|
165
|
+
|
166
|
+
context 'when the opportunity is not valid' do
|
167
|
+
let(:opportunity) { CapsuleCRM::Opportunity.new(id: 1) }
|
168
|
+
|
169
|
+
before { opportunity.update_attributes }
|
170
|
+
|
171
|
+
it { opportunity.should_not be_valid }
|
172
|
+
|
173
|
+
it { opportunity.errors.should_not be_blank }
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
describe '#update_attributes!' do
|
178
|
+
|
179
|
+
let(:opportunity) { CapsuleCRM::Opportunity.new(id: 1) }
|
180
|
+
|
181
|
+
context 'when the opportunity is valid' do
|
182
|
+
before do
|
183
|
+
stub_request(:put, /.*/).to_return(status: 200)
|
184
|
+
end
|
185
|
+
|
186
|
+
before { opportunity.update_attributes name: 'A New Name' }
|
187
|
+
|
188
|
+
it { opportunity.name.should eql('A New Name') }
|
189
|
+
|
190
|
+
it { opportunity.id.should eql(1) }
|
191
|
+
end
|
192
|
+
|
193
|
+
context 'when the opportunity is not valid' do
|
194
|
+
it do
|
195
|
+
expect { opportunity.update_attributes! }.
|
196
|
+
to raise_error(CapsuleCRM::Errors::RecordInvalid)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
describe '#save' do
|
202
|
+
context 'when the opportunity is a new record' do
|
203
|
+
before do
|
204
|
+
stub_request(:post, /.*/).to_return(headers: {
|
205
|
+
'Location' => 'https://sample.capsulecrm.com/api/party/100'
|
206
|
+
}, status: 200)
|
207
|
+
end
|
208
|
+
|
209
|
+
let(:opportunity) do
|
210
|
+
CapsuleCRM::Opportunity.new(name: 'Test', milestone_id: 1)
|
211
|
+
end
|
212
|
+
|
213
|
+
before { opportunity.save }
|
214
|
+
|
215
|
+
it { opportunity.name.should eql('Test') }
|
216
|
+
|
217
|
+
it { opportunity.milestone_id.should eql(1) }
|
218
|
+
|
219
|
+
it { opportunity.should be_persisted }
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
describe '#save!' do
|
224
|
+
context 'when the opportunity is a new record' do
|
225
|
+
context 'when the opportunity is valid' do
|
226
|
+
before do
|
227
|
+
stub_request(:post, /.*/).to_return(headers: {
|
228
|
+
'Location' => 'https://sample.capsulecrm.com/api/party/100',
|
229
|
+
}, status: 200)
|
230
|
+
end
|
231
|
+
|
232
|
+
let(:opportunity) do
|
233
|
+
CapsuleCRM::Opportunity.new(name: 'Test', milestone_id: 1)
|
234
|
+
end
|
235
|
+
|
236
|
+
before { opportunity.save! }
|
237
|
+
|
238
|
+
it { opportunity.should be_persisted }
|
239
|
+
end
|
240
|
+
|
241
|
+
context 'when the opportunity is not valid' do
|
242
|
+
let(:opportunity) { CapsuleCRM::Opportunity.new }
|
243
|
+
|
244
|
+
it do
|
245
|
+
expect { opportunity.save! }.
|
246
|
+
to raise_error(CapsuleCRM::Errors::RecordInvalid)
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
context 'when the opportunity is not a new record' do
|
252
|
+
context 'when the opportunity is not valid' do
|
253
|
+
|
254
|
+
let(:opportunity) { CapsuleCRM::Opportunity.new(id: 1) }
|
255
|
+
|
256
|
+
it do
|
257
|
+
expect { opportunity.save! }.
|
258
|
+
to raise_exception(CapsuleCRM::Errors::RecordInvalid)
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
describe '#new_record?' do
|
265
|
+
context 'when the opportunity is a new record' do
|
266
|
+
let(:opportunity) { CapsuleCRM::Opportunity.new }
|
267
|
+
|
268
|
+
subject { opportunity.new_record? }
|
269
|
+
|
270
|
+
it { should be_true }
|
271
|
+
end
|
272
|
+
|
273
|
+
context 'when the opportunity is not a new record' do
|
274
|
+
let(:opportunity) { CapsuleCRM::Opportunity.new(id: 1) }
|
275
|
+
|
276
|
+
subject { opportunity.new_record? }
|
277
|
+
|
278
|
+
it { should be_false }
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
describe '#persisted?' do
|
283
|
+
context 'when the opportunity is persisted' do
|
284
|
+
let(:opportunity) { CapsuleCRM::Opportunity.new(id: 1) }
|
285
|
+
|
286
|
+
subject { opportunity.persisted? }
|
287
|
+
|
288
|
+
it { should be_true }
|
289
|
+
end
|
290
|
+
|
291
|
+
context 'when the opportunity is not persisted' do
|
292
|
+
let(:opportunity) { CapsuleCRM::Opportunity.new }
|
293
|
+
|
294
|
+
subject { opportunity.persisted? }
|
295
|
+
|
296
|
+
it { should be_false }
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
describe '.init_collection' do
|
301
|
+
subject do
|
302
|
+
CapsuleCRM::Opportunity.init_collection(
|
303
|
+
JSON.parse(
|
304
|
+
File.read('spec/support/all_opportunities.json')
|
305
|
+
)['opportunities']['opportunity']
|
306
|
+
)
|
307
|
+
end
|
308
|
+
|
309
|
+
it { should be_a(Array) }
|
310
|
+
|
311
|
+
it { subject.length.should eql(1) }
|
312
|
+
|
313
|
+
it do
|
314
|
+
subject.all? { |item| item.is_a?(CapsuleCRM::Opportunity) }.should be_true
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -3,6 +3,10 @@ require 'bundler/setup'
|
|
3
3
|
require 'webmock/rspec'
|
4
4
|
require 'support/helpers'
|
5
5
|
require 'capsule_crm'
|
6
|
+
require 'shoulda-matchers'
|
7
|
+
require 'coveralls'
|
8
|
+
|
9
|
+
Coveralls.wear!
|
6
10
|
|
7
11
|
# This file was generated by the `rspec --init` command. Conventionally, all
|
8
12
|
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
@@ -0,0 +1,23 @@
|
|
1
|
+
{
|
2
|
+
"opportunities": {
|
3
|
+
"opportunity": [
|
4
|
+
{
|
5
|
+
"value": "500.00",
|
6
|
+
"id": "43",
|
7
|
+
"durationBasis": "DAY",
|
8
|
+
"createdOn": "2011-09-30T00:00:00Z",
|
9
|
+
"milestoneId": "2",
|
10
|
+
"duration": "10",
|
11
|
+
"currency": "GBP",
|
12
|
+
"description": "Scope and design web site shopping cart",
|
13
|
+
"name": "Consulting",
|
14
|
+
"owner": "a.user",
|
15
|
+
"milestone": "Bid",
|
16
|
+
"updatedOn": "2011-09-30T00:00:00Z",
|
17
|
+
"probability": "50",
|
18
|
+
"expectedCloseDate": "2012-09-30T00:00:00Z",
|
19
|
+
"partyId": "2"
|
20
|
+
}
|
21
|
+
]
|
22
|
+
}
|
23
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
{
|
2
|
+
"opportunity": {
|
3
|
+
"value": "500.00",
|
4
|
+
"id": "43",
|
5
|
+
"durationBasis": "DAY",
|
6
|
+
"createdOn": "2011-09-30T00:00:00Z",
|
7
|
+
"milestoneId": "2",
|
8
|
+
"duration": "10",
|
9
|
+
"currency": "GBP",
|
10
|
+
"description": "Scope and design web site shopping cart",
|
11
|
+
"name": "Consulting",
|
12
|
+
"owner": "a.user",
|
13
|
+
"milestone": "Bid",
|
14
|
+
"updatedOn": "2011-09-30T00:00:00Z",
|
15
|
+
"probability": "50",
|
16
|
+
"expectedCloseDate": "2012-09-30T00:00:00Z",
|
17
|
+
"partyId": "2"
|
18
|
+
}
|
19
|
+
}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: capsule_crm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Beedle
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-05-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - '>='
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: coveralls
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
98
|
name: cucumber
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -150,6 +164,20 @@ dependencies:
|
|
150
164
|
- - '>='
|
151
165
|
- !ruby/object:Gem::Version
|
152
166
|
version: '0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: shoulda-matchers
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - '>='
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - '>='
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
153
181
|
- !ruby/object:Gem::Dependency
|
154
182
|
name: webmock
|
155
183
|
requirement: !ruby/object:Gem::Requirement
|
@@ -192,6 +220,7 @@ files:
|
|
192
220
|
- lib/capsule_crm/email.rb
|
193
221
|
- lib/capsule_crm/errors/record_invalid.rb
|
194
222
|
- lib/capsule_crm/hash_helper.rb
|
223
|
+
- lib/capsule_crm/opportunity.rb
|
195
224
|
- lib/capsule_crm/organization.rb
|
196
225
|
- lib/capsule_crm/party.rb
|
197
226
|
- lib/capsule_crm/person.rb
|
@@ -202,10 +231,13 @@ files:
|
|
202
231
|
- spec/lib/capsule_crm/address_spec.rb
|
203
232
|
- spec/lib/capsule_crm/contacts_spec.rb
|
204
233
|
- spec/lib/capsule_crm/email_spec.rb
|
234
|
+
- spec/lib/capsule_crm/opportunity_spec.rb
|
205
235
|
- spec/lib/capsule_crm/person_spec.rb
|
206
236
|
- spec/spec_helper.rb
|
237
|
+
- spec/support/all_opportunities.json
|
207
238
|
- spec/support/all_parties.json
|
208
239
|
- spec/support/helpers.rb
|
240
|
+
- spec/support/opportunity.json
|
209
241
|
- spec/support/person.json
|
210
242
|
homepage: ''
|
211
243
|
licenses: []
|
@@ -235,8 +267,11 @@ test_files:
|
|
235
267
|
- spec/lib/capsule_crm/address_spec.rb
|
236
268
|
- spec/lib/capsule_crm/contacts_spec.rb
|
237
269
|
- spec/lib/capsule_crm/email_spec.rb
|
270
|
+
- spec/lib/capsule_crm/opportunity_spec.rb
|
238
271
|
- spec/lib/capsule_crm/person_spec.rb
|
239
272
|
- spec/spec_helper.rb
|
273
|
+
- spec/support/all_opportunities.json
|
240
274
|
- spec/support/all_parties.json
|
241
275
|
- spec/support/helpers.rb
|
276
|
+
- spec/support/opportunity.json
|
242
277
|
- spec/support/person.json
|