usps-imis-api 0.6.15 → 0.7.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 +4 -4
- data/.rubocop.yml +1 -3
- data/Gemfile.lock +36 -30
- data/Readme.md +48 -23
- data/lib/usps/imis/api.rb +9 -17
- data/lib/usps/imis/business_object.rb +2 -0
- data/lib/usps/imis/config.rb +1 -1
- data/lib/usps/imis/error.rb +51 -0
- data/lib/usps/imis/errors/api_error.rb +11 -0
- data/lib/usps/imis/errors/config_error.rb +11 -0
- data/lib/usps/imis/errors/locked_id_error.rb +15 -0
- data/lib/usps/imis/errors/mapper_error.rb +29 -0
- data/lib/usps/imis/errors/not_found_error.rb +11 -0
- data/lib/usps/imis/errors/panel_unimplemented_error.rb +34 -0
- data/lib/usps/imis/{error → errors}/response_error.rb +4 -7
- data/lib/usps/imis/errors/unexpected_property_type_error.rb +31 -0
- data/lib/usps/imis/mapper.rb +2 -6
- data/lib/usps/imis/mocks/business_object.rb +37 -0
- data/lib/usps/imis/mocks.rb +11 -0
- data/lib/usps/imis/{panel → panels}/base_panel.rb +3 -3
- data/lib/usps/imis/{panel → panels}/education.rb +1 -1
- data/lib/usps/imis/{panel → panels}/vsc.rb +1 -1
- data/lib/usps/imis/panels.rb +25 -0
- data/lib/usps/imis/properties.rb +1 -1
- data/lib/usps/imis/requests.rb +1 -1
- data/lib/usps/imis/version.rb +1 -1
- data/lib/usps/imis.rb +5 -15
- data/spec/lib/usps/imis/api_spec.rb +8 -8
- data/spec/lib/usps/imis/config_spec.rb +1 -1
- data/spec/lib/usps/imis/{error/api_error_spec.rb → error_spec.rb} +1 -1
- data/spec/lib/usps/imis/{error → errors}/response_error_spec.rb +4 -4
- data/spec/lib/usps/imis/mapper_spec.rb +2 -2
- data/spec/lib/usps/imis/{business_object_mock_spec.rb → mocks/business_object_spec.rb} +1 -1
- data/spec/lib/usps/imis/panels/base_panel_spec.rb +33 -0
- data/spec/lib/usps/imis/{panel → panels}/education_spec.rb +1 -1
- data/spec/lib/usps/imis/{panel → panels}/vsc_spec.rb +1 -1
- data/spec/lib/usps/imis/properties_spec.rb +1 -1
- metadata +22 -15
- data/lib/ext/hash.rb +0 -10
- data/lib/usps/imis/business_object_mock.rb +0 -35
- data/lib/usps/imis/error/api_error.rb +0 -44
- data/lib/usps/imis/error/mapper_error.rb +0 -11
- data/spec/lib/usps/imis/panel/base_panel_spec.rb +0 -32
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bc6237ee6d52c0fdfc8cd33809a90600b68a19926490facab194e751b8c983d3
|
|
4
|
+
data.tar.gz: f66d10f8a53e2df13e42a96fec6a4fc2cb61d798f80dbe7ddc88cf2f84418277
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 16b7a7e05c2fa1cb5d3e2de1604a4a06e5d551a650f7ee451662afa7f43b2b1917f0be04a2c3d4af063a18c0b22515d304bcc25afca79e9214e76542d3b39438
|
|
7
|
+
data.tar.gz: bfe78effec93b84b65963c54decb29ae114e10231e537ad216d1c3d2b250348474efeb0bd20b5f5759a7b6440eca6b28660a10c94d617c90fa70708c1c85727e
|
data/.rubocop.yml
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
plugins:
|
|
2
2
|
- rubocop-rspec
|
|
3
3
|
|
|
4
4
|
AllCops:
|
|
@@ -37,8 +37,6 @@ Lint/UnusedMethodArgument:
|
|
|
37
37
|
Enabled: true
|
|
38
38
|
Lint/UselessAssignment:
|
|
39
39
|
Enabled: true
|
|
40
|
-
Lint/ItWithoutArgumentsInBlock:
|
|
41
|
-
Enabled: false
|
|
42
40
|
|
|
43
41
|
Metrics/MethodLength:
|
|
44
42
|
Enabled: true
|
data/Gemfile.lock
CHANGED
|
@@ -1,37 +1,36 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
usps-imis-api (0.
|
|
4
|
+
usps-imis-api (0.7.0)
|
|
5
5
|
activesupport (~> 8.0)
|
|
6
6
|
|
|
7
7
|
GEM
|
|
8
8
|
remote: https://rubygems.org/
|
|
9
9
|
specs:
|
|
10
|
-
activesupport (8.0
|
|
10
|
+
activesupport (8.1.0)
|
|
11
11
|
base64
|
|
12
|
-
benchmark (>= 0.3)
|
|
13
12
|
bigdecimal
|
|
14
13
|
concurrent-ruby (~> 1.0, >= 1.3.1)
|
|
15
14
|
connection_pool (>= 2.2.5)
|
|
16
15
|
drb
|
|
17
16
|
i18n (>= 1.6, < 2)
|
|
17
|
+
json
|
|
18
18
|
logger (>= 1.4.2)
|
|
19
19
|
minitest (>= 5.1)
|
|
20
20
|
securerandom (>= 0.3)
|
|
21
21
|
tzinfo (~> 2.0, >= 2.0.5)
|
|
22
22
|
uri (>= 0.13.1)
|
|
23
|
-
ast (2.4.
|
|
23
|
+
ast (2.4.3)
|
|
24
24
|
base64 (0.3.0)
|
|
25
|
-
benchmark (0.4.1)
|
|
26
25
|
bigdecimal (3.3.1)
|
|
27
26
|
concurrent-ruby (1.3.5)
|
|
28
27
|
connection_pool (2.5.4)
|
|
29
28
|
date (3.4.1)
|
|
30
|
-
diff-lcs (1.
|
|
29
|
+
diff-lcs (1.6.2)
|
|
31
30
|
docile (1.4.1)
|
|
32
|
-
dotenv (3.1.
|
|
31
|
+
dotenv (3.1.8)
|
|
33
32
|
drb (2.2.3)
|
|
34
|
-
erb (5.
|
|
33
|
+
erb (5.1.1)
|
|
35
34
|
i18n (1.14.7)
|
|
36
35
|
concurrent-ruby (~> 1.0)
|
|
37
36
|
io-console (0.8.1)
|
|
@@ -39,70 +38,77 @@ GEM
|
|
|
39
38
|
pp (>= 0.6.0)
|
|
40
39
|
rdoc (>= 4.0.0)
|
|
41
40
|
reline (>= 0.4.2)
|
|
42
|
-
json (2.
|
|
43
|
-
language_server-protocol (3.17.0.
|
|
41
|
+
json (2.15.1)
|
|
42
|
+
language_server-protocol (3.17.0.5)
|
|
43
|
+
lint_roller (1.1.0)
|
|
44
44
|
logger (1.7.0)
|
|
45
45
|
minitest (5.26.0)
|
|
46
|
-
parallel (1.
|
|
47
|
-
parser (3.3.
|
|
46
|
+
parallel (1.27.0)
|
|
47
|
+
parser (3.3.9.0)
|
|
48
48
|
ast (~> 2.4.1)
|
|
49
49
|
racc
|
|
50
50
|
pp (0.6.3)
|
|
51
51
|
prettyprint
|
|
52
52
|
prettyprint (0.2.0)
|
|
53
|
+
prism (1.6.0)
|
|
53
54
|
psych (5.2.6)
|
|
54
55
|
date
|
|
55
56
|
stringio
|
|
56
57
|
racc (1.8.1)
|
|
57
58
|
rainbow (3.1.1)
|
|
58
|
-
rake (13.
|
|
59
|
+
rake (13.3.0)
|
|
59
60
|
rdoc (6.15.0)
|
|
60
61
|
erb
|
|
61
62
|
psych (>= 4.0.0)
|
|
62
63
|
tsort
|
|
63
|
-
regexp_parser (2.
|
|
64
|
+
regexp_parser (2.11.3)
|
|
64
65
|
reline (0.6.2)
|
|
65
66
|
io-console (~> 0.5)
|
|
66
|
-
rspec (3.13.
|
|
67
|
+
rspec (3.13.2)
|
|
67
68
|
rspec-core (~> 3.13.0)
|
|
68
69
|
rspec-expectations (~> 3.13.0)
|
|
69
70
|
rspec-mocks (~> 3.13.0)
|
|
70
|
-
rspec-core (3.13.
|
|
71
|
+
rspec-core (3.13.6)
|
|
71
72
|
rspec-support (~> 3.13.0)
|
|
72
|
-
rspec-expectations (3.13.
|
|
73
|
+
rspec-expectations (3.13.5)
|
|
73
74
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
74
75
|
rspec-support (~> 3.13.0)
|
|
75
|
-
rspec-mocks (3.13.
|
|
76
|
+
rspec-mocks (3.13.6)
|
|
76
77
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
77
78
|
rspec-support (~> 3.13.0)
|
|
78
|
-
rspec-support (3.13.
|
|
79
|
-
rubocop (1.
|
|
79
|
+
rspec-support (3.13.6)
|
|
80
|
+
rubocop (1.81.6)
|
|
80
81
|
json (~> 2.3)
|
|
81
|
-
language_server-protocol (
|
|
82
|
+
language_server-protocol (~> 3.17.0.2)
|
|
83
|
+
lint_roller (~> 1.1.0)
|
|
82
84
|
parallel (~> 1.10)
|
|
83
85
|
parser (>= 3.3.0.2)
|
|
84
86
|
rainbow (>= 2.2.2, < 4.0)
|
|
85
|
-
regexp_parser (>= 2.
|
|
86
|
-
rubocop-ast (>= 1.
|
|
87
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
|
88
|
+
rubocop-ast (>= 1.47.1, < 2.0)
|
|
87
89
|
ruby-progressbar (~> 1.7)
|
|
88
|
-
unicode-display_width (>= 2.4.0, <
|
|
89
|
-
rubocop-ast (1.
|
|
90
|
-
parser (>= 3.3.
|
|
91
|
-
|
|
92
|
-
|
|
90
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
|
91
|
+
rubocop-ast (1.47.1)
|
|
92
|
+
parser (>= 3.3.7.2)
|
|
93
|
+
prism (~> 1.4)
|
|
94
|
+
rubocop-rspec (3.7.0)
|
|
95
|
+
lint_roller (~> 1.1)
|
|
96
|
+
rubocop (~> 1.72, >= 1.72.1)
|
|
93
97
|
ruby-progressbar (1.13.0)
|
|
94
98
|
securerandom (0.4.1)
|
|
95
99
|
simplecov (0.22.0)
|
|
96
100
|
docile (~> 1.1)
|
|
97
101
|
simplecov-html (~> 0.11)
|
|
98
102
|
simplecov_json_formatter (~> 0.1)
|
|
99
|
-
simplecov-html (0.13.
|
|
103
|
+
simplecov-html (0.13.2)
|
|
100
104
|
simplecov_json_formatter (0.1.4)
|
|
101
105
|
stringio (3.1.7)
|
|
102
106
|
tsort (0.2.0)
|
|
103
107
|
tzinfo (2.0.6)
|
|
104
108
|
concurrent-ruby (~> 1.0)
|
|
105
|
-
unicode-display_width (2.
|
|
109
|
+
unicode-display_width (3.2.0)
|
|
110
|
+
unicode-emoji (~> 4.1)
|
|
111
|
+
unicode-emoji (4.1.0)
|
|
106
112
|
uri (1.0.4)
|
|
107
113
|
|
|
108
114
|
PLATFORMS
|
data/Readme.md
CHANGED
|
@@ -77,33 +77,37 @@ You can also manually set the current ID, if you already have it for a given mem
|
|
|
77
77
|
api.imis_id = imis_id
|
|
78
78
|
```
|
|
79
79
|
|
|
80
|
-
###
|
|
80
|
+
### Business Object and Panel Actions
|
|
81
|
+
|
|
82
|
+
Business Objects and Panels support the following actions.
|
|
83
|
+
|
|
84
|
+
Panels require passing in the ordinal identifier as an argument, except for `POST`.
|
|
85
|
+
|
|
86
|
+
#### GET
|
|
81
87
|
|
|
82
88
|
To fetch member data, run e.g.:
|
|
83
89
|
|
|
84
90
|
```ruby
|
|
85
|
-
api.imis_id = 31092
|
|
86
|
-
|
|
87
91
|
data = api.on('ABC_ASC_Individual_Demog').get
|
|
88
92
|
```
|
|
89
93
|
|
|
90
|
-
|
|
94
|
+
Alias: `read`
|
|
95
|
+
|
|
96
|
+
#### GET Field
|
|
91
97
|
|
|
92
98
|
To fetch a specific field from member data, run e.g.:
|
|
93
99
|
|
|
94
100
|
```ruby
|
|
95
|
-
api.imis_id = 31092
|
|
96
|
-
|
|
97
101
|
tot_mms = api.on('ABC_ASC_Individual_Demog').get_field('TotMMS')
|
|
98
102
|
```
|
|
99
103
|
|
|
100
|
-
|
|
104
|
+
Alias: `fetch`
|
|
105
|
+
|
|
106
|
+
#### PUT Fields
|
|
101
107
|
|
|
102
108
|
To update member data, run e.g.:
|
|
103
109
|
|
|
104
110
|
```ruby
|
|
105
|
-
api.imis_id = 31092
|
|
106
|
-
|
|
107
111
|
data = { 'MMS_Updated' => Time.now.strftime('%Y-%m-%dT%H:%M:%S'), 'TotMMS' => new_total }
|
|
108
112
|
update = api.on('ABC_ASC_Individual_Demog').put_fields(data)
|
|
109
113
|
```
|
|
@@ -111,19 +115,23 @@ update = api.on('ABC_ASC_Individual_Demog').put_fields(data)
|
|
|
111
115
|
This method fetches the current data structure, and filters it down to just what you want to
|
|
112
116
|
update, to reduce the likelihood of update collisions or type validation failures.
|
|
113
117
|
|
|
114
|
-
|
|
118
|
+
Alias: `patch`
|
|
119
|
+
|
|
120
|
+
#### PUT
|
|
115
121
|
|
|
116
122
|
To update member data, run e.g.:
|
|
117
123
|
|
|
118
124
|
```ruby
|
|
119
|
-
api.imis_id = 31092
|
|
120
|
-
|
|
121
125
|
update = api.on('ABC_ASC_Individual_Demog').put(complete_imis_object)
|
|
122
126
|
```
|
|
123
127
|
|
|
124
|
-
This method requires a complete iMIS data structure.
|
|
128
|
+
This method requires a complete iMIS data structure. However, any properties not included will be
|
|
129
|
+
left unmodified (meaning this also effectively handles `PATCH`, though iMIS does not accept that
|
|
130
|
+
HTTP verb).
|
|
131
|
+
|
|
132
|
+
Alias: `update`
|
|
125
133
|
|
|
126
|
-
|
|
134
|
+
#### POST
|
|
127
135
|
|
|
128
136
|
To create new member data, run e.g.:
|
|
129
137
|
|
|
@@ -133,18 +141,20 @@ created = api.on('ABC_ASC_Individual_Demog').post(complete_imis_object)
|
|
|
133
141
|
|
|
134
142
|
This method requires a complete iMIS data structure.
|
|
135
143
|
|
|
136
|
-
|
|
144
|
+
Alias: `create`
|
|
145
|
+
|
|
146
|
+
#### DELETE
|
|
137
147
|
|
|
138
148
|
To remove member data, run e.g.:
|
|
139
149
|
|
|
140
150
|
```ruby
|
|
141
|
-
api.imis_id = 31092
|
|
142
|
-
|
|
143
151
|
api.on('ABC_ASC_Individual_Demog').delete
|
|
144
152
|
```
|
|
145
153
|
|
|
146
154
|
This returns a blank string on success.
|
|
147
155
|
|
|
156
|
+
Alias: `destroy`
|
|
157
|
+
|
|
148
158
|
### QUERY
|
|
149
159
|
|
|
150
160
|
Run an IQA Query
|
|
@@ -180,24 +190,27 @@ For supported panels (usually, business objects with composite identity keys), y
|
|
|
180
190
|
with them in the same general way:
|
|
181
191
|
|
|
182
192
|
```ruby
|
|
183
|
-
vsc = Usps::Imis::
|
|
184
|
-
|
|
185
|
-
vsc.api.imis_id = 6374
|
|
193
|
+
vsc = Usps::Imis::Panels::Vsc.new(imis_id: 6374)
|
|
186
194
|
|
|
187
195
|
vsc.get(1417)
|
|
188
196
|
|
|
197
|
+
vsc.get_field(1417, 'Quantity')
|
|
198
|
+
|
|
189
199
|
created = vsc.create(certificate: 'E136924', year: 2024, count: 42)
|
|
190
|
-
ordinal = created['Properties']['$values'][
|
|
200
|
+
ordinal = created['Properties']['$values'].find { it['Name'] == 'Ordinal' }['Value']['$value']
|
|
201
|
+
# ordinal = created['Identity']['IdentityElements']['$values'][1] # Alternative
|
|
191
202
|
|
|
192
203
|
vsc.update(certificate: 'E136924', year: 2024, count: 43, ordinal: ordinal)
|
|
193
204
|
|
|
205
|
+
vsc.put_fields(ordinal, 'Quantity' => 44)
|
|
206
|
+
|
|
194
207
|
vsc.destroy(ordinal)
|
|
195
208
|
```
|
|
196
209
|
|
|
197
210
|
If you already have an iMIS ID to work with, you can pass that in immediately:
|
|
198
211
|
|
|
199
212
|
```ruby
|
|
200
|
-
vsc = Usps::Imis::
|
|
213
|
+
vsc = Usps::Imis::Panels::Vsc.new(imis_id: imis_id)
|
|
201
214
|
```
|
|
202
215
|
|
|
203
216
|
Panels are also accessible directly from the API object:
|
|
@@ -249,9 +262,21 @@ end
|
|
|
249
262
|
api.with(31092).on('ABC_ASC_Individual_Demog').get_field('TotMMS')
|
|
250
263
|
```
|
|
251
264
|
|
|
265
|
+
## Test Data Mocking
|
|
266
|
+
|
|
267
|
+
You can use the provided Business Object Mock to generate stub data for rspec:
|
|
268
|
+
|
|
269
|
+
```ruby
|
|
270
|
+
allow(api).to(
|
|
271
|
+
receive(:on).with('ABC_ASC_Individual_Demog').and_return(
|
|
272
|
+
Usps::Imis::Mocks::BusinessObject.new(TotMMS: 2)
|
|
273
|
+
)
|
|
274
|
+
)
|
|
275
|
+
```
|
|
276
|
+
|
|
252
277
|
## Exception Handling
|
|
253
278
|
|
|
254
|
-
All internal exceptions inherit from `Usps::Imis::
|
|
279
|
+
All internal exceptions inherit from `Usps::Imis::Error`.
|
|
255
280
|
|
|
256
281
|
## Automated Testing and Linting
|
|
257
282
|
|
data/lib/usps/imis/api.rb
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative 'requests'
|
|
4
|
+
require_relative 'business_object'
|
|
5
|
+
require_relative 'mapper'
|
|
6
|
+
|
|
3
7
|
module Usps
|
|
4
8
|
module Imis
|
|
5
9
|
# The core API wrapper
|
|
@@ -48,7 +52,7 @@ module Usps
|
|
|
48
52
|
# @param id [Integer, String] iMIS ID to select for future requests
|
|
49
53
|
#
|
|
50
54
|
def imis_id=(id)
|
|
51
|
-
raise
|
|
55
|
+
raise Errors::LockedIdError if lock_imis_id
|
|
52
56
|
|
|
53
57
|
@imis_id = id&.to_i&.to_s
|
|
54
58
|
end
|
|
@@ -60,13 +64,13 @@ module Usps
|
|
|
60
64
|
# @return [String] Corresponding iMIS ID
|
|
61
65
|
#
|
|
62
66
|
def imis_id_for(certificate)
|
|
63
|
-
raise
|
|
67
|
+
raise Errors::LockedIdError if lock_imis_id
|
|
64
68
|
|
|
65
69
|
begin
|
|
66
70
|
result = query(Imis.configuration.imis_id_query_name, { certificate: })
|
|
67
71
|
@imis_id = result['Items']['$values'][0]['ID']
|
|
68
72
|
rescue StandardError
|
|
69
|
-
raise
|
|
73
|
+
raise Errors::NotFoundError, 'Member not found'
|
|
70
74
|
end
|
|
71
75
|
end
|
|
72
76
|
|
|
@@ -132,15 +136,6 @@ module Usps
|
|
|
132
136
|
results
|
|
133
137
|
end
|
|
134
138
|
|
|
135
|
-
# An instance of +BusinessObject+, using this instance as its parent +Api+
|
|
136
|
-
#
|
|
137
|
-
# @param business_object_name [String] Name of the business object
|
|
138
|
-
# @param ordinal [Integer] Ordinal to build override ID param of the URL (e.g. used for Panels)
|
|
139
|
-
#
|
|
140
|
-
def business_object(business_object_name, ordinal: nil)
|
|
141
|
-
BusinessObject.new(self, business_object_name, ordinal:)
|
|
142
|
-
end
|
|
143
|
-
|
|
144
139
|
# Run requests as DSL, with specific +BusinessObject+ only maintained for this scope
|
|
145
140
|
#
|
|
146
141
|
# If no block is given, this returns the specified +BusinessObject+.
|
|
@@ -149,7 +144,7 @@ module Usps
|
|
|
149
144
|
# @param ordinal [Integer] Ordinal to build override ID param of the URL (e.g. used for Panels)
|
|
150
145
|
#
|
|
151
146
|
def on(business_object_name, ordinal: nil, &)
|
|
152
|
-
object =
|
|
147
|
+
object = BusinessObject.new(self, business_object_name, ordinal:)
|
|
153
148
|
return object unless block_given?
|
|
154
149
|
|
|
155
150
|
object.instance_eval(&)
|
|
@@ -171,10 +166,7 @@ module Usps
|
|
|
171
166
|
# +Api+
|
|
172
167
|
#
|
|
173
168
|
def panels
|
|
174
|
-
@panels ||=
|
|
175
|
-
Panel::Vsc.new(self),
|
|
176
|
-
Panel::Education.new(self)
|
|
177
|
-
)
|
|
169
|
+
@panels ||= Panels.all(self)
|
|
178
170
|
end
|
|
179
171
|
|
|
180
172
|
# Ruby 3.5 instance variable filter
|
data/lib/usps/imis/config.rb
CHANGED
|
@@ -32,7 +32,7 @@ module Usps
|
|
|
32
32
|
return IMIS_ROOT_URL_PROD if environment.production?
|
|
33
33
|
return IMIS_ROOT_URL_DEV if environment.development?
|
|
34
34
|
|
|
35
|
-
raise
|
|
35
|
+
raise Errors::ConfigError, "Unexpected API environment: #{environment}"
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
# Ruby 3.5 instance variable filter
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Usps
|
|
4
|
+
module Imis
|
|
5
|
+
# Base error class for all internal exceptions
|
|
6
|
+
#
|
|
7
|
+
class Error < StandardError
|
|
8
|
+
# Additional call-specific metadata to pass through to Bugsnag
|
|
9
|
+
#
|
|
10
|
+
attr_accessor :metadata
|
|
11
|
+
|
|
12
|
+
# A new instance of +ApiError+
|
|
13
|
+
#
|
|
14
|
+
# @param message [String] The base exception message
|
|
15
|
+
# @param metadata [Hash] Additional call-specific metadata to pass through to Bugsnag
|
|
16
|
+
#
|
|
17
|
+
def initialize(message, metadata = {})
|
|
18
|
+
super(message)
|
|
19
|
+
@metadata = metadata
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Additional metadata to include in Bugsnag reports
|
|
23
|
+
#
|
|
24
|
+
# Can include fields at the top level, which will be shows on the custom tab
|
|
25
|
+
#
|
|
26
|
+
# Can include fields nested under a top-level key, which will be shown on a tab with the
|
|
27
|
+
# top-level key as its name
|
|
28
|
+
#
|
|
29
|
+
# @return [Hash]
|
|
30
|
+
#
|
|
31
|
+
def bugsnag_meta_data
|
|
32
|
+
metadata == {} ? {} : base_metadata
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def base_metadata
|
|
38
|
+
{ api: metadata }
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
require_relative 'errors/api_error'
|
|
45
|
+
require_relative 'errors/config_error'
|
|
46
|
+
require_relative 'errors/locked_id_error'
|
|
47
|
+
require_relative 'errors/mapper_error'
|
|
48
|
+
require_relative 'errors/not_found_error'
|
|
49
|
+
require_relative 'errors/response_error'
|
|
50
|
+
require_relative 'errors/panel_unimplemented_error'
|
|
51
|
+
require_relative 'errors/unexpected_property_type_error'
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Usps
|
|
4
|
+
module Imis
|
|
5
|
+
module Errors
|
|
6
|
+
# Exception raised when attempting to change the iMIS ID while it is locked
|
|
7
|
+
#
|
|
8
|
+
class LockedIdError < Error
|
|
9
|
+
def initialize = super(message)
|
|
10
|
+
|
|
11
|
+
def message = 'Cannot change iMIS ID while locked'
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Usps
|
|
4
|
+
module Imis
|
|
5
|
+
module Errors
|
|
6
|
+
# Exception raised by a +Mapper+
|
|
7
|
+
#
|
|
8
|
+
class MapperError < Error
|
|
9
|
+
# Create a new instance of +MapperError+
|
|
10
|
+
#
|
|
11
|
+
# @param metadata [Hash] Additional call-specific metadata to pass through to Bugsnag
|
|
12
|
+
#
|
|
13
|
+
def initialize(metadata = {})
|
|
14
|
+
@metadata = metadata
|
|
15
|
+
super(message, metadata)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Exception message including the unrecognized field
|
|
19
|
+
#
|
|
20
|
+
def message
|
|
21
|
+
<<~MESSAGE.chomp
|
|
22
|
+
Mapper does not recognize field: "#{metadata[:field_name]}".
|
|
23
|
+
Please report what data you are attempting to work with to ITCom leadership.
|
|
24
|
+
MESSAGE
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Usps
|
|
4
|
+
module Imis
|
|
5
|
+
module Errors
|
|
6
|
+
# Exception raised when a panel is missing required method definitions
|
|
7
|
+
#
|
|
8
|
+
class PanelUnimplementedError < Error
|
|
9
|
+
# Create a new instance of +PanelUnimplementedError+ from the class name and missing method
|
|
10
|
+
#
|
|
11
|
+
# @param class_name [String] Name of the Panel class that is missing a method definition
|
|
12
|
+
# @param method [String] Method definition that is not defined on the Panel
|
|
13
|
+
#
|
|
14
|
+
def self.from(class_name, method) = new(class_name, method)
|
|
15
|
+
|
|
16
|
+
# Create a new instance of +PanelUnimplementedError+
|
|
17
|
+
#
|
|
18
|
+
# @param class_name [String] Name of the Panel class that is missing a method definition
|
|
19
|
+
# @param method [String] Method definition that is not defined on the Panel
|
|
20
|
+
# @param metadata [Hash] Additional call-specific metadata to pass through to Bugsnag
|
|
21
|
+
#
|
|
22
|
+
def initialize(class_name, method, metadata = {})
|
|
23
|
+
@class_name = class_name
|
|
24
|
+
@method = method
|
|
25
|
+
super(message, metadata)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Exception message including the undefined method
|
|
29
|
+
#
|
|
30
|
+
def message = "#{@class_name} must implement ##{@method}"
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
module Usps
|
|
4
4
|
module Imis
|
|
5
|
-
module
|
|
5
|
+
module Errors
|
|
6
6
|
# Exception raised due to receiving an error response from the API
|
|
7
7
|
#
|
|
8
|
-
class ResponseError <
|
|
8
|
+
class ResponseError < Error
|
|
9
9
|
# [Net::HTTPResponse] The response received from the API
|
|
10
10
|
#
|
|
11
11
|
attr_reader :response
|
|
@@ -18,17 +18,14 @@ module Usps
|
|
|
18
18
|
#
|
|
19
19
|
# @param response [Net::HTTPResponse] The response received from the API
|
|
20
20
|
#
|
|
21
|
-
def self.from(response)
|
|
22
|
-
new(nil, response)
|
|
23
|
-
end
|
|
21
|
+
def self.from(response) = new(response)
|
|
24
22
|
|
|
25
23
|
# Create a new instance of +ResponseError+
|
|
26
24
|
#
|
|
27
|
-
# @param _message Ignored
|
|
28
25
|
# @param response [Net::HTTPResponse] The response received from the API
|
|
29
26
|
# @param metadata [Hash] Additional call-specific metadata to pass through to Bugsnag
|
|
30
27
|
#
|
|
31
|
-
def initialize(
|
|
28
|
+
def initialize(response, metadata = {})
|
|
32
29
|
@response = response
|
|
33
30
|
super(message, metadata)
|
|
34
31
|
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Usps
|
|
4
|
+
module Imis
|
|
5
|
+
module Errors
|
|
6
|
+
# Exception raised when attempting to wrap an unexpected property type
|
|
7
|
+
#
|
|
8
|
+
class UnexpectedPropertyTypeError < Error
|
|
9
|
+
# Create a new instance of +UnexpectedPropertyTypeError+ from an unexpected value
|
|
10
|
+
#
|
|
11
|
+
# @param value Unexpected value
|
|
12
|
+
#
|
|
13
|
+
def self.from(value) = new(value)
|
|
14
|
+
|
|
15
|
+
# Create a new instance of +UnexpectedPropertyTypeError+
|
|
16
|
+
#
|
|
17
|
+
# @param value Unexpected value
|
|
18
|
+
# @param metadata [Hash] Additional call-specific metadata to pass through to Bugsnag
|
|
19
|
+
#
|
|
20
|
+
def initialize(value, metadata = {})
|
|
21
|
+
@value = value
|
|
22
|
+
super(message, metadata)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Exception message including the undefined method
|
|
26
|
+
#
|
|
27
|
+
def message = "Unexpected property type: #{@value.inspect}"
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
data/lib/usps/imis/mapper.rb
CHANGED
|
@@ -47,7 +47,7 @@ module Usps
|
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
updates.map do |business_object_name, field_updates|
|
|
50
|
-
api.
|
|
50
|
+
api.on(business_object_name).put_fields(field_updates)
|
|
51
51
|
end
|
|
52
52
|
end
|
|
53
53
|
|
|
@@ -73,11 +73,7 @@ module Usps
|
|
|
73
73
|
# :nocov:
|
|
74
74
|
end
|
|
75
75
|
|
|
76
|
-
raise(
|
|
77
|
-
Error::MapperError,
|
|
78
|
-
"Unrecognized field: \"#{field_name}\". " \
|
|
79
|
-
'Please report what data you are attempting to work with to ITCom leadership.'
|
|
80
|
-
)
|
|
76
|
+
raise Errors::MapperError.new({ field_name: })
|
|
81
77
|
end
|
|
82
78
|
end
|
|
83
79
|
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Usps
|
|
4
|
+
module Imis
|
|
5
|
+
module Mocks
|
|
6
|
+
# Mock data response for testing
|
|
7
|
+
#
|
|
8
|
+
class BusinessObject
|
|
9
|
+
attr_reader :fields
|
|
10
|
+
|
|
11
|
+
def initialize(**fields)
|
|
12
|
+
@fields = fields.transform_keys(&:to_s)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def get_field(name) = fields[name]
|
|
16
|
+
|
|
17
|
+
def get
|
|
18
|
+
Usps::Imis::Properties.build do |props|
|
|
19
|
+
fields.each { |name, value| props.add(name, value) }
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def put_fields(data)
|
|
24
|
+
Usps::Imis::Properties.build do |props|
|
|
25
|
+
fields.merge(data.transform_keys(&:to_s)).each { |name, value| props.add(name, value) }
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def put(data) = data
|
|
30
|
+
|
|
31
|
+
def post(data) = data
|
|
32
|
+
|
|
33
|
+
def delete = ''
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module Usps
|
|
4
4
|
module Imis
|
|
5
|
-
module
|
|
5
|
+
module Panels
|
|
6
6
|
# Base class for configuring Panels
|
|
7
7
|
#
|
|
8
8
|
class BasePanel
|
|
@@ -79,11 +79,11 @@ module Usps
|
|
|
79
79
|
private
|
|
80
80
|
|
|
81
81
|
def business_object
|
|
82
|
-
raise
|
|
82
|
+
raise Errors::PanelUnimplementedError.from(self.class.name, 'business_object')
|
|
83
83
|
end
|
|
84
84
|
|
|
85
85
|
def payload(_data)
|
|
86
|
-
raise
|
|
86
|
+
raise Errors::PanelUnimplementedError.from(self.class.name, 'payload(data)')
|
|
87
87
|
end
|
|
88
88
|
|
|
89
89
|
def payload_header(data)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'panels/base_panel'
|
|
4
|
+
require_relative 'panels/vsc'
|
|
5
|
+
require_relative 'panels/education'
|
|
6
|
+
|
|
7
|
+
module Usps
|
|
8
|
+
module Imis
|
|
9
|
+
# Namespace for all Panels
|
|
10
|
+
#
|
|
11
|
+
module Panels
|
|
12
|
+
# Convenience accessor for available Panel objects
|
|
13
|
+
#
|
|
14
|
+
# @param api [Api] Parent to use for making requests
|
|
15
|
+
#
|
|
16
|
+
def self.all(api = Api.new)
|
|
17
|
+
panels = constants.reject { it == :BasePanel }
|
|
18
|
+
|
|
19
|
+
Struct
|
|
20
|
+
.new(*panels.map { it.to_s.underscore.to_sym })
|
|
21
|
+
.new(*panels.map { const_get(it).new(api) })
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
data/lib/usps/imis/properties.rb
CHANGED
|
@@ -42,7 +42,7 @@ module Usps
|
|
|
42
42
|
when Integer then { '$type' => 'System.Int32', '$value' => value }
|
|
43
43
|
when true, false then { '$type' => 'System.Boolean', '$value' => value }
|
|
44
44
|
else
|
|
45
|
-
raise
|
|
45
|
+
raise Errors::UnexpectedPropertyTypeError.from(value)
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
48
|
end
|
data/lib/usps/imis/requests.rb
CHANGED
|
@@ -25,7 +25,7 @@ module Usps
|
|
|
25
25
|
|
|
26
26
|
def submit(uri, request)
|
|
27
27
|
client(uri).request(request).tap do |result|
|
|
28
|
-
raise
|
|
28
|
+
raise Errors::ResponseError.from(result) unless result.is_a?(Net::HTTPSuccess)
|
|
29
29
|
end
|
|
30
30
|
end
|
|
31
31
|
end
|
data/lib/usps/imis/version.rb
CHANGED
data/lib/usps/imis.rb
CHANGED
|
@@ -6,27 +6,17 @@ require 'json'
|
|
|
6
6
|
require 'time'
|
|
7
7
|
require 'cgi'
|
|
8
8
|
|
|
9
|
+
require 'active_support/core_ext/string/inflections'
|
|
10
|
+
require 'active_support/core_ext/object/to_query'
|
|
9
11
|
require 'active_support/string_inquirer'
|
|
10
12
|
|
|
11
|
-
# Extensions
|
|
12
|
-
# :nocov:
|
|
13
|
-
require 'ext/hash' unless defined?(Rails)
|
|
14
|
-
# :nocov:
|
|
15
|
-
|
|
16
13
|
# Internal requires
|
|
17
14
|
require_relative 'imis/config'
|
|
18
|
-
require_relative 'imis/error
|
|
19
|
-
require_relative 'imis/error/mapper_error'
|
|
20
|
-
require_relative 'imis/error/response_error'
|
|
21
|
-
require_relative 'imis/requests'
|
|
22
|
-
require_relative 'imis/business_object'
|
|
15
|
+
require_relative 'imis/error'
|
|
23
16
|
require_relative 'imis/api'
|
|
24
|
-
require_relative 'imis/mapper'
|
|
25
17
|
require_relative 'imis/properties'
|
|
26
|
-
require_relative 'imis/
|
|
27
|
-
require_relative 'imis/
|
|
28
|
-
require_relative 'imis/panel/vsc'
|
|
29
|
-
require_relative 'imis/panel/education'
|
|
18
|
+
require_relative 'imis/panels'
|
|
19
|
+
require_relative 'imis/mocks'
|
|
30
20
|
|
|
31
21
|
module Usps
|
|
32
22
|
# API wrapper for interacting with iMIS
|
|
@@ -31,7 +31,7 @@ describe Usps::Imis::Api do
|
|
|
31
31
|
|
|
32
32
|
it 'wraps errors' do
|
|
33
33
|
expect { api.imis_id_for('E231625') }.to raise_error(
|
|
34
|
-
Usps::Imis::
|
|
34
|
+
Usps::Imis::Errors::NotFoundError, 'Member not found'
|
|
35
35
|
)
|
|
36
36
|
end
|
|
37
37
|
end
|
|
@@ -56,7 +56,7 @@ describe Usps::Imis::Api do
|
|
|
56
56
|
before { api.imis_id = 31092 }
|
|
57
57
|
|
|
58
58
|
it 'sends an update' do
|
|
59
|
-
expect(api.
|
|
59
|
+
expect(api.on('ABC_ASC_Individual_Demog').put_fields('TotMMS' => 15)).to(
|
|
60
60
|
be_a(Hash)
|
|
61
61
|
)
|
|
62
62
|
end
|
|
@@ -64,7 +64,7 @@ describe Usps::Imis::Api do
|
|
|
64
64
|
context 'when receiving a response error' do
|
|
65
65
|
let(:warning_text) do
|
|
66
66
|
<<~WARNING.chomp
|
|
67
|
-
Usps::Imis::
|
|
67
|
+
Usps::Imis::Errors::ResponseError: [INTERNAL_SERVER_ERROR] The iMIS API returned an error.
|
|
68
68
|
Something went wrong
|
|
69
69
|
WARNING
|
|
70
70
|
end
|
|
@@ -78,8 +78,8 @@ describe Usps::Imis::Api do
|
|
|
78
78
|
end
|
|
79
79
|
|
|
80
80
|
it 'wraps the error' do
|
|
81
|
-
expect { api.
|
|
82
|
-
raise_error(Usps::Imis::
|
|
81
|
+
expect { api.on('ABC_ASC_Individual_Demog').put_fields('TotMMS' => 15) }.to(
|
|
82
|
+
raise_error(Usps::Imis::Errors::ResponseError, warning_text)
|
|
83
83
|
)
|
|
84
84
|
end
|
|
85
85
|
end
|
|
@@ -88,7 +88,7 @@ describe Usps::Imis::Api do
|
|
|
88
88
|
describe '#with' do
|
|
89
89
|
it 'sends an update from put' do
|
|
90
90
|
expect(
|
|
91
|
-
api.with(31092) {
|
|
91
|
+
api.with(31092) { on('ABC_ASC_Individual_Demog').put_fields('TotMMS' => 15) }
|
|
92
92
|
).to be_a(Hash)
|
|
93
93
|
end
|
|
94
94
|
|
|
@@ -103,13 +103,13 @@ describe Usps::Imis::Api do
|
|
|
103
103
|
it 'blocks calling imis_id=' do
|
|
104
104
|
expect do
|
|
105
105
|
api.with(31092) { self.imis_id = 31092 }
|
|
106
|
-
end.to raise_error(Usps::Imis::
|
|
106
|
+
end.to raise_error(Usps::Imis::Errors::LockedIdError, 'Cannot change iMIS ID while locked')
|
|
107
107
|
end
|
|
108
108
|
|
|
109
109
|
it 'blocks calling imis_id_for' do
|
|
110
110
|
expect do
|
|
111
111
|
api.with(31092) { imis_id_for('E231625') }
|
|
112
|
-
end.to raise_error(Usps::Imis::
|
|
112
|
+
end.to raise_error(Usps::Imis::Errors::LockedIdError, 'Cannot change iMIS ID while locked')
|
|
113
113
|
end
|
|
114
114
|
end
|
|
115
115
|
|
|
@@ -51,7 +51,7 @@ describe Usps::Imis::Config do
|
|
|
51
51
|
|
|
52
52
|
it 'raises an error' do
|
|
53
53
|
expect { config.hostname }.to raise_error(
|
|
54
|
-
Usps::Imis::
|
|
54
|
+
Usps::Imis::Errors::ConfigError, 'Unexpected API environment: nothing'
|
|
55
55
|
)
|
|
56
56
|
end
|
|
57
57
|
end
|
|
@@ -4,7 +4,7 @@ require 'spec_helper'
|
|
|
4
4
|
|
|
5
5
|
ApiResponseStub = Struct.new(:code, :body)
|
|
6
6
|
|
|
7
|
-
describe Usps::Imis::
|
|
7
|
+
describe Usps::Imis::Errors::ResponseError do
|
|
8
8
|
let(:error) { described_class.from(response) }
|
|
9
9
|
|
|
10
10
|
describe 'error codes' do
|
|
@@ -61,7 +61,7 @@ describe Usps::Imis::Error::ResponseError do
|
|
|
61
61
|
let(:response) { ApiResponseStub.new('500', 'Body of the API response error') }
|
|
62
62
|
let(:warning_text) do
|
|
63
63
|
<<~WARNING.chomp
|
|
64
|
-
Usps::Imis::
|
|
64
|
+
Usps::Imis::Errors::ResponseError: [INTERNAL_SERVER_ERROR] The iMIS API returned an error.
|
|
65
65
|
Body of the API response error
|
|
66
66
|
WARNING
|
|
67
67
|
end
|
|
@@ -78,7 +78,7 @@ describe Usps::Imis::Error::ResponseError do
|
|
|
78
78
|
let(:response) { ApiResponseStub.new('500', response_body) }
|
|
79
79
|
let(:warning_text) do
|
|
80
80
|
<<~WARNING.chomp
|
|
81
|
-
Usps::Imis::
|
|
81
|
+
Usps::Imis::Errors::ResponseError: [INTERNAL_SERVER_ERROR] The iMIS API returned an error.
|
|
82
82
|
description
|
|
83
83
|
WARNING
|
|
84
84
|
end
|
|
@@ -95,7 +95,7 @@ describe Usps::Imis::Error::ResponseError do
|
|
|
95
95
|
let(:response) { ApiResponseStub.new('500', response_body) }
|
|
96
96
|
let(:warning_text) do
|
|
97
97
|
<<~WARNING.chomp
|
|
98
|
-
Usps::Imis::
|
|
98
|
+
Usps::Imis::Errors::ResponseError: [INTERNAL_SERVER_ERROR] The iMIS API returned an error.
|
|
99
99
|
#{response_body}
|
|
100
100
|
WARNING
|
|
101
101
|
end
|
|
@@ -22,8 +22,8 @@ describe Usps::Imis::Mapper do
|
|
|
22
22
|
|
|
23
23
|
it 'raises for unmapped updates' do
|
|
24
24
|
expect { api.mapper.update(something: 'anything') }.to raise_error(
|
|
25
|
-
Usps::Imis::
|
|
26
|
-
|
|
25
|
+
Usps::Imis::Errors::MapperError,
|
|
26
|
+
%(Mapper does not recognize field: "something".\n) \
|
|
27
27
|
'Please report what data you are attempting to work with to ITCom leadership.'
|
|
28
28
|
)
|
|
29
29
|
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
module Usps
|
|
6
|
+
module Imis
|
|
7
|
+
module Panels
|
|
8
|
+
class InvalidPanel < BasePanel; end
|
|
9
|
+
|
|
10
|
+
class InvalidPanelWithBusinessObject < BasePanel
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
def business_object = 'Something'
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
describe Usps::Imis::Panels::BasePanel do
|
|
20
|
+
it 'requires #business_object to be defined' do
|
|
21
|
+
expect { Usps::Imis::Panels::InvalidPanel.new.get(1) }.to raise_error(
|
|
22
|
+
Usps::Imis::Errors::PanelUnimplementedError,
|
|
23
|
+
'Usps::Imis::Panels::InvalidPanel must implement #business_object'
|
|
24
|
+
)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'requires #payload(data) to be defined' do
|
|
28
|
+
expect { Usps::Imis::Panels::InvalidPanelWithBusinessObject.new.create({}) }.to raise_error(
|
|
29
|
+
Usps::Imis::Errors::PanelUnimplementedError,
|
|
30
|
+
'Usps::Imis::Panels::InvalidPanelWithBusinessObject must implement #payload(data)'
|
|
31
|
+
)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -13,7 +13,7 @@ describe Usps::Imis::Properties do
|
|
|
13
13
|
|
|
14
14
|
it 'raises an error for unexpected property types' do
|
|
15
15
|
expect { builder.send(:wrap, {}) }.to raise_error(
|
|
16
|
-
Usps::Imis::
|
|
16
|
+
Usps::Imis::Errors::UnexpectedPropertyTypeError, 'Unexpected property type: {}'
|
|
17
17
|
)
|
|
18
18
|
end
|
|
19
19
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: usps-imis-api
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Julian Fiander
|
|
@@ -41,32 +41,39 @@ files:
|
|
|
41
41
|
- Readme.md
|
|
42
42
|
- bin/console
|
|
43
43
|
- bin/setup
|
|
44
|
-
- lib/ext/hash.rb
|
|
45
44
|
- lib/usps/imis.rb
|
|
46
45
|
- lib/usps/imis/api.rb
|
|
47
46
|
- lib/usps/imis/business_object.rb
|
|
48
|
-
- lib/usps/imis/business_object_mock.rb
|
|
49
47
|
- lib/usps/imis/config.rb
|
|
50
|
-
- lib/usps/imis/error
|
|
51
|
-
- lib/usps/imis/
|
|
52
|
-
- lib/usps/imis/
|
|
48
|
+
- lib/usps/imis/error.rb
|
|
49
|
+
- lib/usps/imis/errors/api_error.rb
|
|
50
|
+
- lib/usps/imis/errors/config_error.rb
|
|
51
|
+
- lib/usps/imis/errors/locked_id_error.rb
|
|
52
|
+
- lib/usps/imis/errors/mapper_error.rb
|
|
53
|
+
- lib/usps/imis/errors/not_found_error.rb
|
|
54
|
+
- lib/usps/imis/errors/panel_unimplemented_error.rb
|
|
55
|
+
- lib/usps/imis/errors/response_error.rb
|
|
56
|
+
- lib/usps/imis/errors/unexpected_property_type_error.rb
|
|
53
57
|
- lib/usps/imis/mapper.rb
|
|
54
|
-
- lib/usps/imis/
|
|
55
|
-
- lib/usps/imis/
|
|
56
|
-
- lib/usps/imis/
|
|
58
|
+
- lib/usps/imis/mocks.rb
|
|
59
|
+
- lib/usps/imis/mocks/business_object.rb
|
|
60
|
+
- lib/usps/imis/panels.rb
|
|
61
|
+
- lib/usps/imis/panels/base_panel.rb
|
|
62
|
+
- lib/usps/imis/panels/education.rb
|
|
63
|
+
- lib/usps/imis/panels/vsc.rb
|
|
57
64
|
- lib/usps/imis/properties.rb
|
|
58
65
|
- lib/usps/imis/requests.rb
|
|
59
66
|
- lib/usps/imis/version.rb
|
|
60
67
|
- spec/lib/usps/imis/api_spec.rb
|
|
61
|
-
- spec/lib/usps/imis/business_object_mock_spec.rb
|
|
62
68
|
- spec/lib/usps/imis/business_object_spec.rb
|
|
63
69
|
- spec/lib/usps/imis/config_spec.rb
|
|
64
|
-
- spec/lib/usps/imis/
|
|
65
|
-
- spec/lib/usps/imis/
|
|
70
|
+
- spec/lib/usps/imis/error_spec.rb
|
|
71
|
+
- spec/lib/usps/imis/errors/response_error_spec.rb
|
|
66
72
|
- spec/lib/usps/imis/mapper_spec.rb
|
|
67
|
-
- spec/lib/usps/imis/
|
|
68
|
-
- spec/lib/usps/imis/
|
|
69
|
-
- spec/lib/usps/imis/
|
|
73
|
+
- spec/lib/usps/imis/mocks/business_object_spec.rb
|
|
74
|
+
- spec/lib/usps/imis/panels/base_panel_spec.rb
|
|
75
|
+
- spec/lib/usps/imis/panels/education_spec.rb
|
|
76
|
+
- spec/lib/usps/imis/panels/vsc_spec.rb
|
|
70
77
|
- spec/lib/usps/imis/properties_spec.rb
|
|
71
78
|
- spec/lib/usps/imis_spec.rb
|
|
72
79
|
- spec/spec_helper.rb
|
data/lib/ext/hash.rb
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Usps
|
|
4
|
-
module Imis
|
|
5
|
-
# Mock data response for testing
|
|
6
|
-
#
|
|
7
|
-
class BusinessObjectMock
|
|
8
|
-
attr_reader :fields
|
|
9
|
-
|
|
10
|
-
def initialize(**fields)
|
|
11
|
-
@fields = fields.transform_keys(&:to_s)
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def get_field(name) = fields[name]
|
|
15
|
-
|
|
16
|
-
def get
|
|
17
|
-
Usps::Imis::Properties.build do |props|
|
|
18
|
-
fields.each { |name, value| props.add(name, value) }
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def put_fields(data)
|
|
23
|
-
Usps::Imis::Properties.build do |props|
|
|
24
|
-
fields.merge(data.transform_keys(&:to_s)).each { |name, value| props.add(name, value) }
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def put(data) = data
|
|
29
|
-
|
|
30
|
-
def post(data) = data
|
|
31
|
-
|
|
32
|
-
def delete = ''
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Usps
|
|
4
|
-
module Imis
|
|
5
|
-
module Error
|
|
6
|
-
# Base error class for all internal exceptions
|
|
7
|
-
#
|
|
8
|
-
class ApiError < StandardError
|
|
9
|
-
# Additional call-specific metadata to pass through to Bugsnag
|
|
10
|
-
#
|
|
11
|
-
attr_accessor :metadata
|
|
12
|
-
|
|
13
|
-
# A new instance of +ApiError+
|
|
14
|
-
#
|
|
15
|
-
# @param message [String] The base exception message
|
|
16
|
-
# @param metadata [Hash] Additional call-specific metadata to pass through to Bugsnag
|
|
17
|
-
#
|
|
18
|
-
def initialize(message, metadata = {})
|
|
19
|
-
super(message)
|
|
20
|
-
@metadata = metadata
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
# Additional metadata to include in Bugsnag reports
|
|
24
|
-
#
|
|
25
|
-
# Can include fields at the top level, which will be shows on the custom tab
|
|
26
|
-
#
|
|
27
|
-
# Can include fields nested under a top-level key, which will be shown on a tab with the
|
|
28
|
-
# top-level key as its name
|
|
29
|
-
#
|
|
30
|
-
# @return [Hash]
|
|
31
|
-
#
|
|
32
|
-
def bugsnag_meta_data
|
|
33
|
-
metadata == {} ? {} : base_metadata
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
private
|
|
37
|
-
|
|
38
|
-
def base_metadata
|
|
39
|
-
{ api: metadata }
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
end
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'spec_helper'
|
|
4
|
-
|
|
5
|
-
module Usps
|
|
6
|
-
module Imis
|
|
7
|
-
module Panel
|
|
8
|
-
class InvalidPanel < BasePanel; end
|
|
9
|
-
|
|
10
|
-
class InvalidPanelWithBusinessObject < BasePanel
|
|
11
|
-
private
|
|
12
|
-
|
|
13
|
-
def business_object = 'Something'
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
describe Usps::Imis::Panel::BasePanel do
|
|
20
|
-
it 'requires #business_object to be defined' do
|
|
21
|
-
expect { Usps::Imis::Panel::InvalidPanel.new.get(1) }.to raise_error(
|
|
22
|
-
Usps::Imis::Error::ApiError, 'Usps::Imis::Panel::InvalidPanel must implement #business_object'
|
|
23
|
-
)
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
it 'requires #payload(data) to be defined' do
|
|
27
|
-
expect { Usps::Imis::Panel::InvalidPanelWithBusinessObject.new.create({}) }.to raise_error(
|
|
28
|
-
Usps::Imis::Error::ApiError,
|
|
29
|
-
'Usps::Imis::Panel::InvalidPanelWithBusinessObject must implement #payload(data)'
|
|
30
|
-
)
|
|
31
|
-
end
|
|
32
|
-
end
|