blue_state_digital 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +1 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +3 -0
- data/Gemfile +2 -0
- data/Guardfile +5 -0
- data/LICENSE +24 -0
- data/README.md +123 -0
- data/Rakefile +11 -0
- data/blue_state_digital.gemspec +37 -0
- data/lib/blue_state_digital.rb +32 -0
- data/lib/blue_state_digital/address.rb +28 -0
- data/lib/blue_state_digital/api_data_model.rb +31 -0
- data/lib/blue_state_digital/collection_resource.rb +14 -0
- data/lib/blue_state_digital/connection.rb +119 -0
- data/lib/blue_state_digital/constituent.rb +178 -0
- data/lib/blue_state_digital/constituent_group.rb +151 -0
- data/lib/blue_state_digital/contribution.rb +73 -0
- data/lib/blue_state_digital/dataset.rb +139 -0
- data/lib/blue_state_digital/dataset_map.rb +138 -0
- data/lib/blue_state_digital/email.rb +22 -0
- data/lib/blue_state_digital/email_unsubscribe.rb +11 -0
- data/lib/blue_state_digital/error_middleware.rb +29 -0
- data/lib/blue_state_digital/event.rb +46 -0
- data/lib/blue_state_digital/event_rsvp.rb +17 -0
- data/lib/blue_state_digital/event_type.rb +19 -0
- data/lib/blue_state_digital/phone.rb +20 -0
- data/lib/blue_state_digital/version.rb +3 -0
- data/spec/blue_state_digital/address_spec.rb +25 -0
- data/spec/blue_state_digital/api_data_model_spec.rb +13 -0
- data/spec/blue_state_digital/connection_spec.rb +153 -0
- data/spec/blue_state_digital/constituent_group_spec.rb +269 -0
- data/spec/blue_state_digital/constituent_spec.rb +422 -0
- data/spec/blue_state_digital/contribution_spec.rb +132 -0
- data/spec/blue_state_digital/dataset_map_spec.rb +137 -0
- data/spec/blue_state_digital/dataset_spec.rb +177 -0
- data/spec/blue_state_digital/email_spec.rb +16 -0
- data/spec/blue_state_digital/error_middleware_spec.rb +15 -0
- data/spec/blue_state_digital/event_rsvp_spec.rb +17 -0
- data/spec/blue_state_digital/event_spec.rb +70 -0
- data/spec/blue_state_digital/event_type_spec.rb +51 -0
- data/spec/blue_state_digital/phone_spec.rb +16 -0
- data/spec/fixtures/multiple_event_types.json +234 -0
- data/spec/fixtures/single_event_type.json +117 -0
- data/spec/spec_helper.rb +21 -0
- data/spec/support/matchers/fields.rb +23 -0
- metadata +334 -0
@@ -0,0 +1,269 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BlueStateDigital::ConstituentGroup do
|
4
|
+
before(:each) do
|
5
|
+
@empty_response = <<-xml_string
|
6
|
+
<?xml version="1.0" encoding="utf-8"?>
|
7
|
+
<api>
|
8
|
+
</api>
|
9
|
+
xml_string
|
10
|
+
@empty_response.strip!
|
11
|
+
|
12
|
+
@multiple_cons_groups = <<-xml_string
|
13
|
+
<?xml version="1.0" encoding="utf-8"?>
|
14
|
+
<api>
|
15
|
+
<cons_group id='12' modified_dt="1171861200">
|
16
|
+
<name>First Quarter Donors</name>
|
17
|
+
<slug>q1donors</slug>
|
18
|
+
<description>People who donated in Q1 2007</description>
|
19
|
+
<is_banned>0</is_banned>
|
20
|
+
<create_dt>1168146000</create_dt>
|
21
|
+
<group_type>manual</group_type>
|
22
|
+
<members>162</members>
|
23
|
+
<unique_emails>164</unique_emails>
|
24
|
+
<unique_emails_subscribed>109</unique_emails_subscribed>
|
25
|
+
<count_dt>1213861583</count_dt>
|
26
|
+
</cons_group>
|
27
|
+
<cons_group id='13' modified_dt="1171861200">
|
28
|
+
<name>Second Quarter Donors</name>
|
29
|
+
<slug>q2donors</slug>
|
30
|
+
<description>People who donated in Q1 2007</description>
|
31
|
+
<is_banned>0</is_banned>
|
32
|
+
<create_dt>1168146000</create_dt>
|
33
|
+
<group_type>manual</group_type>
|
34
|
+
<members>162</members>
|
35
|
+
<unique_emails>164</unique_emails>
|
36
|
+
<unique_emails_subscribed>109</unique_emails_subscribed>
|
37
|
+
<count_dt>1213861583</count_dt>
|
38
|
+
</cons_group>
|
39
|
+
</api>
|
40
|
+
xml_string
|
41
|
+
|
42
|
+
@single_cons_groups = <<-xml_string
|
43
|
+
<?xml version="1.0" encoding="utf-8"?>
|
44
|
+
<api>
|
45
|
+
<cons_group id='13' modified_dt="1171861200">
|
46
|
+
<name>First Quarter Donors</name>
|
47
|
+
<slug>q1donors</slug>
|
48
|
+
<description>People who donated in Q1 2007</description>
|
49
|
+
<is_banned>0</is_banned>
|
50
|
+
<create_dt>1168146000</create_dt>
|
51
|
+
<group_type>manual</group_type>
|
52
|
+
<members>162</members>
|
53
|
+
<unique_emails>164</unique_emails>
|
54
|
+
<unique_emails_subscribed>109</unique_emails_subscribed>
|
55
|
+
<count_dt>1213861583</count_dt>
|
56
|
+
</cons_group>
|
57
|
+
</api>
|
58
|
+
xml_string
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
let(:connection) { BlueStateDigital::Connection.new({}) }
|
63
|
+
|
64
|
+
describe ".list_constituent_groups" do
|
65
|
+
it "should return a list of groups" do
|
66
|
+
expect(connection).to receive(:perform_request).with('/cons_group/list_constituent_groups', {}, "GET").and_return(@multiple_cons_groups)
|
67
|
+
groups = connection.constituent_groups.list_constituent_groups
|
68
|
+
expect(groups).to be_a(Array)
|
69
|
+
expect(groups.length).to eq(2)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe ".find_by_id" do
|
74
|
+
it "should do a list comprehension to find a group in the list by id" do
|
75
|
+
expect(connection).to receive(:perform_request).with('/cons_group/get_constituent_group', {cons_group_id: 13}, "GET").and_return(@single_cons_groups)
|
76
|
+
group = connection.constituent_groups.find_by_id(13)
|
77
|
+
expect(group).to be_a(BlueStateDigital::ConstituentGroup)
|
78
|
+
expect(group.id).to eq('13')
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should handle an empty result" do
|
82
|
+
expect(connection).to receive(:perform_request).with('/cons_group/get_constituent_group', {cons_group_id: 13}, "GET").and_return(@empty_response)
|
83
|
+
group = connection.constituent_groups.find_by_id(13)
|
84
|
+
expect(group).to be_nil
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe ".delete_constituent_groups" do
|
89
|
+
it "should handle an array of integers" do
|
90
|
+
expect(connection).to receive(:perform_request).with('/cons_group/delete_constituent_groups', {:cons_group_ids=>"2,3"}, "POST").and_return("deferred_id")
|
91
|
+
expect(connection).to receive(:perform_request).with('/get_deferred_results', {deferred_id: "deferred_id"}, "GET").and_return(true)
|
92
|
+
connection.constituent_groups.delete_constituent_groups([2,3])
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should handle a single integer" do
|
96
|
+
expect(connection).to receive(:perform_request).with('/cons_group/delete_constituent_groups', {:cons_group_ids=>"2"}, "POST").and_return("deferred_id")
|
97
|
+
expect(connection).to receive(:perform_request).with('/get_deferred_results', {deferred_id: "deferred_id"}, "GET").and_return(true)
|
98
|
+
|
99
|
+
connection.constituent_groups.delete_constituent_groups(2)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe ".find_or_create" do
|
104
|
+
before(:all) do
|
105
|
+
@timestamp = Time.now.to_i
|
106
|
+
|
107
|
+
@new_group_xml = <<-xml_string
|
108
|
+
<?xml version="1.0" encoding="utf-8"?>
|
109
|
+
<api>
|
110
|
+
<cons_group>
|
111
|
+
<name>Environment</name>
|
112
|
+
<slug>environment</slug>
|
113
|
+
<description>Environment Group</description>
|
114
|
+
<group_type>manual</group_type>
|
115
|
+
<create_dt>#{@timestamp}</create_dt>
|
116
|
+
</cons_group>
|
117
|
+
</api>
|
118
|
+
xml_string
|
119
|
+
@new_group_xml.gsub!(/\n/, "")
|
120
|
+
|
121
|
+
@exists_response = <<-xml_string
|
122
|
+
<?xml version="1.0" encoding="utf-8"?>
|
123
|
+
<api>
|
124
|
+
<cons_group id='12'>
|
125
|
+
</cons_group>
|
126
|
+
</api>
|
127
|
+
xml_string
|
128
|
+
@exists_response.strip!
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should create a new group" do
|
132
|
+
attrs = { name: "Environment", slug: "environment", description: "Environment Group", group_type: "manual", create_dt: @timestamp }
|
133
|
+
|
134
|
+
|
135
|
+
expect(connection).to receive(:perform_request).with('/cons_group/get_constituent_group_by_slug', {slug:attrs[:slug]}, "GET") { @empty_response }
|
136
|
+
expect(connection).to receive(:perform_request).with('/cons_group/add_constituent_groups', {}, "POST", @new_group_xml) { @exists_response }
|
137
|
+
|
138
|
+
cons_group = connection.constituent_groups.find_or_create(attrs)
|
139
|
+
expect(cons_group.id).to eq('12')
|
140
|
+
end
|
141
|
+
|
142
|
+
|
143
|
+
it "should not create group if it already exists" do
|
144
|
+
attrs = { name: "Environment", slug: "environment", description: "Environment Group", group_type: "manual", create_dt: @timestamp }
|
145
|
+
|
146
|
+
expect(connection).to receive(:perform_request).with('/cons_group/get_constituent_group_by_slug', {slug:attrs[:slug]}, "GET") { @exists_response }
|
147
|
+
expect(connection).not_to receive(:perform_request).with('/cons_group/add_constituent_groups', {}, "POST", @new_group_xml)
|
148
|
+
|
149
|
+
cons_group = connection.constituent_groups.find_or_create(attrs)
|
150
|
+
expect(cons_group.id).to eq('12')
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
describe ".from_response" do
|
155
|
+
describe "a single group" do
|
156
|
+
before(:each) do
|
157
|
+
@response = <<-xml_string
|
158
|
+
<?xml version="1.0" encoding="utf-8"?>
|
159
|
+
<api>
|
160
|
+
<cons_group id='12' modified_dt="1171861200">
|
161
|
+
<name>First Quarter Donors</name>
|
162
|
+
<slug>q1donors</slug>
|
163
|
+
<description>People who donated in Q1 2007</description>
|
164
|
+
<is_banned>0</is_banned>
|
165
|
+
<create_dt>1168146000</create_dt>
|
166
|
+
<group_type>manual</group_type>
|
167
|
+
<members>162</members>
|
168
|
+
<unique_emails>164</unique_emails>
|
169
|
+
<unique_emails_subscribed>109</unique_emails_subscribed>
|
170
|
+
<count_dt>1213861583</count_dt>
|
171
|
+
</cons_group>
|
172
|
+
</api>
|
173
|
+
xml_string
|
174
|
+
end
|
175
|
+
|
176
|
+
it "should create a group from an xml string" do
|
177
|
+
response = connection.constituent_groups.send(:from_response, @response)
|
178
|
+
expect(response.id).to eq("12")
|
179
|
+
expect(response.slug).to eq('q1donors')
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
describe "multiple groups" do
|
184
|
+
it "should create an array of groups from an xml string" do
|
185
|
+
response = connection.constituent_groups.send(:from_response, @multiple_cons_groups)
|
186
|
+
expect(response).to be_a(Array)
|
187
|
+
first = response.first
|
188
|
+
expect(first.id).to eq("12")
|
189
|
+
expect(first.slug).to eq('q1donors')
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
[[:add, 'add_cons_ids_to_group'], [:remove, 'remove_cons_ids_from_group']].each do |(operation, method)|
|
195
|
+
# operation, method = method_under_test.key, method_under_test.value
|
196
|
+
|
197
|
+
it "should #{operation} constituent ids to group" do
|
198
|
+
cons_group_id = "12"
|
199
|
+
cons_ids = ["1", "2"]
|
200
|
+
post_params = { cons_group_id: cons_group_id, cons_ids: "1,2" }
|
201
|
+
|
202
|
+
expect(connection).to receive(:perform_request).with("/cons_group/#{method}", post_params, "POST").and_return("deferred_id")
|
203
|
+
expect(connection).to receive(:perform_request).with('/get_deferred_results', {deferred_id: "deferred_id"}, "GET").and_return(true)
|
204
|
+
|
205
|
+
connection.constituent_groups.send(method.to_sym, cons_group_id, cons_ids)
|
206
|
+
end
|
207
|
+
|
208
|
+
it "should batch on #{operation} constituent ids to group" do
|
209
|
+
stub_const('BlueStateDigital::ConstituentGroups::CONSTITUENTS_BATCH_SIZE', 2)
|
210
|
+
|
211
|
+
cons_group_id = "12"
|
212
|
+
cons_ids = ["1", "2", "3", "4"]
|
213
|
+
|
214
|
+
expect(connection).to receive(:perform_request).with("/cons_group/#{method}", { cons_group_id: cons_group_id, cons_ids: "1,2" }, "POST").and_return("deferred_id")
|
215
|
+
expect(connection).to receive(:perform_request).with("/cons_group/#{method}", { cons_group_id: cons_group_id, cons_ids: "3,4" }, "POST").and_return("deferred_id")
|
216
|
+
expect(connection).to receive(:perform_request).with('/get_deferred_results', {deferred_id: "deferred_id"}, "GET").twice.and_return(true)
|
217
|
+
|
218
|
+
connection.constituent_groups.send(method.to_sym, cons_group_id, cons_ids)
|
219
|
+
end
|
220
|
+
|
221
|
+
it "should not wait for the result if told not to" do
|
222
|
+
cons_group_id = "12"
|
223
|
+
cons_ids = ["1", "2"]
|
224
|
+
post_params = { cons_group_id: cons_group_id, cons_ids: "1,2" }
|
225
|
+
|
226
|
+
expect(connection).to receive(:perform_request).with("/cons_group/#{method}", post_params, "POST").and_return("deferred_id")
|
227
|
+
expect(connection).not_to receive(:perform_request).with('/get_deferred_results', {deferred_id: "deferred_id"}, "GET")
|
228
|
+
|
229
|
+
connection.constituent_groups.send(method.to_sym, cons_group_id, cons_ids, {wait_for_result: false})
|
230
|
+
end
|
231
|
+
|
232
|
+
it "should #{operation} a single constituent id to a group" do
|
233
|
+
cons_group_id = "12"
|
234
|
+
cons_ids = ["1"]
|
235
|
+
post_params = { cons_group_id: cons_group_id, cons_ids: "1" }
|
236
|
+
|
237
|
+
expect(connection).to receive(:perform_request).with("/cons_group/#{method}", post_params, "POST").and_return("deferred_id")
|
238
|
+
expect(connection).to receive(:perform_request).with('/get_deferred_results', {deferred_id: "deferred_id"}, "GET").and_return(true)
|
239
|
+
|
240
|
+
connection.constituent_groups.send(method.to_sym, cons_group_id, cons_ids)
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
|
245
|
+
it "should rename the constituent group" do
|
246
|
+
expect(connection).to receive(:perform_request).with('/cons_group/rename_group', {cons_group_id: "1", new_name: "foo"}, "POST").and_return("")
|
247
|
+
connection.constituent_groups.rename_group("1", "foo")
|
248
|
+
end
|
249
|
+
|
250
|
+
it "should allow replace_constituent_group!" do
|
251
|
+
old_cons_group_id = 15
|
252
|
+
new_cons_group_id = 1
|
253
|
+
attrs = { name: "Environment", slug: "environment", description: "Environment Group", group_type: "manual", create_dt: @timestamp }
|
254
|
+
new_group = double
|
255
|
+
allow(new_group).to receive(:id).and_return(new_cons_group_id)
|
256
|
+
|
257
|
+
old_group = double
|
258
|
+
allow(old_group).to receive(:id).and_return(old_cons_group_id)
|
259
|
+
|
260
|
+
|
261
|
+
expect(connection.constituent_groups).to receive(:get_constituent_group).with(old_cons_group_id).and_return( old_group )
|
262
|
+
expect(connection.constituent_groups).to receive(:find_or_create).with(attrs).and_return( new_group )
|
263
|
+
expect(connection.constituent_groups).to receive(:get_cons_ids_for_group).with(old_cons_group_id).and_return( [1, 2, 3] )
|
264
|
+
expect(connection.constituent_groups).to receive(:add_cons_ids_to_group).with(new_cons_group_id, [1, 2, 3] )
|
265
|
+
expect(connection.constituent_groups).to receive(:delete_constituent_groups).with( old_cons_group_id )
|
266
|
+
|
267
|
+
expect(connection.constituent_groups.replace_constituent_group!(old_cons_group_id, attrs)).to eq(new_group)
|
268
|
+
end
|
269
|
+
end
|
@@ -0,0 +1,422 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BlueStateDigital::Constituent do
|
4
|
+
describe ".to_xml" do
|
5
|
+
before(:each) do
|
6
|
+
@cons = BlueStateDigital::Constituent.new({})
|
7
|
+
end
|
8
|
+
|
9
|
+
context "with addresses" do
|
10
|
+
let(:expected_result) do
|
11
|
+
<<-xml_string.split("\n").map(&:strip).join
|
12
|
+
<?xml version="1.0" encoding="utf-8"?>
|
13
|
+
<api>
|
14
|
+
<cons>
|
15
|
+
<cons_addr>
|
16
|
+
<addr1>one</addr1>
|
17
|
+
</cons_addr>
|
18
|
+
</cons>
|
19
|
+
</api>
|
20
|
+
xml_string
|
21
|
+
end
|
22
|
+
it "should allow constituent addresses entries as hashes" do
|
23
|
+
constituent = BlueStateDigital::Constituent.new addresses: [{addr1: 'one'}]
|
24
|
+
expect(constituent.to_xml).to eq(expected_result)
|
25
|
+
end
|
26
|
+
it "should allow constituent addresses entries as BlueStateDigital::Addresses" do
|
27
|
+
constituent = BlueStateDigital::Constituent.new addresses: [BlueStateDigital::Address.new(addr1: 'one')]
|
28
|
+
expect(constituent.to_xml).to eq(expected_result)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
context "with emails" do
|
34
|
+
let(:expected_result) do
|
35
|
+
<<-xml_string.split("\n").map(&:strip).join
|
36
|
+
<?xml version="1.0" encoding="utf-8"?>
|
37
|
+
<api>
|
38
|
+
<cons>
|
39
|
+
<cons_email>
|
40
|
+
<email>one@two.com</email>
|
41
|
+
</cons_email>
|
42
|
+
</cons>
|
43
|
+
</api>
|
44
|
+
xml_string
|
45
|
+
end
|
46
|
+
it "should allow constituent addresses entries as hashes" do
|
47
|
+
constituent = BlueStateDigital::Constituent.new emails: [{email: 'one@two.com'}]
|
48
|
+
expect(constituent.to_xml).to eq(expected_result)
|
49
|
+
end
|
50
|
+
it "should allow constituent addresses entries as BlueStateDigital::Addresses" do
|
51
|
+
constituent = BlueStateDigital::Constituent.new emails: [BlueStateDigital::Email.new(email: 'one@two.com')]
|
52
|
+
expect(constituent.to_xml).to eq(expected_result)
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
context "with phone numbers" do
|
58
|
+
let(:expected_result) do
|
59
|
+
<<-xml_string.split("\n").map(&:strip).join
|
60
|
+
<?xml version="1.0" encoding="utf-8"?>
|
61
|
+
<api>
|
62
|
+
<cons>
|
63
|
+
<cons_phone>
|
64
|
+
<phone>123321123</phone>
|
65
|
+
</cons_phone>
|
66
|
+
</cons>
|
67
|
+
</api>
|
68
|
+
xml_string
|
69
|
+
end
|
70
|
+
it "should allow constituent addresses entries as hashes" do
|
71
|
+
constituent = BlueStateDigital::Constituent.new phones: [{phone: '123321123'}]
|
72
|
+
expect(constituent.to_xml).to eq(expected_result)
|
73
|
+
end
|
74
|
+
it "should allow constituent addresses entries as BlueStateDigital::Addresses" do
|
75
|
+
constituent = BlueStateDigital::Constituent.new phones: [BlueStateDigital::Phone.new(phone: '123321123')]
|
76
|
+
expect(constituent.to_xml).to eq(expected_result)
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
[:firstname,:lastname,:is_banned,:create_dt,:birth_dt,:gender].each do |param|
|
82
|
+
describe "with #{param}" do
|
83
|
+
let (:expected_result) do
|
84
|
+
<<-xml_string.split("\n").map(&:strip).join
|
85
|
+
<?xml version="1.0" encoding="utf-8"?>
|
86
|
+
<api>
|
87
|
+
<cons>
|
88
|
+
<#{param.to_s}>#{param.to_s}_value</#{param.to_s}>
|
89
|
+
</cons>
|
90
|
+
</api>
|
91
|
+
xml_string
|
92
|
+
end
|
93
|
+
it "should be present as #{param.to_s} tag in cons tag" do
|
94
|
+
constituent = BlueStateDigital::Constituent.new
|
95
|
+
eval("constituent.#{param.to_s}='#{param.to_s}_value'")
|
96
|
+
expect(constituent.to_xml).to eq(expected_result)
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
let(:connection) { BlueStateDigital::Connection.new({}) }
|
104
|
+
|
105
|
+
describe "Get Constituents" do
|
106
|
+
before(:each) do
|
107
|
+
@single_constituent = <<-xml_string
|
108
|
+
<?xml version="1.0" encoding="utf-8"?>
|
109
|
+
<api>
|
110
|
+
<cons id="4382" modified_dt="1171861200">
|
111
|
+
<guid>ygdFPkyEdomzBhWEFZGREys</guid>
|
112
|
+
<firstname>Bob</firstname>
|
113
|
+
<middlename>Reginald</middlename>
|
114
|
+
<lastname>Smith</lastname>
|
115
|
+
<has_account>1</has_account>
|
116
|
+
<is_banned>0</is_banned>
|
117
|
+
<create_dt>1168146000</create_dt>
|
118
|
+
<suffix>III</suffix>
|
119
|
+
<prefix>Mr</prefix>
|
120
|
+
<gender>M</gender>
|
121
|
+
</cons>
|
122
|
+
</api>
|
123
|
+
xml_string
|
124
|
+
|
125
|
+
@constituent_with_group = <<-xml_string
|
126
|
+
<?xml version="1.0" encoding="utf-8"?>
|
127
|
+
<api>
|
128
|
+
<cons id="4382" modified_dt="1171861200">
|
129
|
+
<guid>ygdFPkyEdomzBhWEFZGREys</guid>
|
130
|
+
<firstname>Bob</firstname>
|
131
|
+
<lastname>Smith</lastname>
|
132
|
+
<has_account>1</has_account>
|
133
|
+
<is_banned>0</is_banned>
|
134
|
+
<create_dt>1168146000</create_dt>
|
135
|
+
|
136
|
+
<cons_group id="41" modified_dt="1163196031" />
|
137
|
+
</cons>
|
138
|
+
</api>
|
139
|
+
xml_string
|
140
|
+
|
141
|
+
@constituent_with_addr = <<-xml_string
|
142
|
+
<?xml version="1.0" encoding="utf-8"?>
|
143
|
+
<api>
|
144
|
+
<cons id="4382" modified_dt="1171861200">
|
145
|
+
<guid>ygdFPkyEdomzBhWEFZGREys</guid>
|
146
|
+
<firstname>Bob</firstname>
|
147
|
+
<lastname>Smith</lastname>
|
148
|
+
<has_account>1</has_account>
|
149
|
+
<is_banned>0</is_banned>
|
150
|
+
<create_dt>1168146000</create_dt>
|
151
|
+
<cons_addr id="43" modified_dt="1355800948">
|
152
|
+
<addr1>yyy2</addr1>
|
153
|
+
<addr2>yyy3</addr2>
|
154
|
+
<city>here</city>
|
155
|
+
<state_cd>2323</state_cd>
|
156
|
+
<zip>00323</zip>
|
157
|
+
<country></country>
|
158
|
+
<latitude>0.000000</latitude>
|
159
|
+
<longitude>0.000000</longitude>
|
160
|
+
<is_primary>0</is_primary>
|
161
|
+
<cons_addr_type_id>0</cons_addr_type_id>
|
162
|
+
</cons_addr>
|
163
|
+
<cons_addr id="42" modified_dt="1355800946">
|
164
|
+
<addr1>xxx1</addr1>
|
165
|
+
<addr2>xxx2</addr2>
|
166
|
+
<city>Helsinki</city>
|
167
|
+
<state_cd></state_cd>
|
168
|
+
<zip>12345</zip>
|
169
|
+
<country>AM</country>
|
170
|
+
<latitude>42.810059</latitude>
|
171
|
+
<longitude>-73.951050</longitude>
|
172
|
+
<is_primary>1</is_primary>
|
173
|
+
<cons_addr_type_id>0</cons_addr_type_id>
|
174
|
+
</cons_addr>
|
175
|
+
</cons>
|
176
|
+
</api>
|
177
|
+
xml_string
|
178
|
+
|
179
|
+
@constituent_with_emails = <<-xml_string
|
180
|
+
<?xml version="1.0" encoding="utf-8"?>
|
181
|
+
<api>
|
182
|
+
<cons id="4382" modified_dt="1171861200">
|
183
|
+
<guid>ygdFPkyEdomzBhWEFZGREys</guid>
|
184
|
+
<firstname>Bob</firstname>
|
185
|
+
<lastname>Smith</lastname>
|
186
|
+
<has_account>1</has_account>
|
187
|
+
<is_banned>0</is_banned>
|
188
|
+
<create_dt>1168146000</create_dt>
|
189
|
+
|
190
|
+
<cons_email id="35" modified_dt="1355796381">
|
191
|
+
<email>gil+punky1@thoughtworks.com</email>
|
192
|
+
<email_type>personal</email_type>
|
193
|
+
<is_subscribed>1</is_subscribed>
|
194
|
+
<is_primary>1</is_primary>
|
195
|
+
</cons_email>
|
196
|
+
<cons_email id="36" modified_dt="1355796381">
|
197
|
+
<email>fred@thoughtworks.com</email>
|
198
|
+
<email_type>internal</email_type>
|
199
|
+
<is_subscribed>0</is_subscribed>
|
200
|
+
<is_primary>0</is_primary>
|
201
|
+
</cons_email>
|
202
|
+
</cons>
|
203
|
+
</api>
|
204
|
+
xml_string
|
205
|
+
|
206
|
+
@constituent_with_groups = <<-xml_string
|
207
|
+
<?xml version="1.0" encoding="utf-8"?>
|
208
|
+
<api>
|
209
|
+
<cons id="4382" modified_dt="1171861200">
|
210
|
+
<guid>ygdFPkyEdomzBhWEFZGREys</guid>
|
211
|
+
<firstname>Bob</firstname>
|
212
|
+
<lastname>Smith</lastname>
|
213
|
+
<has_account>1</has_account>
|
214
|
+
<is_banned>0</is_banned>
|
215
|
+
<create_dt>1168146000</create_dt>
|
216
|
+
|
217
|
+
<cons_group id="17" modified_dt="1168146011"/>
|
218
|
+
<cons_group id="41" modified_dt="1163196031" />
|
219
|
+
</cons>
|
220
|
+
</api>
|
221
|
+
xml_string
|
222
|
+
|
223
|
+
@multiple_constituents = <<-xml_string
|
224
|
+
<?xml version="1.0" encoding="utf-8"?>
|
225
|
+
<api>
|
226
|
+
<cons id="4382" modified_dt="1171861200">
|
227
|
+
<guid>ygdFPkyEdomzBhWEFZGREys</guid>
|
228
|
+
<firstname>Bob</firstname>
|
229
|
+
<middlename>Reginald</middlename>
|
230
|
+
<lastname>Smith</lastname>
|
231
|
+
<has_account>1</has_account>
|
232
|
+
<is_banned>0</is_banned>
|
233
|
+
<create_dt>1168146000</create_dt>
|
234
|
+
<suffix>III</suffix>
|
235
|
+
<prefix>Mr</prefix>
|
236
|
+
<gender>M</gender>
|
237
|
+
</cons>
|
238
|
+
|
239
|
+
<cons id="4381" modified_dt="1171861200">
|
240
|
+
<guid>ygdFPkyEdomzBhWEFZGREys</guid>
|
241
|
+
<firstname>Susan</firstname>
|
242
|
+
<middlename>Reginald</middlename>
|
243
|
+
<lastname>Smith</lastname>
|
244
|
+
<has_account>1</has_account>
|
245
|
+
<is_banned>0</is_banned>
|
246
|
+
<create_dt>1168146000</create_dt>
|
247
|
+
<suffix></suffix>
|
248
|
+
<prefix>Mrs</prefix>
|
249
|
+
<gender>F</gender>
|
250
|
+
</cons>
|
251
|
+
</api>
|
252
|
+
xml_string
|
253
|
+
end
|
254
|
+
|
255
|
+
describe ".get_constituents_by_email" do
|
256
|
+
it "should make a filtered constituents query" do
|
257
|
+
expect(connection).to receive(:perform_request).with('/cons/get_constituents', {:filter=>"email=george@washington.com", :bundles => 'cons_group'}, "GET").and_return("deferred_id")
|
258
|
+
expect(connection).to receive(:perform_request).with('/get_deferred_results', {deferred_id: "deferred_id"}, "GET").and_return(@single_constituent)
|
259
|
+
response = connection.constituents.get_constituents_by_email("george@washington.com").first
|
260
|
+
expect(response.id).to eq("4382")
|
261
|
+
expect(response.firstname).to eq('Bob')
|
262
|
+
end
|
263
|
+
|
264
|
+
it "should return constituents' details based on bundles" do
|
265
|
+
bundles = 'cons_addr'
|
266
|
+
expect(connection).to receive(:perform_request).with('/cons/get_constituents', {:filter=>"email=george@washington.com", :bundles => bundles}, "GET").and_return("deferred_id")
|
267
|
+
expect(connection).to receive(:perform_request).with('/get_deferred_results', {deferred_id: "deferred_id"}, "GET").and_return(@constituent_with_addr)
|
268
|
+
response = connection.constituents.get_constituents_by_email("george@washington.com", ['cons_addr']).first
|
269
|
+
response.addresses[0].addr1 == "aaa1"
|
270
|
+
response.addresses[0].addr2 == "aaa2"
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
describe ".get_constituents_by_id" do
|
275
|
+
it "should return a constituent" do
|
276
|
+
expect(connection).to receive(:perform_request).with('/cons/get_constituents_by_id', {:cons_ids=>"23", :bundles => 'cons_group'}, "GET").and_return(@single_constituent)
|
277
|
+
response = connection.constituents.get_constituents_by_id("23").first
|
278
|
+
expect(response.id).to eq("4382")
|
279
|
+
expect(response.firstname).to eq('Bob')
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
describe ".from_response" do
|
284
|
+
it "should set connection in generated constituents" do
|
285
|
+
response = connection.constituents.send(:from_response, @single_constituent)
|
286
|
+
expect(response).to be_a(Array)
|
287
|
+
expect(response.size).to eq(1)
|
288
|
+
expect(response.first.connection).to eq(connection)
|
289
|
+
end
|
290
|
+
|
291
|
+
it "should create an array of constituents from a response that contains multiple constituents" do
|
292
|
+
response = connection.constituents.send(:from_response, @multiple_constituents)
|
293
|
+
expect(response).to be_a(Array)
|
294
|
+
first = response.first
|
295
|
+
expect(first.id).to eq("4382")
|
296
|
+
expect(first.firstname).to eq('Bob')
|
297
|
+
end
|
298
|
+
|
299
|
+
it "should create an array of single constituent when only one is supplied" do
|
300
|
+
response = connection.constituents.send(:from_response, @single_constituent)
|
301
|
+
expect(response).to be_a(Array)
|
302
|
+
expect(response.size).to eq(1)
|
303
|
+
expect(response.first.id).to eq("4382")
|
304
|
+
expect(response.first.firstname).to eq('Bob')
|
305
|
+
expect(response.first.gender).to eq('M')
|
306
|
+
end
|
307
|
+
|
308
|
+
it "should handle constituent group membership" do
|
309
|
+
response = connection.constituents.send(:from_response, @constituent_with_groups).first
|
310
|
+
expect(response.id).to eq('4382')
|
311
|
+
expect(response.group_ids).to eq(["17", "41"])
|
312
|
+
end
|
313
|
+
|
314
|
+
it "should handle single constituent group membership" do
|
315
|
+
response = connection.constituents.send(:from_response, @constituent_with_group).first
|
316
|
+
expect(response.id).to eq('4382')
|
317
|
+
expect(response.group_ids).to eq(["41"])
|
318
|
+
end
|
319
|
+
|
320
|
+
it "Should handle constituent addresses" do
|
321
|
+
response = connection.constituents.send(:from_response, @constituent_with_addr).first
|
322
|
+
expect(response.addresses.size).to eq(2)
|
323
|
+
expect(response.addresses[0]).to be_a BlueStateDigital::Address
|
324
|
+
expect(response.addresses[0].addr1).to eq("yyy2")
|
325
|
+
expect(response.addresses[0].addr2).to eq("yyy3")
|
326
|
+
|
327
|
+
expect(response.addresses[1]).to be_a BlueStateDigital::Address
|
328
|
+
expect(response.addresses[1].addr1).to eq("xxx1")
|
329
|
+
expect(response.addresses[1].addr2).to eq("xxx2")
|
330
|
+
end
|
331
|
+
|
332
|
+
it "Should handle constituent email addresses" do
|
333
|
+
response = connection.constituents.send(:from_response, @constituent_with_emails).first
|
334
|
+
expect(response.emails.size).to eq(2)
|
335
|
+
expect(response.emails[0]).to be_a BlueStateDigital::Email
|
336
|
+
expect(response.emails[0].email).to eq("gil+punky1@thoughtworks.com")
|
337
|
+
expect(response.emails[0].email_type).to eq("personal")
|
338
|
+
expect(response.emails[0].is_subscribed).to eq("1")
|
339
|
+
expect(response.emails[0].is_primary).to eq("1")
|
340
|
+
|
341
|
+
expect(response.emails[1]).to be_a BlueStateDigital::Email
|
342
|
+
expect(response.emails[1].email).to eq("fred@thoughtworks.com")
|
343
|
+
expect(response.emails[1].email_type).to eq("internal")
|
344
|
+
expect(response.emails[1].is_subscribed).to eq("0")
|
345
|
+
expect(response.emails[1].is_primary).to eq("0")
|
346
|
+
end
|
347
|
+
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
describe "delete_constituents_by_id" do
|
352
|
+
it "should handle an array of integers" do
|
353
|
+
expect(connection).to receive(:perform_request).with('/cons/delete_constituents_by_id', {:cons_ids=>"2,3"}, "POST")
|
354
|
+
connection.constituents.delete_constituents_by_id([2,3])
|
355
|
+
end
|
356
|
+
|
357
|
+
it "should handle a single integer" do
|
358
|
+
expect(connection).to receive(:perform_request).with('/cons/delete_constituents_by_id', {:cons_ids=>"2"}, "POST")
|
359
|
+
connection.constituents.delete_constituents_by_id(2)
|
360
|
+
end
|
361
|
+
end
|
362
|
+
it "should set constituent data" do
|
363
|
+
timestamp = Time.now.to_i
|
364
|
+
|
365
|
+
data = {
|
366
|
+
id: 'id',
|
367
|
+
firstname: 'First',
|
368
|
+
lastname: 'Last',
|
369
|
+
is_banned: 0,
|
370
|
+
create_dt: timestamp,
|
371
|
+
emails: [{ email: "email@email.com", email_type: "work", is_subscribed: 1, is_primary: 1 }],
|
372
|
+
groups: [3, 5],
|
373
|
+
connection: connection
|
374
|
+
}
|
375
|
+
|
376
|
+
input = %q{<?xml version="1.0" encoding="utf-8"?>}
|
377
|
+
input << "<api>"
|
378
|
+
input << "<cons id=\"id\">"
|
379
|
+
input << "<firstname>First</firstname>"
|
380
|
+
input << "<lastname>Last</lastname>"
|
381
|
+
input << "<is_banned>0</is_banned>"
|
382
|
+
input << "<create_dt>#{timestamp}</create_dt>"
|
383
|
+
input << "<cons_email>"
|
384
|
+
input << "<email>email@email.com</email>"
|
385
|
+
input << "<email_type>work</email_type>"
|
386
|
+
input << "<is_subscribed>1</is_subscribed>"
|
387
|
+
input << "<is_primary>1</is_primary>"
|
388
|
+
input << "</cons_email>"
|
389
|
+
input << "<cons_group id=\"3\"/>"
|
390
|
+
input << "<cons_group id=\"5\"/>"
|
391
|
+
input << "</cons>"
|
392
|
+
input << "</api>"
|
393
|
+
|
394
|
+
output = %q{<?xml version="1.0" encoding="utf-8"?>}
|
395
|
+
output << "<api>"
|
396
|
+
output << "<cons is_new='1' id='329'>"
|
397
|
+
output << "</cons>"
|
398
|
+
output << "</api>"
|
399
|
+
|
400
|
+
expect(connection).to receive(:perform_request).with('/cons/set_constituent_data', {}, "POST", input) { output }
|
401
|
+
|
402
|
+
cons_data = BlueStateDigital::Constituent.new(data)
|
403
|
+
cons_data.save
|
404
|
+
expect(cons_data.id).to eq('329')
|
405
|
+
expect(cons_data.is_new).to eq('1')
|
406
|
+
expect(cons_data.is_new?).to be_truthy
|
407
|
+
end
|
408
|
+
|
409
|
+
describe "#to_xml" do
|
410
|
+
it "should convert a constituent hash to xml" do
|
411
|
+
cons = BlueStateDigital::Constituent.new ({
|
412
|
+
firstname: 'George',
|
413
|
+
lastname: 'Washington',
|
414
|
+
create_dt: Time.now.to_i,
|
415
|
+
emails: [{ email: 'george@washington.com', is_subscribed: 1}],
|
416
|
+
addresses: [{ country: 'US', zip: '20001', is_primary: 1}],
|
417
|
+
phones: [{phone: '123456789', phone_type: 'unknown'}]
|
418
|
+
})
|
419
|
+
expect(cons.to_xml).not_to be_nil
|
420
|
+
end
|
421
|
+
end
|
422
|
+
end
|