blue_state_digital 0.6.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.
- 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,132 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BlueStateDigital::Contribution do
|
4
|
+
let(:attributes) {
|
5
|
+
{
|
6
|
+
external_id: 'GUID_1234',
|
7
|
+
firstname: 'carlos',
|
8
|
+
lastname: 'the jackal',
|
9
|
+
transaction_amt: 1.0,
|
10
|
+
transaction_dt: '2012-12-31 23:59:59',
|
11
|
+
cc_type_cd: 'vs'
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
15
|
+
it { is_expected.to have_fields(
|
16
|
+
:external_id,
|
17
|
+
:prefix,:firstname,:middlename,:lastname,:suffix,
|
18
|
+
:transaction_dt,:transaction_amt,:cc_type_cd,:gateway_transaction_id,
|
19
|
+
:contribution_page_id,:stg_contribution_recurring_id,:contribution_page_slug,
|
20
|
+
:outreach_page_id,:source,:opt_compliance,
|
21
|
+
:addr1,:addr2,:city,:state_cd,:zip,:country,
|
22
|
+
:phone,:email,
|
23
|
+
:employer,:occupation,
|
24
|
+
:custom_fields
|
25
|
+
) }
|
26
|
+
|
27
|
+
describe 'as_json' do
|
28
|
+
let(:connection) { double }
|
29
|
+
|
30
|
+
it 'should include contribution_page_id and contribution_page_slug if they are set' do
|
31
|
+
contribution = BlueStateDigital::Contribution.new(attributes.merge({ connection: connection, contribution_page_slug: 'donate-here-12', contribution_page_id: 4 }))
|
32
|
+
expect(contribution.as_json).to include('contribution_page_id')
|
33
|
+
expect(contribution.as_json).to include('contribution_page_slug')
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should not include contribution_page_id and contribution_page_slug if they are not set' do
|
37
|
+
contribution = BlueStateDigital::Contribution.new(attributes.merge({ connection: connection }))
|
38
|
+
expect(contribution.as_json).not_to include('contribution_page_id')
|
39
|
+
expect(contribution.as_json).not_to include('contribution_page_slug')
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe 'save' do
|
44
|
+
let(:connection) { double }
|
45
|
+
let(:contribution) { BlueStateDigital::Contribution.new(attributes.merge({ connection: connection })) }
|
46
|
+
|
47
|
+
before :each do
|
48
|
+
expect(connection)
|
49
|
+
.to receive(:perform_request)
|
50
|
+
.with(
|
51
|
+
'/contribution/add_external_contribution',
|
52
|
+
{accept: 'application/json'},
|
53
|
+
'POST',
|
54
|
+
[contribution].to_json
|
55
|
+
)
|
56
|
+
.and_return(response)
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'successful' do
|
60
|
+
let(:response) {
|
61
|
+
{
|
62
|
+
'summary'=> {
|
63
|
+
'sucesses'=> 1,
|
64
|
+
'failures'=> 0,
|
65
|
+
'missing_ids'=> 0
|
66
|
+
},
|
67
|
+
'errors'=> {
|
68
|
+
}
|
69
|
+
}.to_json
|
70
|
+
}
|
71
|
+
|
72
|
+
it "should perform API request" do
|
73
|
+
saved_contribution = contribution.save
|
74
|
+
expect(saved_contribution).not_to be_nil
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'failure' do
|
79
|
+
context 'bad request' do
|
80
|
+
let(:response) { 'Method add_external_contribution expects a JSON array.' }
|
81
|
+
it "should raise error" do
|
82
|
+
expect { contribution.save }.to raise_error(
|
83
|
+
BlueStateDigital::Contribution::ContributionSaveFailureException,
|
84
|
+
/Method add_external_contribution expects a JSON array/m
|
85
|
+
)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
context 'missing ID' do
|
89
|
+
let(:response) {
|
90
|
+
{
|
91
|
+
'summary'=> {
|
92
|
+
'sucesses'=> 0,
|
93
|
+
'failures'=> 0,
|
94
|
+
'missing_ids'=> 1
|
95
|
+
},
|
96
|
+
'errors'=>{
|
97
|
+
}
|
98
|
+
}.to_json
|
99
|
+
}
|
100
|
+
it "should raise error" do
|
101
|
+
expect { contribution.save }.to raise_error(
|
102
|
+
BlueStateDigital::Contribution::ContributionExternalIdMissingException
|
103
|
+
)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
context 'validation errors' do
|
107
|
+
let(:response) {
|
108
|
+
{
|
109
|
+
'summary'=> {
|
110
|
+
'sucesses'=> 0,
|
111
|
+
'failures'=> 1,
|
112
|
+
'missing_ids'=> 0
|
113
|
+
},
|
114
|
+
'errors'=>{
|
115
|
+
'UNIQUE_ID_1234567890'=>
|
116
|
+
[
|
117
|
+
'Parameter source is expected to be a list of strings',
|
118
|
+
'Parameter email does not appear to be a valid email address.'
|
119
|
+
]
|
120
|
+
}
|
121
|
+
}.to_json
|
122
|
+
}
|
123
|
+
it "should raise error" do
|
124
|
+
expect { contribution.save }.to raise_error(
|
125
|
+
BlueStateDigital::Contribution::ContributionSaveValidationException,
|
126
|
+
/Error for Contribution.ID. UNIQUE_ID_1234567890.. Parameter source is expected to be a list of strings, Parameter email does not appear to be a valid email address/m
|
127
|
+
)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BlueStateDigital::DatasetMap do
|
4
|
+
|
5
|
+
let(:connection) { double }
|
6
|
+
let(:dataset_map_attributes) do
|
7
|
+
{
|
8
|
+
}
|
9
|
+
end
|
10
|
+
subject { BlueStateDigital::DatasetMap.new(dataset_map_attributes.merge({connection: connection}))}
|
11
|
+
|
12
|
+
describe "new" do
|
13
|
+
it "should accept dataset_map params" do
|
14
|
+
dataset = BlueStateDigital::Dataset.new(dataset_map_attributes)
|
15
|
+
dataset_map_attributes.each do |k,v|
|
16
|
+
expect(dataset.send(k)).to eq(v)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "save" do
|
22
|
+
context "validations" do
|
23
|
+
it "should not error if there is no data" do
|
24
|
+
expect(subject.data).to be_blank
|
25
|
+
expect(subject).to be_valid
|
26
|
+
end
|
27
|
+
it "should error if there is data but no data header" do
|
28
|
+
subject.add_data_row([1])
|
29
|
+
expect(subject).not_to be_valid
|
30
|
+
expect(subject.errors.full_messages).to eq(["data_header is missing"])
|
31
|
+
end
|
32
|
+
end
|
33
|
+
context "csv upload" do
|
34
|
+
let(:header) { ['a','b','c','d'] }
|
35
|
+
let(:row1) { ['1','2','3','4'] }
|
36
|
+
let(:csv) { "#{header.join(',')}\n#{row1.join(',')}\n"}
|
37
|
+
before(:each) do
|
38
|
+
expect(connection)
|
39
|
+
.to receive(:perform_request_raw)
|
40
|
+
.with('/cons/upload_dataset_map', { api_ver: 2, content_type: "text/csv", accept: "application/json" }, 'PUT',csv)
|
41
|
+
.and_return(response)
|
42
|
+
end
|
43
|
+
let(:response) { Hashie::Mash.new(status: 202,body: "accepted") }
|
44
|
+
it "should convert data into csv and dispatch" do
|
45
|
+
subject.add_data_header(header)
|
46
|
+
subject.add_data_row(row1)
|
47
|
+
expect(subject.save).to be_truthy
|
48
|
+
end
|
49
|
+
context "failure" do
|
50
|
+
let(:response) { Hashie::Mash.new(status: 404,body: "Something bad happened") }
|
51
|
+
it "should return false if save fails" do
|
52
|
+
subject.add_data_header(header)
|
53
|
+
subject.add_data_row(row1)
|
54
|
+
expect(subject.save).to be_falsey
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "delete" do
|
61
|
+
context "validations" do
|
62
|
+
it "should complaing if map_id is not provided" do
|
63
|
+
subject.map_id = nil
|
64
|
+
expect(subject.delete).to be false
|
65
|
+
expect(subject.errors.full_messages).to eq(["map_id is missing"])
|
66
|
+
end
|
67
|
+
end
|
68
|
+
context "service" do
|
69
|
+
let(:map_id) { 1 }
|
70
|
+
let(:delete_payload){ {map_id: map_id} }
|
71
|
+
before :each do
|
72
|
+
expect(connection)
|
73
|
+
.to receive(:perform_request_raw)
|
74
|
+
.with('/cons/delete_dataset_map', {api_ver: 2}, 'POST',delete_payload.to_json)
|
75
|
+
.and_return(response)
|
76
|
+
end
|
77
|
+
context "failure" do
|
78
|
+
let(:response) { Hashie::Mash.new(status: 404,body: "Something bad happened") }
|
79
|
+
it "should return false if delete fails" do
|
80
|
+
subject.map_id = map_id
|
81
|
+
expect(subject.delete).to be_falsey
|
82
|
+
expect(subject.errors.full_messages).to eq(["web_service Something bad happened"])
|
83
|
+
end
|
84
|
+
end
|
85
|
+
context "success" do
|
86
|
+
let(:response) { Hashie::Mash.new(status: 200,body: "") }
|
87
|
+
it "should return true" do
|
88
|
+
subject.map_id = map_id
|
89
|
+
expect(subject.delete).to be_truthy
|
90
|
+
expect(subject.errors.full_messages).to eq([])
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "get_dataset_maps" do
|
97
|
+
let(:connection) { BlueStateDigital::Connection.new({}) }
|
98
|
+
let(:dataset_map1) do
|
99
|
+
{
|
100
|
+
map_id:1,
|
101
|
+
type:"state"
|
102
|
+
}
|
103
|
+
end
|
104
|
+
let(:dataset_map2) do
|
105
|
+
{
|
106
|
+
map_id:2,
|
107
|
+
type:"downballot"
|
108
|
+
}
|
109
|
+
end
|
110
|
+
let(:response) do
|
111
|
+
{
|
112
|
+
data:[
|
113
|
+
dataset_map1,
|
114
|
+
dataset_map2
|
115
|
+
]
|
116
|
+
}.to_json
|
117
|
+
end
|
118
|
+
before :each do
|
119
|
+
expect(connection)
|
120
|
+
.to receive(:perform_request)
|
121
|
+
.with('/cons/list_dataset_maps', {api_ver: 2}, 'GET')
|
122
|
+
.and_return(response)
|
123
|
+
end
|
124
|
+
it "should fetch datasets" do
|
125
|
+
dataset_maps = connection.dataset_maps.get_dataset_maps
|
126
|
+
expect(dataset_maps.length).to eq(2)
|
127
|
+
expect(dataset_maps[0].to_json).to eq(dataset_map1.to_json)
|
128
|
+
expect(dataset_maps[1].to_json).to eq(dataset_map2.to_json)
|
129
|
+
end
|
130
|
+
context "failure" do
|
131
|
+
let(:response) { "Something bad happened" }
|
132
|
+
it "should raise exception if fetch fails" do
|
133
|
+
expect { connection.dataset_maps.get_dataset_maps }.to raise_error(BlueStateDigital::CollectionResource::FetchFailureException)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BlueStateDigital::Dataset do
|
4
|
+
|
5
|
+
let(:connection) { double }
|
6
|
+
let(:slug) { "my_dataset" }
|
7
|
+
let(:map_type) { "state" }
|
8
|
+
let(:dataset_attributes) do
|
9
|
+
{
|
10
|
+
"dataset_id" => 42,
|
11
|
+
"slug" => slug,
|
12
|
+
"rows" => 100,
|
13
|
+
"map_type" => map_type
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
subject { BlueStateDigital::Dataset.new(dataset_attributes.merge({connection: connection}))}
|
18
|
+
|
19
|
+
describe "new" do
|
20
|
+
it "should accept dataset params" do
|
21
|
+
dataset = BlueStateDigital::Dataset.new(dataset_attributes)
|
22
|
+
dataset_attributes.each do |k,v|
|
23
|
+
expect(dataset.send(k)).to eq(v)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "save" do
|
29
|
+
context "validations" do
|
30
|
+
it "should error if required params are not provided" do
|
31
|
+
[:slug,:map_type].each do |field|
|
32
|
+
val = subject.send(field)
|
33
|
+
subject.send("#{field}=",nil)
|
34
|
+
expect(subject).not_to be_valid
|
35
|
+
expect(subject.errors.full_messages).to eq(["#{field} can't be blank"])
|
36
|
+
subject.send("#{field}=",val)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should not error if there is no data" do
|
41
|
+
expect(subject.data).to be_blank
|
42
|
+
expect(subject).to be_valid
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should error if there is data but no data header" do
|
46
|
+
subject.add_data_row([1])
|
47
|
+
expect(subject).not_to be_valid
|
48
|
+
expect(subject.errors.full_messages).to eq(["data_header is missing"])
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context "csv upload" do
|
53
|
+
let(:header) { ['a','b','c','d'] }
|
54
|
+
let(:row1) { ['1','2','3','4'] }
|
55
|
+
let(:csv) { "#{header.join(',')}\n#{row1.join(',')}\n"}
|
56
|
+
let(:response) { Hashie::Mash.new(status: 202, body: "accepted") }
|
57
|
+
|
58
|
+
before(:each) do
|
59
|
+
expect(connection)
|
60
|
+
.to receive(:perform_request_raw)
|
61
|
+
.with('/cons/upload_dataset', { api_ver: 2, slug: slug,map_type: map_type, content_type: "text/csv", accept: "application/json" }, 'PUT',csv)
|
62
|
+
.and_return(response)
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
it "should convert data into csv and dispatch" do
|
67
|
+
subject.add_data_header(header)
|
68
|
+
subject.add_data_row(row1)
|
69
|
+
expect(subject.save).to be_truthy
|
70
|
+
end
|
71
|
+
|
72
|
+
context "failure" do
|
73
|
+
let(:response) { Hashie::Mash.new(status: 404,body: "Something bad happened") }
|
74
|
+
|
75
|
+
it "should return false if save fails" do
|
76
|
+
subject.add_data_header(header)
|
77
|
+
subject.add_data_row(row1)
|
78
|
+
expect(subject.save).to be_falsey
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "delete" do
|
85
|
+
context "validations" do
|
86
|
+
it "should complaing if map_id is not provided" do
|
87
|
+
subject.dataset_id = nil
|
88
|
+
expect(subject.delete).to be false
|
89
|
+
expect(subject.errors.full_messages).to eq(["dataset_id is missing"])
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context "service" do
|
94
|
+
let(:dataset_id) { 1 }
|
95
|
+
let(:delete_payload){ {dataset_id: dataset_id} }
|
96
|
+
|
97
|
+
before :each do
|
98
|
+
expect(connection)
|
99
|
+
.to receive(:perform_request_raw)
|
100
|
+
.with('/cons/delete_dataset', {api_ver: 2}, 'POST',delete_payload.to_json)
|
101
|
+
.and_return(response)
|
102
|
+
end
|
103
|
+
|
104
|
+
context "failure" do
|
105
|
+
let(:response) { Hashie::Mash.new(status: 404,body: "Something bad happened") }
|
106
|
+
|
107
|
+
it "should return false if delete fails" do
|
108
|
+
subject.dataset_id = dataset_id
|
109
|
+
expect(subject.delete).to be_falsey
|
110
|
+
expect(subject.errors.full_messages).to eq(["web_service Something bad happened"])
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
context "success" do
|
115
|
+
let(:response) { Hashie::Mash.new(status: 200,body: "") }
|
116
|
+
|
117
|
+
it "should return true" do
|
118
|
+
subject.dataset_id = dataset_id
|
119
|
+
expect(subject.delete).to be_truthy
|
120
|
+
expect(subject.errors.full_messages).to eq([])
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
describe "get_datasets" do
|
127
|
+
let(:connection) { BlueStateDigital::Connection.new({}) }
|
128
|
+
let(:dataset1) do
|
129
|
+
{
|
130
|
+
dataset_id:42,
|
131
|
+
map_type:"state",
|
132
|
+
slug:"my_dataset",
|
133
|
+
rows:100,
|
134
|
+
}
|
135
|
+
end
|
136
|
+
|
137
|
+
let(:dataset2) do
|
138
|
+
{
|
139
|
+
dataset_id:43,
|
140
|
+
map_type:"downballot",
|
141
|
+
slug:"downballot_dataset",
|
142
|
+
rows:50,
|
143
|
+
}
|
144
|
+
end
|
145
|
+
|
146
|
+
let(:response) do
|
147
|
+
{
|
148
|
+
data:[
|
149
|
+
dataset1,
|
150
|
+
dataset2
|
151
|
+
]
|
152
|
+
}.to_json
|
153
|
+
end
|
154
|
+
|
155
|
+
before :each do
|
156
|
+
expect(connection)
|
157
|
+
.to receive(:perform_request)
|
158
|
+
.with('/cons/list_datasets', { api_ver: 2 }, 'GET')
|
159
|
+
.and_return(response)
|
160
|
+
end
|
161
|
+
|
162
|
+
it "should fetch datasets" do
|
163
|
+
datasets = connection.datasets.get_datasets
|
164
|
+
expect(datasets.length).to eq(2)
|
165
|
+
expect(datasets[0].to_json).to eq(dataset1.to_json)
|
166
|
+
expect(datasets[1].to_json).to eq(dataset2.to_json)
|
167
|
+
end
|
168
|
+
|
169
|
+
context "failure" do
|
170
|
+
let(:response) { "Something bad happened" }
|
171
|
+
|
172
|
+
it "should raise exception if fetch fails" do
|
173
|
+
expect { connection.datasets.get_datasets }.to raise_error(BlueStateDigital::CollectionResource::FetchFailureException)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BlueStateDigital::Email do
|
4
|
+
describe :to_hash do
|
5
|
+
it "should return a hash of all fields" do
|
6
|
+
attr_hash = {email: '123432', email_type: 'personal', is_primary: '1', is_subscribed: '0'}
|
7
|
+
phone = BlueStateDigital::Email.new attr_hash
|
8
|
+
expect(phone.to_hash).to eq(attr_hash)
|
9
|
+
end
|
10
|
+
it "should include nil fields" do
|
11
|
+
expected_hash = {email: nil, email_type: nil, is_primary: nil, is_subscribed: nil}
|
12
|
+
phone = BlueStateDigital::Email.new {}
|
13
|
+
expect(phone.to_hash).to eq(expected_hash)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|