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,189 @@
1
+ describe Hubspot::Form do
2
+ let(:guid) { '78c2891f-ebdd-44c0-bd94-15c012bbbfbf' } # '561d9ce9-bb4c-45b4-8e32-21cdeaa3a7f0'
3
+ let(:example_form_hash) do
4
+ VCR.use_cassette('form_example') do
5
+ HTTParty.get("https://api.hubapi.com#{Hubspot::Form::FORMS_PATH}/#{guid}/?hapikey=demo").parsed_response
6
+ end
7
+ end
8
+
9
+ describe '#initialize' do
10
+ subject { Hubspot::Form.new(example_form_hash) }
11
+
12
+ it { should be_an_instance_of Hubspot::Form }
13
+ its(:guid) { should be_a(String) }
14
+ its(:properties) { should be_a(Hash) }
15
+ end
16
+
17
+ before { Hubspot.configure(hapikey: 'demo', portal_id: '62515') }
18
+
19
+ describe '.all' do
20
+ cassette 'find_all_forms'
21
+
22
+ it 'returns all forms' do
23
+ forms = Hubspot::Form.all
24
+ expect(forms.count).to be > 20
25
+
26
+ form = forms.first
27
+ expect(form).to be_a(Hubspot::Form)
28
+ end
29
+ end
30
+
31
+ describe '.find' do
32
+ cassette 'form_find'
33
+ subject { Hubspot::Form.find(guid) }
34
+
35
+ context 'when the form is found' do
36
+ it { should be_an_instance_of Hubspot::Form }
37
+ its(:fields) { should_not be_empty }
38
+ end
39
+
40
+ context 'when the form is not found' do
41
+ it 'raises an error' do
42
+ expect { Hubspot::Form.find(-1) }.to raise_error(Hubspot::RequestError)
43
+ end
44
+ end
45
+ end
46
+
47
+ describe '.create' do
48
+ subject { Hubspot::Form.create!(params) }
49
+
50
+ context 'with all required parameters' do
51
+ cassette 'create_form'
52
+
53
+ let(:params) do
54
+ {
55
+ name: "Demo Form #{Time.now.to_i}",
56
+ action: '',
57
+ method: 'POST',
58
+ cssClass: 'hs-form stacked',
59
+ redirect: '',
60
+ submitText: 'Sign Up',
61
+ followUpId: '',
62
+ leadNurturingCampaignId: '',
63
+ notifyRecipients: '',
64
+ embeddedCode: ''
65
+ }
66
+ end
67
+ it { should be_an_instance_of Hubspot::Form }
68
+ its(:guid) { should be_a(String) }
69
+ end
70
+
71
+ context 'without all required parameters' do
72
+ cassette 'fail_to_create_form'
73
+
74
+ it 'raises an error' do
75
+ expect { Hubspot::Form.create!({}) }.to raise_error(Hubspot::RequestError)
76
+ end
77
+ end
78
+ end
79
+
80
+ describe '#fields' do
81
+ context 'returning all the fields' do
82
+ cassette 'fields_among_form'
83
+
84
+ let(:form) { Hubspot::Form.new(example_form_hash) }
85
+
86
+ it 'returns by default the fields property if present' do
87
+ fields = form.fields
88
+ fields.should_not be_empty
89
+ end
90
+
91
+ it 'updates the fields property and returns it' do
92
+ fields = form.fields(bypass_cache: true)
93
+ fields.should_not be_empty
94
+ end
95
+ end
96
+
97
+ context 'returning an uniq field' do
98
+ cassette 'field_among_form'
99
+
100
+ let(:form) { Hubspot::Form.new(example_form_hash) }
101
+ let(:field_name) { form.fields.first['name'] }
102
+
103
+ it 'returns by default the field if present as a property' do
104
+ field = form.fields(only: field_name)
105
+ expect(field).to be_a(Hash)
106
+ expect(field['name']).to be == field_name
107
+ end
108
+
109
+ it 'makes an API request if specified' do
110
+ field = form.fields(only: field_name, bypass_cache: true)
111
+ expect(field).to be_a(Hash)
112
+ expect(field['name']).to be == field_name
113
+ end
114
+ end
115
+ end
116
+
117
+ describe '#submit' do
118
+ cassette 'form_submit_data'
119
+
120
+ let(:form) { Hubspot::Form.find('561d9ce9-bb4c-45b4-8e32-21cdeaa3a7f0') }
121
+
122
+ context 'with a valid portal id' do
123
+ before do
124
+ Hubspot.configure(hapikey: 'demo', portal_id: '62515')
125
+ end
126
+
127
+ it 'returns true if the form submission is successful' do
128
+ params = {}
129
+ result = form.submit(params)
130
+ result.should be true
131
+ end
132
+ end
133
+
134
+ context 'with an invalid portal id' do
135
+ before do
136
+ Hubspot.configure(hapikey: 'demo', portal_id: 'xxxx')
137
+ end
138
+
139
+ it 'returns false in case of errors' do
140
+ params = { unknown_field: :bogus_value }
141
+ result = form.submit(params)
142
+ result.should be false
143
+ end
144
+ end
145
+
146
+ context 'when initializing Hubspot::Form directly' do
147
+ let(:form) { Hubspot::Form.new('guid' => '561d9ce9-bb4c-45b4-8e32-21cdeaa3a7f0') }
148
+
149
+ before { Hubspot.configure(hapikey: 'demo', portal_id: '62515') }
150
+
151
+ it 'returns true if the form submission is successful' do
152
+ params = {}
153
+ result = form.submit(params)
154
+ result.should be true
155
+ end
156
+ end
157
+ end
158
+
159
+ describe '#update!' do
160
+ cassette 'form_update'
161
+
162
+ new_name = 'updated form name 1424709912'
163
+ redirect = 'http://hubspot.com'
164
+
165
+ let(:form) { Hubspot::Form.find('561d9ce9-bb4c-45b4-8e32-21cdeaa3a7f0') }
166
+ let(:params) { { name: new_name, redirect: redirect } }
167
+ subject { form.update!(params) }
168
+
169
+ it { should be_an_instance_of Hubspot::Form }
170
+ it 'updates properties' do
171
+ subject.properties['name'].should be == new_name
172
+ subject.properties['redirect'].should be == redirect
173
+ end
174
+ end
175
+
176
+ describe '#destroy!' do
177
+ cassette 'form_destroy'
178
+
179
+ # NOTE: form previous created via the create! method
180
+ let(:form) { Hubspot::Form.find('beb92950-ca65-4daf-87ae-a42c054e429f') }
181
+ subject { form.destroy! }
182
+ it { should be true }
183
+
184
+ it 'should be destroyed' do
185
+ subject
186
+ form.destroyed?.should be true
187
+ end
188
+ end
189
+ end
@@ -0,0 +1,56 @@
1
+ describe Hubspot::Owner do
2
+ let(:example_owners) do
3
+ VCR.use_cassette('owner_example') do
4
+ HTTParty.get('https://api.hubapi.com/owners/v2/owners?hapikey=demo&portalId=62515').parsed_response
5
+ end
6
+ end
7
+
8
+ before { Hubspot.configure(hapikey: 'demo') }
9
+
10
+ describe '.all' do
11
+ cassette 'owner_all'
12
+
13
+ it 'should find all owners' do
14
+ owners = Hubspot::Owner.all
15
+
16
+ expect(owners.blank?).to be false
17
+ compare_owners(owners, example_owners)
18
+ end
19
+ end
20
+
21
+ describe '.find_by_email' do
22
+ cassette 'owner_find_by_email'
23
+
24
+ let(:sample) { example_owners.first }
25
+ let(:email) { sample['email'] }
26
+
27
+ it 'should find a user via their email address' do
28
+ owner = Hubspot::Owner.find_by_email(email)
29
+ sample.map do |key, val|
30
+ expect(owner[key]).to eq(val)
31
+ end
32
+ end
33
+ end
34
+
35
+ describe '.find_by_emails' do
36
+ cassette 'owner_find_by_emails'
37
+
38
+ let(:samples) { example_owners[0..[example_owners.count, 3].min] }
39
+ let(:emails) { samples.map { |s| s['email'] } }
40
+
41
+ it 'should find users via their email address' do
42
+ owners = Hubspot::Owner.find_by_emails(emails)
43
+ compare_owners(owners, samples)
44
+ end
45
+ end
46
+ end
47
+
48
+ def compare_owners(owners, examples)
49
+ owners.each do |owner|
50
+ example = examples.detect { |o| o['email'] == owner.email }
51
+ expect(example.blank?).to be false
52
+ example.each do |key, val|
53
+ expect(owner[key]).to eq(val)
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,45 @@
1
+ module Hubspot
2
+ describe Properties do
3
+ let(:params) { { 'name' => 'amount_of_new_money_lined_up',
4
+ 'label' => 'New Money Lined Up (Over $50K or Under $50K)',
5
+ 'description' => '',
6
+ 'groupName' => 'onboarding_questionnaire',
7
+ 'type' => 'enumeration',
8
+ 'fieldType' => 'select',
9
+ 'options' => [{ 'description' => '', 'value' => 'option0', 'readOnly' => false, 'label' => 'Under $50K', 'displayOrder' => 0, 'hidden' => false, 'doubleData' => 0.0 },
10
+ { 'description' => '', 'value' => 'option1', 'readOnly' => false, 'label' => '$50K and above', 'displayOrder' => 1, 'hidden' => false, 'doubleData' => 0.0 },
11
+ { 'description' => nil, 'value' => 'option2', 'readOnly' => nil, 'label' => 'Not applicable', 'displayOrder' => 2, 'hidden' => false, 'doubleData' => nil }],
12
+ 'formField' => true,
13
+ 'displayOrder' => 0,
14
+ 'readOnlyDefinition' => false,
15
+ 'hidden' => false,
16
+ 'mutableDefinitionNotDeletable' => false,
17
+ 'displayMode' => 'current_value',
18
+ 'deleted' => false,
19
+ 'createdUserId' => 2334900,
20
+ 'calculated' => false,
21
+ 'readOnlyValue' => false,
22
+ 'externalOptions' => false,
23
+ 'updatedUserId' => 2225340 } }
24
+ let(:valid_params) { { 'name' => 'amount_of_new_money_lined_up',
25
+ 'groupName' => 'onboarding_questionnaire',
26
+ 'description' => '',
27
+ 'fieldType' => 'select',
28
+ 'formField' => true,
29
+ 'type' => 'enumeration',
30
+ 'displayOrder' => 0,
31
+ 'label' => 'New Money Lined Up (Over $50K or Under $50K)',
32
+ 'options' => [{ 'description' => '', 'value' => 'option0', 'label' => 'Under $50K', 'hidden' => false, 'displayOrder' => 0 },
33
+ { 'description' => '', 'value' => 'option1', 'label' => '$50K and above', 'hidden' => false, 'displayOrder' => 1 },
34
+ { 'description' => nil, 'value' => 'option2', 'label' => 'Not applicable', 'hidden' => false, 'displayOrder' => 2 }]
35
+ } }
36
+
37
+ context '.valid_params' do
38
+ it 'should strip out extra keys and their values' do
39
+ result = Hubspot::Properties.valid_params(params)
40
+ expect(Properties.same?(result, valid_params))
41
+ end
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,54 @@
1
+
2
+ RSpec.describe Hubspot::Resource do
3
+ describe '#new' do
4
+ context 'when specifying an ID' do
5
+ let(:id) { 1 }
6
+ subject { described_class.new(id) }
7
+
8
+ it 'sets the id property' do
9
+ expect(subject.id).to eq id
10
+ end
11
+
12
+ it "isn't persisted" do
13
+ pending "rework of pending flag"
14
+ expect(subject).not_to be_persisted
15
+ end
16
+
17
+ it 'has no changes' do
18
+ expect(subject).not_to be_changed
19
+ end
20
+ end
21
+
22
+ context 'when specifying properties' do
23
+ let(:name) { Faker::Company.name }
24
+ let(:properties) { { name: name } }
25
+ subject { described_class.new properties }
26
+
27
+ it 'has no id' do
28
+ expect(subject.id).to be_nil
29
+ end
30
+
31
+ it 'has the property set' do
32
+ expect(subject[:name]).to eq name
33
+ expect(subject["name"]).to eq name
34
+ expect(subject.name).to eq name
35
+ end
36
+
37
+ it 'has changes' do
38
+ expect(subject.changes).not_to be_empty
39
+ end
40
+ end
41
+
42
+ context 'with no arguments' do
43
+ subject { described_class.new }
44
+
45
+ it 'has no id' do
46
+ expect(subject.id).to be_nil
47
+ end
48
+
49
+ it 'has no changes' do
50
+ expect(subject).not_to be_changed
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,23 @@
1
+ describe Hubspot::Topic do
2
+ before do
3
+ Hubspot.configure(hapikey: "demo")
4
+ end
5
+
6
+ describe ".list" do
7
+ cassette "topics_list"
8
+ let(:topics) { Hubspot::Topic.list }
9
+
10
+ it "should have a list of topics" do
11
+ topics.count.should be(3)
12
+ end
13
+ end
14
+
15
+ describe ".find_by_topic_id" do
16
+ cassette "topics_list"
17
+
18
+ it "should find a specific topic" do
19
+ topic = Hubspot::Topic.find_by_topic_id(349001328)
20
+ topic['id'].should eq(349001328)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,164 @@
1
+ describe Hubspot::Utils do
2
+ describe ".properties_to_hash" do
3
+ let(:properties) do
4
+ {
5
+ "email" => { "value" => "email@address.com" },
6
+ "firstname" => { "value" => "Bob" },
7
+ "lastname" => { "value" => "Smith" }
8
+ }
9
+ end
10
+ subject { Hubspot::Utils.properties_to_hash(properties) }
11
+ its(["email"]) { should == "email@address.com" }
12
+ its(["firstname"]) { should == "Bob" }
13
+ its(["lastname"]) { should == "Smith" }
14
+ end
15
+
16
+ describe ".hash_to_properties" do
17
+ let(:hash) do
18
+ {
19
+ "email" => "email@address.com",
20
+ "firstname" => "Bob",
21
+ "lastname" => "Smith"
22
+ }
23
+ end
24
+ subject { Hubspot::Utils.hash_to_properties(hash) }
25
+ it { should be_an_instance_of Array }
26
+ its(:length) { should == 3 }
27
+ it { should include({ "property" => "email", "value" => "email@address.com" }) }
28
+ it { should include({ "property" => "firstname", "value" => "Bob" }) }
29
+ it { should include({ "property" => "lastname", "value" => "Smith" }) }
30
+ end
31
+
32
+ describe '.compare_property_lists for ContactProperties' do
33
+ let(:example_groups) do
34
+ VCR.use_cassette('contact_properties/groups_example') do
35
+ HTTParty.get('https://api.hubapi.com/contacts/v2/groups?hapikey=demo').parsed_response
36
+ end
37
+ end
38
+
39
+ let(:example_properties) do
40
+ VCR.use_cassette('contact_properties/properties_example') do
41
+ HTTParty.get('https://api.hubapi.com/contacts/v2/properties?hapikey=demo').parsed_response
42
+ end
43
+ end
44
+
45
+ let(:source) { { 'groups' => example_groups, 'properties' => example_properties } }
46
+ let!(:target) { Marshal.load(Marshal.dump(source)) }
47
+
48
+ context 'with no changes' do
49
+ it 'should report no changes' do
50
+ skip, new_groups, new_props, update_props = Hubspot::Utils.compare_property_lists(Hubspot::ContactProperties, source, target)
51
+ expect(skip.count).to be > 0
52
+ expect(new_groups.count).to be(0)
53
+ expect(new_props.count).to be(0)
54
+ expect(update_props.count).to be(0)
55
+ end
56
+ end
57
+
58
+ context 'with changes' do
59
+ let(:description) { "#{source['properties'][0]['description']}_XXX" }
60
+
61
+ count = 0
62
+
63
+ it 'should report the changes' do
64
+ 10.times do |i|
65
+ if !source['properties'][i]['readOnlyDefinition']
66
+ source['properties'][i]['description'] = description
67
+ source['properties'][i]['createdUserId'] = 2500
68
+ count += 1
69
+ end
70
+ end
71
+
72
+ skip, new_groups, new_props, update_props = Hubspot::Utils.compare_property_lists(Hubspot::ContactProperties, source, target)
73
+ expect(skip.count).to be > 0
74
+ expect(new_groups.count).to be(0)
75
+ expect(new_props.count).to be(0)
76
+ expect(update_props.count).to be(count)
77
+ end
78
+ end
79
+ end
80
+
81
+ describe '.compare_property_lists for DealProperties' do
82
+ let(:example_groups) do
83
+ VCR.use_cassette('deal_groups_example') do
84
+ HTTParty.get('https://api.hubapi.com/deals/v1/groups?hapikey=demo').parsed_response
85
+ end
86
+ end
87
+
88
+ let(:example_properties) do
89
+ VCR.use_cassette('deal_properties_example') do
90
+ HTTParty.get('https://api.hubapi.com/deals/v1/properties?hapikey=demo').parsed_response
91
+ end
92
+ end
93
+
94
+ let(:source) { { 'groups' => example_groups, 'properties' => example_properties } }
95
+ let!(:target) { Marshal.load(Marshal.dump(source)) }
96
+
97
+ context 'with no changes' do
98
+ it 'should report no changes' do
99
+ skip, new_groups, new_props, update_props = Hubspot::Utils.compare_property_lists(Hubspot::DealProperties, source, target)
100
+ expect(skip.count).to be > 0
101
+ expect(new_groups.count).to be(0)
102
+ expect(new_props.count).to be(0)
103
+ expect(update_props.count).to be(0)
104
+ end
105
+ end
106
+
107
+ context 'with changes' do
108
+ let(:description) { "#{source['properties'][0]['description']}_XXX" }
109
+
110
+ count = 0
111
+
112
+ it 'should report the changes' do
113
+ 10.times do |i|
114
+ if !source['properties'][i]['readOnlyDefinition']
115
+ source['properties'][i]['description'] = description
116
+ source['properties'][i]['createdUserId'] = 2500
117
+ count += 1
118
+ end
119
+ end
120
+
121
+ skip, new_groups, new_props, update_props = Hubspot::Utils.compare_property_lists(Hubspot::DealProperties, source, target)
122
+ expect(skip.count).to be > 0
123
+ expect(new_groups.count).to be(0)
124
+ expect(new_props.count).to be(0)
125
+ expect(update_props.count).to be(count)
126
+ end
127
+ end
128
+ end
129
+
130
+ describe ".dump_properties" do
131
+ it "prints a deprecation warning" do
132
+ VCR.use_cassette("dump_deal_properties_and_groups") do
133
+ api_key = "demo"
134
+
135
+ output = capture_stderr do
136
+ Hubspot::Utils.dump_properties(Hubspot::DealProperties, api_key)
137
+ end
138
+
139
+ expected_warning = "Hubspot::Utils.dump_properties is deprecated"
140
+ expect(output).to include(expected_warning)
141
+ end
142
+ end
143
+ end
144
+
145
+ describe ".restore_properties" do
146
+ it "prints a deprecation warning" do
147
+ VCR.use_cassette("restore_deal_properties_and_groups") do
148
+ api_key = "demo"
149
+ properties = {"groups" => {}, "properties" => {}}
150
+
151
+ output = capture_stderr do
152
+ Hubspot::Utils.restore_properties(
153
+ Hubspot::DealProperties,
154
+ api_key,
155
+ properties
156
+ )
157
+ end
158
+
159
+ expected_warning = "Hubspot::Utils.restore_properties is deprecated"
160
+ expect(output).to include(expected_warning)
161
+ end
162
+ end
163
+ end
164
+ end