hubspot-api-ruby 0.8.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 (73) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/Gemfile +3 -0
  4. data/Guardfile +9 -0
  5. data/LICENSE.txt +18 -0
  6. data/README.md +295 -0
  7. data/RELEASING.md +6 -0
  8. data/Rakefile +32 -0
  9. data/hubspot-api-ruby.gemspec +42 -0
  10. data/lib/hubspot-api-ruby.rb +39 -0
  11. data/lib/hubspot/blog.rb +98 -0
  12. data/lib/hubspot/collection.rb +41 -0
  13. data/lib/hubspot/company.rb +160 -0
  14. data/lib/hubspot/company_properties.rb +59 -0
  15. data/lib/hubspot/config.rb +63 -0
  16. data/lib/hubspot/connection.rb +152 -0
  17. data/lib/hubspot/contact.rb +110 -0
  18. data/lib/hubspot/contact_list.rb +129 -0
  19. data/lib/hubspot/contact_properties.rb +59 -0
  20. data/lib/hubspot/deal.rb +173 -0
  21. data/lib/hubspot/deal_pipeline.rb +58 -0
  22. data/lib/hubspot/deal_properties.rb +59 -0
  23. data/lib/hubspot/deprecator.rb +7 -0
  24. data/lib/hubspot/engagement.rb +222 -0
  25. data/lib/hubspot/event.rb +21 -0
  26. data/lib/hubspot/exceptions.rb +18 -0
  27. data/lib/hubspot/file.rb +38 -0
  28. data/lib/hubspot/form.rb +95 -0
  29. data/lib/hubspot/oauth.rb +50 -0
  30. data/lib/hubspot/owner.rb +57 -0
  31. data/lib/hubspot/paged_collection.rb +35 -0
  32. data/lib/hubspot/properties.rb +123 -0
  33. data/lib/hubspot/railtie.rb +10 -0
  34. data/lib/hubspot/resource.rb +270 -0
  35. data/lib/hubspot/subscription.rb +37 -0
  36. data/lib/hubspot/topic.rb +37 -0
  37. data/lib/hubspot/utils.rb +127 -0
  38. data/lib/tasks/hubspot.rake +53 -0
  39. data/spec/factories/companies.rb +9 -0
  40. data/spec/factories/contacts.rb +10 -0
  41. data/spec/lib/hubspot-ruby_spec.rb +12 -0
  42. data/spec/lib/hubspot/blog_spec.rb +150 -0
  43. data/spec/lib/hubspot/company_properties_spec.rb +410 -0
  44. data/spec/lib/hubspot/company_spec.rb +340 -0
  45. data/spec/lib/hubspot/config_spec.rb +87 -0
  46. data/spec/lib/hubspot/connection_spec.rb +214 -0
  47. data/spec/lib/hubspot/contact_list_spec.rb +301 -0
  48. data/spec/lib/hubspot/contact_properties_spec.rb +245 -0
  49. data/spec/lib/hubspot/contact_spec.rb +223 -0
  50. data/spec/lib/hubspot/deal_pipeline_spec.rb +85 -0
  51. data/spec/lib/hubspot/deal_properties_spec.rb +262 -0
  52. data/spec/lib/hubspot/deal_spec.rb +185 -0
  53. data/spec/lib/hubspot/deprecator_spec.rb +15 -0
  54. data/spec/lib/hubspot/engagement_spec.rb +177 -0
  55. data/spec/lib/hubspot/event_spec.rb +33 -0
  56. data/spec/lib/hubspot/file_spec.rb +38 -0
  57. data/spec/lib/hubspot/form_spec.rb +189 -0
  58. data/spec/lib/hubspot/owner_spec.rb +56 -0
  59. data/spec/lib/hubspot/properties_spec.rb +45 -0
  60. data/spec/lib/hubspot/resource_spec.rb +54 -0
  61. data/spec/lib/hubspot/topic_spec.rb +23 -0
  62. data/spec/lib/hubspot/utils_spec.rb +164 -0
  63. data/spec/lib/tasks/hubspot_spec.rb +119 -0
  64. data/spec/shared_examples/saveable_resource.rb +45 -0
  65. data/spec/shared_examples/updateable_resource.rb +87 -0
  66. data/spec/spec_helper.rb +44 -0
  67. data/spec/support/capture_output.rb +21 -0
  68. data/spec/support/cassette_helper.rb +19 -0
  69. data/spec/support/hubspot_api_helpers.rb +13 -0
  70. data/spec/support/rake.rb +46 -0
  71. data/spec/support/tests_helper.rb +17 -0
  72. data/spec/support/vcr.rb +16 -0
  73. metadata +369 -0
