blue_state_digital 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +1 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +3 -0
  7. data/Gemfile +2 -0
  8. data/Guardfile +5 -0
  9. data/LICENSE +24 -0
  10. data/README.md +123 -0
  11. data/Rakefile +11 -0
  12. data/blue_state_digital.gemspec +37 -0
  13. data/lib/blue_state_digital.rb +32 -0
  14. data/lib/blue_state_digital/address.rb +28 -0
  15. data/lib/blue_state_digital/api_data_model.rb +31 -0
  16. data/lib/blue_state_digital/collection_resource.rb +14 -0
  17. data/lib/blue_state_digital/connection.rb +119 -0
  18. data/lib/blue_state_digital/constituent.rb +178 -0
  19. data/lib/blue_state_digital/constituent_group.rb +151 -0
  20. data/lib/blue_state_digital/contribution.rb +73 -0
  21. data/lib/blue_state_digital/dataset.rb +139 -0
  22. data/lib/blue_state_digital/dataset_map.rb +138 -0
  23. data/lib/blue_state_digital/email.rb +22 -0
  24. data/lib/blue_state_digital/email_unsubscribe.rb +11 -0
  25. data/lib/blue_state_digital/error_middleware.rb +29 -0
  26. data/lib/blue_state_digital/event.rb +46 -0
  27. data/lib/blue_state_digital/event_rsvp.rb +17 -0
  28. data/lib/blue_state_digital/event_type.rb +19 -0
  29. data/lib/blue_state_digital/phone.rb +20 -0
  30. data/lib/blue_state_digital/version.rb +3 -0
  31. data/spec/blue_state_digital/address_spec.rb +25 -0
  32. data/spec/blue_state_digital/api_data_model_spec.rb +13 -0
  33. data/spec/blue_state_digital/connection_spec.rb +153 -0
  34. data/spec/blue_state_digital/constituent_group_spec.rb +269 -0
  35. data/spec/blue_state_digital/constituent_spec.rb +422 -0
  36. data/spec/blue_state_digital/contribution_spec.rb +132 -0
  37. data/spec/blue_state_digital/dataset_map_spec.rb +137 -0
  38. data/spec/blue_state_digital/dataset_spec.rb +177 -0
  39. data/spec/blue_state_digital/email_spec.rb +16 -0
  40. data/spec/blue_state_digital/error_middleware_spec.rb +15 -0
  41. data/spec/blue_state_digital/event_rsvp_spec.rb +17 -0
  42. data/spec/blue_state_digital/event_spec.rb +70 -0
  43. data/spec/blue_state_digital/event_type_spec.rb +51 -0
  44. data/spec/blue_state_digital/phone_spec.rb +16 -0
  45. data/spec/fixtures/multiple_event_types.json +234 -0
  46. data/spec/fixtures/single_event_type.json +117 -0
  47. data/spec/spec_helper.rb +21 -0
  48. data/spec/support/matchers/fields.rb +23 -0
  49. metadata +334 -0
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe BlueStateDigital::ErrorMiddleware do
4
+ it 'should raise with the env' do
5
+ expect do
6
+ subject.on_complete(OpenStruct.new({status: 409, body: 'foo bar'}))
7
+ end.to raise_error(Faraday::Error::ClientError, /foo bar/)
8
+ end
9
+
10
+ it 'should raise a typed exception' do
11
+ expect do
12
+ subject.on_complete(OpenStruct.new({status: 409, body: 'cons_group_id #279 does not exist'}))
13
+ end.to raise_error(BlueStateDigital::ResourceDoesNotExist, /cons_group_id #279 does not exist/)
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe BlueStateDigital::EventRSVP do
4
+ let(:connection) { double }
5
+
6
+ subject { BlueStateDigital::EventRSVP.new(event_rsvp_attributes.merge({connection: connection})) }
7
+
8
+ describe '#save' do
9
+ let(:event_rsvp_attributes) { { event_id_obfuscated: 'xyz', will_attend: '1', email: 'john@example.com', zip: '10010', country: 'US' } }
10
+
11
+ it "should save using Graph API" do
12
+ expect(connection).to receive(:perform_graph_request).with('/addrsvp', { event_id_obfuscated: 'xyz', will_attend: '1', email: 'john@example.com', zip: '10010', country: 'US' }, 'POST')
13
+
14
+ subject.save
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,70 @@
1
+ require 'spec_helper'
2
+
3
+ describe BlueStateDigital::Event do
4
+ let(:start_date) { Time.now }
5
+ let(:end_date) { start_date + 1.hour }
6
+ let(:event_attributes) { {event_type_id: '1', creator_cons_id: '2', name: 'event 1', description: 'my event', venue_name: 'home', venue_country: 'US', venue_zip: '10001', venue_city: 'New York', venue_state_cd: 'NY', start_date: start_date, end_date: end_date} }
7
+
8
+ describe '#to_json' do
9
+ it "should serialize event without event_id_obfuscated" do
10
+ event = BlueStateDigital::Event.new(event_attributes)
11
+
12
+ event_json = JSON.parse(event.to_json)
13
+
14
+ expect(event_json.keys).not_to include(:event_id_obfuscated)
15
+ [:event_type_id, :creator_cons_id, :name, :description, :venue_name, :venue_country, :venue_zip, :venue_city, :venue_state_cd].each do |direct_attribute|
16
+ expect(event_json[direct_attribute.to_s]).to eq(event_attributes[direct_attribute])
17
+ end
18
+ expect(event_json['days'].count).to eq(1)
19
+ start_date = event_json['days'][0]['start_datetime_system']
20
+ expect(Time.parse(start_date)).to eq(start_date)
21
+ expect(event_json['days'][0]['duration']).to eq(60)
22
+ end
23
+
24
+ it "should serialize event with event_id_obfuscated" do
25
+ event_attributes[:event_id_obfuscated] = 'xyz'
26
+ event = BlueStateDigital::Event.new(event_attributes)
27
+
28
+ event_json = JSON.parse(event.to_json)
29
+
30
+ [:event_id_obfuscated, :event_type_id, :creator_cons_id, :name, :description, :venue_name, :venue_country, :venue_zip, :venue_city, :venue_state_cd].each do |direct_attribute|
31
+ expect(event_json[direct_attribute.to_s]).to eq(event_attributes[direct_attribute])
32
+ end
33
+ expect(event_json['days'].count).to eq(1)
34
+ start_date = event_json['days'][0]['start_datetime_system']
35
+ expect(Time.parse(start_date)).to eq(start_date)
36
+ expect(event_json['days'][0]['duration']).to eq(60)
37
+ end
38
+ end
39
+
40
+ describe '#save' do
41
+ let(:connection) { double }
42
+ let(:event) { BlueStateDigital::Event.new(event_attributes.merge({ connection: connection })) }
43
+
44
+ before :each do
45
+ expect(connection)
46
+ .to receive(:perform_request)
47
+ .with('/event/create_event', {accept: 'application/json', event_api_version: '2', values: event.to_json}, 'POST')
48
+ .and_return(response)
49
+ end
50
+
51
+ context 'successful' do
52
+ let(:response) { '{"event_id_obfuscated":"xyz", "event_type_id":"1", "creator_cons_id":"2", "name":"event 1", "description":"my event", "venue_name":"home", "venue_zip":"10001", "venue_city":"New York", "venue_state_cd":"NY", "days":[{"start_dt":"2014-02-13 22:00:00", "duration":"180"}]}' }
53
+
54
+ it "should perform API request and return event with event_id_obfuscated set" do
55
+ saved_event = event.save
56
+
57
+ expect(saved_event).not_to be_nil
58
+ expect(saved_event.event_id_obfuscated).to eq('xyz')
59
+ end
60
+ end
61
+
62
+ context 'validation error' do
63
+ let(:response) { '{"validation_errors":{"venue_zip":["required","regex"], "name":["required"]}}' }
64
+
65
+ it "should raise error" do
66
+ expect { event.save }.to raise_error(BlueStateDigital::Event::EventSaveValidationException, /venue_zip.*name/m)
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ describe BlueStateDigital::EventType do
4
+ subject { BlueStateDigital::EventType.new }
5
+
6
+ it { is_expected.to respond_to(:event_type_id) }
7
+ it { is_expected.to respond_to(:event_type_id=) }
8
+ it { is_expected.to respond_to(:name) }
9
+ it { is_expected.to respond_to(:name=) }
10
+ it { is_expected.to respond_to(:description) }
11
+ it { is_expected.to respond_to(:description=) }
12
+ end
13
+
14
+ describe BlueStateDigital::EventTypes do
15
+ let(:connection) { BlueStateDigital::Connection.new({}) }
16
+
17
+ let(:single_event_types_response) { fixture('single_event_type.json').read }
18
+ let(:multiple_event_types_response) { fixture('multiple_event_types.json').read }
19
+
20
+ subject { BlueStateDigital::EventTypes.new(connection) }
21
+
22
+ it "should retrieve single event type" do
23
+ expect(connection).to receive(:perform_request).with('/event/get_available_types', {}, 'GET').and_return(single_event_types_response)
24
+
25
+ event_types = subject.get_event_types
26
+
27
+ expect(event_types.count).to eq(1)
28
+ expect(event_types.first.event_type_id).to eq('1')
29
+ expect(event_types.first.name).to eq("My event type")
30
+ expect(event_types.first.description).to eq("An event type for testing")
31
+ end
32
+
33
+ it "should retrieve multiple event types" do
34
+ expect(connection).to receive(:perform_request).with('/event/get_available_types', {}, 'GET').and_return(multiple_event_types_response)
35
+
36
+ event_types = subject.get_event_types
37
+
38
+ expect(event_types.count).to eq(2)
39
+ verify_event_type_existence(event_types, {id: '1', name: 'My first event type', description: 'An event type for testing'})
40
+ verify_event_type_existence(event_types, {id: '2', name: 'My second event type', description: 'Another event type for testing'})
41
+ end
42
+
43
+ def verify_event_type_existence(event_types, expected_event_type_attributes)
44
+ expected_event_type_attributes.each do |attr, value|
45
+ unless attr == :id
46
+ val = event_types.any?{ |et| et.send(attr) == value }
47
+ expect(val).to be_truthy
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe BlueStateDigital::Phone do
4
+ describe :to_hash do
5
+ it "should return a hash of all fields" do
6
+ attr_hash = {phone: '123432', phone_type: 'personal', is_primary: '1', is_subscribed: '0'}
7
+ phone = BlueStateDigital::Phone.new attr_hash
8
+ expect(phone.to_hash).to eq(attr_hash)
9
+ end
10
+ it "should include nil fields" do
11
+ expected_hash = {phone: nil, phone_type: nil, is_primary: nil, is_subscribed: nil}
12
+ phone = BlueStateDigital::Phone.new {}
13
+ expect(phone.to_hash).to eq(expected_hash)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,234 @@
1
+ [{"tableName":"event_type",
2
+ "tablePrimary":"event_type_id",
3
+ "tableFields":["contribution_page_id",
4
+ "name",
5
+ "description",
6
+ "van_campaign_title",
7
+ "detail_label",
8
+ "detail_text",
9
+ "can_users_create",
10
+ "fixed_title",
11
+ "fixed_day",
12
+ "fixed_tz",
13
+ "fixed_time",
14
+ "is_searchable",
15
+ "host_mailing_addr",
16
+ "contact_phone",
17
+ "can_set_capacity",
18
+ "expir_dt",
19
+ "pledge_show",
20
+ "pledge_source",
21
+ "pledge_subsource",
22
+ "pledge_require",
23
+ "pledge_min",
24
+ "pledge_max",
25
+ "pledge_suggest",
26
+ "shifts_allow",
27
+ "multiple_dates_allow",
28
+ "rsvp_allow",
29
+ "rsvp_allow_reminder_email",
30
+ "rsvp_require_signup",
31
+ "rsvp_disallow_account",
32
+ "rsvp_use_default_email_message",
33
+ "rsvp_allow_host_override_email_message",
34
+ "rsvp_send_confirmation_email",
35
+ "rsvp_reason",
36
+ "rsvp_email_message",
37
+ "rsvp_email_message_html",
38
+ "rsvp_redirect_url",
39
+ "attendee_volunteer_show",
40
+ "attendee_volunteer_message",
41
+ "approval_require",
42
+ "map_marker_storage_key",
43
+ "map_marker_width",
44
+ "map_marker_height",
45
+ "chapter_id",
46
+ "facebook_default_message",
47
+ "twitter_default_message",
48
+ "van_event_type_name",
49
+ "van_program_type_name",
50
+ "sync_to_van",
51
+ "create_dt",
52
+ "create_app",
53
+ "create_user",
54
+ "modified_dt",
55
+ "modified_app",
56
+ "modified_user",
57
+ "status",
58
+ "note"],
59
+ "hooksEnabled":true,
60
+ "event_type_id":"1",
61
+ "contribution_page_id":"1",
62
+ "name":"My first event type",
63
+ "description":"An event type for testing",
64
+ "van_campaign_title":null,
65
+ "detail_label":"",
66
+ "detail_text":"",
67
+ "can_users_create":"0",
68
+ "fixed_title":null,
69
+ "fixed_day":null,
70
+ "fixed_tz":"US\/Eastern",
71
+ "fixed_time":null,
72
+ "is_searchable":"0",
73
+ "host_mailing_addr":"0",
74
+ "contact_phone":"0",
75
+ "can_set_capacity":"0",
76
+ "expir_dt":null,
77
+ "pledge_show":"0",
78
+ "pledge_source":null,
79
+ "pledge_subsource":null,
80
+ "pledge_require":"0",
81
+ "pledge_min":"0",
82
+ "pledge_max":"0",
83
+ "pledge_suggest":"0",
84
+ "shifts_allow":"0",
85
+ "multiple_dates_allow":"0",
86
+ "rsvp_allow":"1",
87
+ "rsvp_allow_reminder_email":"1",
88
+ "rsvp_require_signup":"1",
89
+ "rsvp_disallow_account":"1",
90
+ "rsvp_use_default_email_message":"1",
91
+ "rsvp_allow_host_override_email_message":"0",
92
+ "rsvp_send_confirmation_email":"1",
93
+ "rsvp_reason":"",
94
+ "rsvp_email_message":"",
95
+ "rsvp_email_message_html":null,
96
+ "rsvp_redirect_url":"",
97
+ "attendee_volunteer_show":"0",
98
+ "attendee_volunteer_message":"",
99
+ "approval_require":"0",
100
+ "map_marker_storage_key":null,
101
+ "map_marker_width":null,
102
+ "map_marker_height":null,
103
+ "chapter_id":"1",
104
+ "facebook_default_message":"",
105
+ "twitter_default_message":"",
106
+ "van_event_type_name":null,
107
+ "van_program_type_name":null,
108
+ "sync_to_van":"0",
109
+ "create_dt":"2014-02-04 17:32:08",
110
+ "create_app":null,
111
+ "create_user":null,
112
+ "modified_dt":"2014-02-04 17:32:08",
113
+ "modified_app":null,
114
+ "modified_user":null,
115
+ "status":"1",
116
+ "note":null
117
+ },
118
+ {"tableName":"event_type",
119
+ "tablePrimary":"event_type_id",
120
+ "tableFields":["contribution_page_id",
121
+ "name",
122
+ "description",
123
+ "van_campaign_title",
124
+ "detail_label",
125
+ "detail_text",
126
+ "can_users_create",
127
+ "fixed_title",
128
+ "fixed_day",
129
+ "fixed_tz",
130
+ "fixed_time",
131
+ "is_searchable",
132
+ "host_mailing_addr",
133
+ "contact_phone",
134
+ "can_set_capacity",
135
+ "expir_dt",
136
+ "pledge_show",
137
+ "pledge_source",
138
+ "pledge_subsource",
139
+ "pledge_require",
140
+ "pledge_min",
141
+ "pledge_max",
142
+ "pledge_suggest",
143
+ "shifts_allow",
144
+ "multiple_dates_allow",
145
+ "rsvp_allow",
146
+ "rsvp_allow_reminder_email",
147
+ "rsvp_require_signup",
148
+ "rsvp_disallow_account",
149
+ "rsvp_use_default_email_message",
150
+ "rsvp_allow_host_override_email_message",
151
+ "rsvp_send_confirmation_email",
152
+ "rsvp_reason",
153
+ "rsvp_email_message",
154
+ "rsvp_email_message_html",
155
+ "rsvp_redirect_url",
156
+ "attendee_volunteer_show",
157
+ "attendee_volunteer_message",
158
+ "approval_require",
159
+ "map_marker_storage_key",
160
+ "map_marker_width",
161
+ "map_marker_height",
162
+ "chapter_id",
163
+ "facebook_default_message",
164
+ "twitter_default_message",
165
+ "van_event_type_name",
166
+ "van_program_type_name",
167
+ "sync_to_van",
168
+ "create_dt",
169
+ "create_app",
170
+ "create_user",
171
+ "modified_dt",
172
+ "modified_app",
173
+ "modified_user",
174
+ "status",
175
+ "note"],
176
+ "hooksEnabled":true,
177
+ "event_type_id":"2",
178
+ "contribution_page_id":"1",
179
+ "name":"My second event type",
180
+ "description":"Another event type for testing",
181
+ "van_campaign_title":null,
182
+ "detail_label":"",
183
+ "detail_text":"",
184
+ "can_users_create":"0",
185
+ "fixed_title":null,
186
+ "fixed_day":null,
187
+ "fixed_tz":"US\/Eastern",
188
+ "fixed_time":null,
189
+ "is_searchable":"0",
190
+ "host_mailing_addr":"0",
191
+ "contact_phone":"0",
192
+ "can_set_capacity":"0",
193
+ "expir_dt":null,
194
+ "pledge_show":"0",
195
+ "pledge_source":null,
196
+ "pledge_subsource":null,
197
+ "pledge_require":"0",
198
+ "pledge_min":"0",
199
+ "pledge_max":"0",
200
+ "pledge_suggest":"0",
201
+ "shifts_allow":"0",
202
+ "multiple_dates_allow":"0",
203
+ "rsvp_allow":"1",
204
+ "rsvp_allow_reminder_email":"1",
205
+ "rsvp_require_signup":"1",
206
+ "rsvp_disallow_account":"1",
207
+ "rsvp_use_default_email_message":"1",
208
+ "rsvp_allow_host_override_email_message":"0",
209
+ "rsvp_send_confirmation_email":"1",
210
+ "rsvp_reason":"",
211
+ "rsvp_email_message":"",
212
+ "rsvp_email_message_html":null,
213
+ "rsvp_redirect_url":"",
214
+ "attendee_volunteer_show":"0",
215
+ "attendee_volunteer_message":"",
216
+ "approval_require":"0",
217
+ "map_marker_storage_key":null,
218
+ "map_marker_width":null,
219
+ "map_marker_height":null,
220
+ "chapter_id":"1",
221
+ "facebook_default_message":"",
222
+ "twitter_default_message":"",
223
+ "van_event_type_name":null,
224
+ "van_program_type_name":null,
225
+ "sync_to_van":"0",
226
+ "create_dt":"2014-02-04 17:32:08",
227
+ "create_app":null,
228
+ "create_user":null,
229
+ "modified_dt":"2014-02-04 17:32:08",
230
+ "modified_app":null,
231
+ "modified_user":null,
232
+ "status":"1",
233
+ "note":null
234
+ }]
@@ -0,0 +1,117 @@
1
+ [{"tableName":"event_type",
2
+ "tablePrimary":"event_type_id",
3
+ "tableFields":["contribution_page_id",
4
+ "name",
5
+ "description",
6
+ "van_campaign_title",
7
+ "detail_label",
8
+ "detail_text",
9
+ "can_users_create",
10
+ "fixed_title",
11
+ "fixed_day",
12
+ "fixed_tz",
13
+ "fixed_time",
14
+ "is_searchable",
15
+ "host_mailing_addr",
16
+ "contact_phone",
17
+ "can_set_capacity",
18
+ "expir_dt",
19
+ "pledge_show",
20
+ "pledge_source",
21
+ "pledge_subsource",
22
+ "pledge_require",
23
+ "pledge_min",
24
+ "pledge_max",
25
+ "pledge_suggest",
26
+ "shifts_allow",
27
+ "multiple_dates_allow",
28
+ "rsvp_allow",
29
+ "rsvp_allow_reminder_email",
30
+ "rsvp_require_signup",
31
+ "rsvp_disallow_account",
32
+ "rsvp_use_default_email_message",
33
+ "rsvp_allow_host_override_email_message",
34
+ "rsvp_send_confirmation_email",
35
+ "rsvp_reason",
36
+ "rsvp_email_message",
37
+ "rsvp_email_message_html",
38
+ "rsvp_redirect_url",
39
+ "attendee_volunteer_show",
40
+ "attendee_volunteer_message",
41
+ "approval_require",
42
+ "map_marker_storage_key",
43
+ "map_marker_width",
44
+ "map_marker_height",
45
+ "chapter_id",
46
+ "facebook_default_message",
47
+ "twitter_default_message",
48
+ "van_event_type_name",
49
+ "van_program_type_name",
50
+ "sync_to_van",
51
+ "create_dt",
52
+ "create_app",
53
+ "create_user",
54
+ "modified_dt",
55
+ "modified_app",
56
+ "modified_user",
57
+ "status",
58
+ "note"],
59
+ "hooksEnabled":true,
60
+ "event_type_id":"1",
61
+ "contribution_page_id":"1",
62
+ "name":"My event type",
63
+ "description":"An event type for testing",
64
+ "van_campaign_title":null,
65
+ "detail_label":"",
66
+ "detail_text":"",
67
+ "can_users_create":"0",
68
+ "fixed_title":null,
69
+ "fixed_day":null,
70
+ "fixed_tz":"US\/Eastern",
71
+ "fixed_time":null,
72
+ "is_searchable":"0",
73
+ "host_mailing_addr":"0",
74
+ "contact_phone":"0",
75
+ "can_set_capacity":"0",
76
+ "expir_dt":null,
77
+ "pledge_show":"0",
78
+ "pledge_source":null,
79
+ "pledge_subsource":null,
80
+ "pledge_require":"0",
81
+ "pledge_min":"0",
82
+ "pledge_max":"0",
83
+ "pledge_suggest":"0",
84
+ "shifts_allow":"0",
85
+ "multiple_dates_allow":"0",
86
+ "rsvp_allow":"1",
87
+ "rsvp_allow_reminder_email":"1",
88
+ "rsvp_require_signup":"1",
89
+ "rsvp_disallow_account":"1",
90
+ "rsvp_use_default_email_message":"1",
91
+ "rsvp_allow_host_override_email_message":"0",
92
+ "rsvp_send_confirmation_email":"1",
93
+ "rsvp_reason":"",
94
+ "rsvp_email_message":"",
95
+ "rsvp_email_message_html":null,
96
+ "rsvp_redirect_url":"",
97
+ "attendee_volunteer_show":"0",
98
+ "attendee_volunteer_message":"",
99
+ "approval_require":"0",
100
+ "map_marker_storage_key":null,
101
+ "map_marker_width":null,
102
+ "map_marker_height":null,
103
+ "chapter_id":"1",
104
+ "facebook_default_message":"",
105
+ "twitter_default_message":"",
106
+ "van_event_type_name":null,
107
+ "van_program_type_name":null,
108
+ "sync_to_van":"0",
109
+ "create_dt":"2014-02-04 17:32:08",
110
+ "create_app":null,
111
+ "create_user":null,
112
+ "modified_dt":"2014-02-04 17:32:08",
113
+ "modified_app":null,
114
+ "modified_user":null,
115
+ "status":"1",
116
+ "note":null
117
+ }]