@@ -0,0 +1,223 @@
1
+ RSpec.describe Hubspot::Contact do
2
+
3
+ before{ Hubspot.configure(hapikey: 'demo') }
4
+
5
+ it_behaves_like "a saveable resource", :contact do
6
+ def set_property(contact)
7
+ contact.firstname = "foobar"
8
+ end
9
+ end
10
+
11
+ it_behaves_like "an updateable resource", :contact do
12
+ let(:changed_properties) { { firstname: "foobar" } }
13
+ let(:overlapping_properties) { { firstname: "asdf", lastname: "qwer" } }
14
+ end
15
+
16
+ describe '.find' do
17
+ context 'with a valid ID' do
18
+ cassette
19
+
20
+ let(:company) { create :company }
21
+ let(:contact) { create :contact, associatedcompanyid: company.id }
22
+ subject { described_class.find contact.id }
23
+
24
+ it 'finds the contact' do
25
+ expect(subject).to be_a(described_class)
26
+ expect(subject.id).to eq(contact.id)
27
+ end
28
+ end
29
+
30
+ context 'with an invalid ID' do
31
+ cassette
32
+
33
+ subject { described_class.find 0 }
34
+
35
+ it 'raises an error' do
36
+ expect {
37
+ subject
38
+ }.to raise_error(Hubspot::RequestError, /contact does not exist/)
39
+ end
40
+ end
41
+ end
42
+
43
+ describe '.create' do
44
+ context 'without properties' do
45
+ cassette
46
+
47
+ let(:email) { Faker::Internet.safe_email("#{(0..3).map { (65 + rand(26)).chr }.join}#{Time.new.to_i.to_s[-5..-1]}") }
48
+ subject { described_class.create email }
49
+
50
+ it 'creates a new contact' do
51
+ expect(subject).to be_a(described_class)
52
+ expect(subject.id).not_to be_nil
53
+ end
54
+ end
55
+
56
+ context 'with properties' do
57
+ cassette
58
+
59
+ let(:email) { Faker::Internet.safe_email("#{(0..3).map { (65 + rand(26)).chr }.join}#{Time.new.to_i.to_s[-5..-1]}") }
60
+ let(:firstname) { "Allison" }
61
+ let(:properties) { { firstname: firstname } }
62
+
63
+ subject { described_class.create email, properties }
64
+
65
+ it 'creates a new contact' do
66
+ expect(subject).to be_a(described_class)
67
+ expect(subject.id).not_to be_nil
68
+ end
69
+
70
+ it 'has the property set' do
71
+ expect(subject.firstname).to eq(firstname)
72
+ end
73
+
74
+ it 'is persisted' do
75
+ expect(subject).to be_persisted
76
+ end
77
+ end
78
+
79
+ context 'with an existing email address' do
80
+ cassette
81
+
82
+ let(:contact) { create :contact }
83
+ let(:email) { contact.email }
84
+
85
+ subject { described_class.create email }
86
+
87
+ it 'raises an error' do
88
+ expect {
89
+ subject
90
+ }.to raise_error(Hubspot::RequestError)
91
+ end
92
+ end
93
+
94
+ context 'with an invalid email address' do
95
+ cassette
96
+
97
+ let(:email) { 'an_invalid_email' }
98
+
99
+ subject { described_class.create email }
100
+
101
+ it 'raises an error' do
102
+ expect {
103
+ subject
104
+ }.to raise_error(Hubspot::RequestError)
105
+ end
106
+ end
107
+ end
108
+
109
+ describe '.find_by_email' do
110
+ cassette
111
+
112
+ let(:contact) { create :contact }
113
+
114
+ subject { described_class.find_by_email contact.email }
115
+
116
+ it 'finds the contact' do
117
+ expect(subject).to be_a(described_class)
118
+ expect(subject.id).to eq(contact.id)
119
+ end
120
+
121
+ it 'is persisted' do
122
+ expect(subject).to be_persisted
123
+ end
124
+ end
125
+
126
+ describe '.find_by_user_token' do
127
+ cassette
128
+
129
+ let(:contact) { create :contact }
130
+ subject { described_class.find_by_user_token contact.utk }
131
+
132
+ it 'finds the contact' do
133
+ skip 'need a contact with a user token'
134
+ expect(subject).to be_a(described_class)
135
+ expect(subject.id).to eq(contact.id)
136
+ end
137
+ end
138
+
139
+ describe '.search' do
140
+ cassette
141
+
142
+ context 'when the query returns contacts' do
143
+ subject { described_class.search 'com' }
144
+
145
+ it 'has contacts' do
146
+ expect(subject).not_to be_empty
147
+ expect(subject.first).to be_a(described_class)
148
+ end
149
+ end
150
+
151
+ context 'when the query returns no contacts' do
152
+ subject { described_class.search '123xyz' }
153
+
154
+ it 'has no contacts' do
155
+ expect(subject).to be_empty
156
+ end
157
+
158
+ it 'does not have more' do
159
+ expect(subject.more?).to be_falsey
160
+ end
161
+
162
+ it 'does not have a next page' do
163
+ expect(subject.next_page?).to be_falsey
164
+ end
165
+ end
166
+ end
167
+
168
+ describe '.merge' do
169
+ context 'with valid contact ids' do
170
+ cassette
171
+
172
+ let!(:contact1) { create :contact }
173
+ let!(:contact2) { create :contact }
174
+
175
+ subject { described_class.merge contact1.id, contact2.id }
176
+
177
+ it 'succeeds' do
178
+ expect(subject).to be_truthy
179
+ end
180
+ end
181
+
182
+ context 'with invalid contact ids' do
183
+ cassette
184
+
185
+ subject { described_class.merge 1, 2 }
186
+
187
+ it 'raises an error' do
188
+ expect {
189
+ subject
190
+ }.to raise_error(Hubspot::RequestError)
191
+ end
192
+ end
193
+ end
194
+
195
+ describe '#merge' do
196
+ context 'with a valid contact' do
197
+ cassette
198
+
199
+ let!(:contact1) { create :contact }
200
+ let!(:contact2) { create :contact }
201
+
202
+ subject { contact1.merge(contact2) }
203
+
204
+ it 'succeeds' do
205
+ expect(subject).to be_truthy
206
+ end
207
+ end
208
+
209
+ context 'with an invalid contact' do
210
+ cassette
211
+
212
+ let!(:contact1) { create :contact }
213
+
214
+ subject { contact1.merge(1) }
215
+
216
+ it 'raises an error' do
217
+ expect {
218
+ subject
219
+ }.to raise_error(Hubspot::RequestError)
220
+ end
221
+ end
222
+ end
223
+ end
@@ -0,0 +1,85 @@
1
+ RSpec.describe Hubspot::DealPipeline do
2
+ before do
3
+ Hubspot.configure hapikey: 'demo'
4
+ end
5
+
6
+ describe ".find" do
7
+ it "retrieves a record by id" do
8
+ VCR.use_cassette("find_deal_pipeline") do
9
+ deal_pipeline = Hubspot::DealPipeline.create!(label: "New Pipeline")
10
+ id = deal_pipeline.pipeline_id
11
+
12
+ result = Hubspot::DealPipeline.find(deal_pipeline.pipeline_id)
13
+
14
+ assert_requested :get, hubspot_api_url("/deals/v1/pipelines/#{id}")
15
+ expect(result).to be_a(Hubspot::DealPipeline)
16
+
17
+ deal_pipeline.destroy!
18
+ end
19
+ end
20
+ end
21
+
22
+ describe ".all" do
23
+ it "returns a list" do
24
+ VCR.use_cassette("all_deal_pipelines") do
25
+ deal_pipeline = Hubspot::DealPipeline.create!(label: "New Pipeline")
26
+
27
+ results = Hubspot::DealPipeline.all
28
+
29
+ assert_requested :get, hubspot_api_url("/deals/v1/pipelines")
30
+ expect(results).to be_kind_of(Array)
31
+ expect(results.first).to be_a(Hubspot::DealPipeline)
32
+
33
+ deal_pipeline.destroy!
34
+ end
35
+ end
36
+ end
37
+
38
+ describe ".create!" do
39
+ it "creates a new record" do
40
+ VCR.use_cassette("create_deal_pipeline") do
41
+ result = Hubspot::DealPipeline.create!(label: "New Pipeline")
42
+
43
+ assert_requested :post, hubspot_api_url("/deals/v1/pipelines")
44
+ expect(result).to be_a(Hubspot::DealPipeline)
45
+
46
+ result.destroy!
47
+ end
48
+ end
49
+ end
50
+
51
+ describe "#destroy!" do
52
+ it "deletes the record" do
53
+ VCR.use_cassette("delete_deal_pipeline") do
54
+ deal_pipeline = Hubspot::DealPipeline.create!(label: "New Pipeline")
55
+ id = deal_pipeline.pipeline_id
56
+
57
+ result = deal_pipeline.destroy!
58
+
59
+ assert_requested :delete, hubspot_api_url("/deals/v1/pipelines/#{id}")
60
+ expect(result).to be_a(HTTParty::Response)
61
+ end
62
+ end
63
+ end
64
+
65
+ describe "#[]" do
66
+ it "returns the stage at the specified index" do
67
+ data = {
68
+ "stages" => [
69
+ {"active": true, "label": "New Lead"},
70
+ {"active": true, "label": "Proposal"},
71
+ ],
72
+ }
73
+
74
+ deal_pipeline = Hubspot::DealPipeline.new(data)
75
+
76
+ result = deal_pipeline[0]
77
+
78
+ expect(result).to eq(data["stages"][0])
79
+ end
80
+ end
81
+
82
+ def hubspot_api_url(path)
83
+ URI.join(Hubspot::Config.base_url, path, "?hapikey=demo")
84
+ end
85
+ end
@@ -0,0 +1,262 @@
1
+ describe Hubspot::DealProperties do
2
+ describe '.add_default_parameters' do
3
+ let(:opts) { {} }
4
+ subject { Hubspot::DealProperties.add_default_parameters(opts) }
5
+ context 'default parameters' do
6
+ context 'without property parameter' do
7
+ its([:property]) { should == 'email' }
8
+ end
9
+
10
+ context 'with property parameter' do
11
+ let(:opts) { {property: 'dealname' } }
12
+ its([:property]) { should == 'dealname'}
13
+ end
14
+ end
15
+ end
16
+
17
+ let(:example_groups) do
18
+ VCR.use_cassette('deal_groups_example') do
19
+ HTTParty.get('https://api.hubapi.com/deals/v1/groups?hapikey=demo').parsed_response
20
+ end
21
+ end
22
+
23
+ let(:example_properties) do
24
+ VCR.use_cassette('deal_properties_example') do
25
+ HTTParty.get('https://api.hubapi.com/deals/v1/properties?hapikey=demo').parsed_response
26
+ end
27
+ end
28
+
29
+ before { Hubspot.configure(hapikey: 'demo') }
30
+
31
+ describe 'Properties' do
32
+ describe '.all' do
33
+ context 'with no filter' do
34
+ cassette 'deal_all_properties'
35
+
36
+ it 'should return all properties' do
37
+ expect(Hubspot::DealProperties.all).to eql(example_properties)
38
+ end
39
+ end
40
+
41
+ let(:groups) { %w(calltrackinginfo emailinformation) }
42
+
43
+ context 'with included groups' do
44
+ cassette 'deal_properties_in_groups'
45
+
46
+ it 'should return properties for the specified group[s]' do
47
+ response = Hubspot::DealProperties.all({}, { include: groups })
48
+ response.each { |p| expect(groups.include?(p['groupName'])).to be true }
49
+ end
50
+ end
51
+
52
+ context 'with excluded groups' do
53
+ cassette 'deal_properties_not_in_groups'
54
+
55
+ it 'should return properties for the non-specified group[s]' do
56
+ response = Hubspot::DealProperties.all({}, { exclude: groups })
57
+ response.each { |p| expect(groups.include?(p['groupName'])).to be false }
58
+ end
59
+ end
60
+ end
61
+
62
+ let(:params) { {
63
+ 'name' => 'my_new_property',
64
+ 'label' => 'This is my new property',
65
+ 'description' => 'How much money do you have?',
66
+ 'groupName' => 'dealinformation',
67
+ 'type' => 'string',
68
+ 'fieldType' => 'text',
69
+ 'hidden' => false,
70
+ 'options' => [{
71
+ 'description' => '',
72
+ 'value' => 'Over $50K',
73
+ 'readOnly' => false,
74
+ 'label' => 'Over $50K',
75
+ 'displayOrder' => 0,
76
+ 'hidden' => false,
77
+ 'doubleData' => 0.0
78
+ },
79
+ {
80
+ 'description' => '',
81
+ 'value' => 'Under $50K',
82
+ 'readOnly' => false,
83
+ 'label' => 'Under $50K',
84
+ 'displayOrder' => 1,
85
+ 'hidden' => false,
86
+ 'doubleData' => 0.0
87
+ }],
88
+ 'deleted' => false,
89
+ 'displayOrder' => 0,
90
+ 'formField' => true,
91
+ 'readOnlyValue' => false,
92
+ 'readOnlyDefinition' => false,
93
+ 'mutableDefinitionNotDeletable' => false,
94
+ 'calculated' => false,
95
+ 'externalOptions' => false,
96
+ 'displayMode' => 'current_value'
97
+ } }
98
+
99
+ describe '.create!' do
100
+ context 'with no valid parameters' do
101
+ cassette 'deal_fail_to_create_property'
102
+
103
+ it 'should return nil' do
104
+ expect(Hubspot::DealProperties.create!({})).to be(nil)
105
+ end
106
+ end
107
+
108
+ context 'with all valid parameters' do
109
+ cassette 'deal_create_property'
110
+
111
+ it 'should return the valid parameters' do
112
+ response = Hubspot::DealProperties.create!(params)
113
+ expect(Hubspot::DealProperties.same?(params, response)).to be true
114
+ end
115
+ end
116
+ end
117
+
118
+ describe '.update!' do
119
+ context 'with no valid parameters' do
120
+
121
+ it 'should return nil ' do
122
+ expect(Hubspot::DealProperties.update!(params['name'], {})).to be(nil)
123
+ end
124
+ end
125
+
126
+ context 'with mixed parameters' do
127
+ cassette 'deal_update_property'
128
+
129
+ it 'should return the valid parameters' do
130
+ params['description'] = 'What is their favorite flavor?'
131
+
132
+ response = Hubspot::DealProperties.update!(params['name'], params)
133
+ expect(Hubspot::DealProperties.same?(response, params)).to be true
134
+ end
135
+ end
136
+ end
137
+
138
+ describe '.delete!' do
139
+ let(:name) { params['name'] }
140
+
141
+ context 'with existing property' do
142
+ cassette 'deal_delete_property'
143
+
144
+ it 'should return nil' do
145
+ expect(Hubspot::DealProperties.delete!(name)).to eq(nil)
146
+ end
147
+ end
148
+
149
+ context 'with non-existent property' do
150
+ cassette 'deal_delete_non_property'
151
+
152
+ it 'should raise an error' do
153
+ expect { Hubspot::DealProperties.delete!(name) }.to raise_error(Hubspot::RequestError)
154
+ end
155
+ end
156
+ end
157
+ end
158
+
159
+ describe 'Groups' do
160
+ describe '.groups' do
161
+ context 'with no filter' do
162
+ cassette 'deal_all_groups'
163
+
164
+ it 'should return all groups' do
165
+ expect(Hubspot::DealProperties.groups).to eql(example_groups)
166
+ end
167
+ end
168
+
169
+ let(:groups) { %w(calltrackinginfo emailinformation) }
170
+
171
+ context 'with included groups' do
172
+ cassette 'deal_groups_included'
173
+
174
+ it 'should return the specified groups' do
175
+ response = Hubspot::DealProperties.groups({}, { include: groups })
176
+ response.each { |p| expect(groups.include?(p['name'])).to be true }
177
+ end
178
+ end
179
+
180
+ context 'with excluded groups' do
181
+ cassette 'deal_groups_not_excluded'
182
+
183
+ it 'should return groups that were not excluded' do
184
+ response = Hubspot::DealProperties.groups({}, { exclude: groups })
185
+ response.each { |p| expect(groups.include?(p['name'])).to be false }
186
+ end
187
+ end
188
+ end
189
+
190
+ let(:params) { { 'name' => 'ff_group1', 'displayName' => 'Test Group One', 'displayOrder' => 100, 'badParam' => 99 } }
191
+
192
+ describe '.create_group!' do
193
+ context 'with no valid parameters' do
194
+ it 'should return nil' do
195
+ expect(Hubspot::DealProperties.create_group!({})).to be(nil)
196
+ end
197
+ end
198
+
199
+ context 'with mixed parameters' do
200
+ cassette 'deal_create_group'
201
+
202
+ it 'should return the valid parameters' do
203
+ response = Hubspot::DealProperties.create_group!(params)
204
+ expect(Hubspot::DealProperties.same?(response, params)).to be true
205
+ end
206
+ end
207
+
208
+ context 'with some valid parameters' do
209
+ cassette 'deal_create_group_some_params'
210
+
211
+ let(:sub_params) { params.select { |k, _| k != 'displayName' } }
212
+
213
+ it 'should return the valid parameters' do
214
+ params['name'] = 'ff_group234'
215
+ response = Hubspot::DealProperties.create_group!(sub_params)
216
+ expect(Hubspot::DealProperties.same?(response, sub_params)).to be true
217
+ end
218
+ end
219
+ end
220
+
221
+ describe '.update_group!' do
222
+ context 'with no valid parameters' do
223
+
224
+ it 'should return nil ' do
225
+ expect(Hubspot::DealProperties.update_group!(params['name'], {})).to be(nil)
226
+ end
227
+ end
228
+
229
+ context 'with mixed parameters' do
230
+ cassette 'deal_update_group'
231
+
232
+ it 'should return the valid parameters' do
233
+ params['displayName'] = 'Test Group OneA'
234
+
235
+ response = Hubspot::DealProperties.update_group!(params['name'], params)
236
+ expect(Hubspot::DealProperties.same?(response, params)).to be true
237
+ end
238
+ end
239
+
240
+ end
241
+
242
+ describe '.delete_group!' do
243
+ let(:name) { params['name'] }
244
+
245
+ context 'with existing group' do
246
+ cassette 'deal_delete_group'
247
+
248
+ it 'should return nil' do
249
+ expect(Hubspot::DealProperties.delete_group!(name)).to eq(nil)
250
+ end
251
+ end
252
+
253
+ context 'with non-existent group' do
254
+ cassette 'deal_delete_non_group'
255
+
256
+ it 'should raise an error' do
257
+ expect { Hubspot::DealProperties.delete_group!(name) }.to raise_error(Hubspot::RequestError)
258
+ end
259
+ end
260
+ end
261
+ end
262
+ end