usps-imis-api 0.4.3 → 0.4.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3e49829b6dee8973f1de4b275516060ced7b426cedd00fe7e4ccaba5e29efc52
4
- data.tar.gz: 8558346d33b416f3d58f9fa5047b925f580c8d8d5123463c6fe137335ddd93d7
3
+ metadata.gz: 62e3948cb55d98465788a509e531d293e7d4b6c4120bd7d9fc5c91e902285a9c
4
+ data.tar.gz: b31b47b360f74ec720b9acc9b1b63251c24c8a0546d83f91da7d92f7f4fc8c60
5
5
  SHA512:
6
- metadata.gz: 89f31684df0cb6001fa31966eec99bf8ec9e9dbdab86ae8213a43200f23bf306b204bc9ecb61d9f6ac066869387e4ba048923af1a77b4c7dd1dec59a9cb9b215
7
- data.tar.gz: 376cc34e675f9caadd5c985733b28ea2e93d4ba3752de8d9fd843d3a15866280f3075138a275be47dfd77d06bb24f2ba81cad8527308060a1e8893befbe5381e
6
+ metadata.gz: 5ed6d327340268f29d595c0942f1836b7ca168a137e59d9533afd3011de3b22c2976640ef43c2f843793b012a9d57f1456e6e2996b898adb1fb50af671216311
7
+ data.tar.gz: 76a41b9150dfcf11bcbc43d6e6986b65396718a86067497d6a944d93fbe15cb4c3f3e4cdac105fd0dd20d1fc8cab28ebe4d86d3eee18926a16e8150e5697abfe
data/.simplecov ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ SimpleCov.start do
4
+ enable_coverage :branch
5
+ primary_coverage :branch
6
+
7
+ add_filter '/spec'
8
+ end
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- usps-imis-api (0.4.3)
4
+ usps-imis-api (0.4.4)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -9,18 +9,16 @@ module Usps
9
9
  def initialize(message, metadata = {})
10
10
  super(message)
11
11
  @metadata = metadata
12
-
13
- warn inspect if ENV.fetch('IMIS_ERROR_LOG_TO_STDERR', 'false') == 'true'
14
12
  end
15
13
 
16
14
  def bugsnag_meta_data
17
- metadata == {} ? {} : { api: metadata }
15
+ metadata == {} ? {} : base_metadata
18
16
  end
19
17
 
20
18
  private
21
19
 
22
20
  def base_metadata
23
- { api: {} }
21
+ { api: metadata }
24
22
  end
25
23
  end
26
24
  end
@@ -47,6 +47,8 @@ module Usps
47
47
  :unprocessable_entity # validation error
48
48
  when /^50\d$/
49
49
  :internal_server_error # error within iMIS
50
+ else
51
+ response.code
50
52
  end
51
53
  end
52
54
 
@@ -52,11 +52,13 @@ module Usps
52
52
 
53
53
  def missing_mapping(field_name)
54
54
  unless ENV['TESTING']
55
+ # :nocov:
55
56
  warn(
56
57
  "Mapper does not know how to handle field \"#{field_name}\".\n\n" \
57
58
  'You can use api.put_fields(business_object_name, { field_name => value }) ' \
58
59
  "if you know the business object and iMIS-specific field name.\n\n"
59
60
  )
61
+ # :nocov:
60
62
  end
61
63
 
62
64
  raise(
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Usps
4
4
  module Imis
5
- VERSION = '0.4.3'
5
+ VERSION = '0.4.4'
6
6
  end
7
7
  end
data/lib/usps/imis.rb CHANGED
@@ -7,7 +7,9 @@ require 'time'
7
7
  require 'cgi'
8
8
 
9
9
  # Extensions
10
+ # :nocov:
10
11
  require 'ext/hash' unless defined?(Rails)
12
+ # :nocov:
11
13
 
12
14
  # Internal requires
13
15
  require_relative 'imis/config'
@@ -5,10 +5,36 @@ require 'spec_helper'
5
5
  describe Usps::Imis::Api do
6
6
  let(:api) { described_class.new }
7
7
 
8
+ describe '#initialize' do
9
+ it 'skips authentication' do
10
+ # rubocop:disable RSpec/AnyInstance
11
+ expect_any_instance_of(described_class).not_to receive(:authenticate)
12
+ # rubocop:enable RSpec/AnyInstance
13
+
14
+ described_class.new(skip_authentication: true)
15
+ end
16
+
17
+ it 'stores the initial imis_id' do
18
+ api = described_class.new(imis_id: 42)
19
+
20
+ expect(api.imis_id).to eq('42')
21
+ end
22
+ end
23
+
8
24
  describe '#imis_id_for' do
9
25
  it 'gets the iMIS ID' do
10
26
  expect(api.imis_id_for('E231625')).to eq('31092')
11
27
  end
28
+
29
+ context 'with a query error' do
30
+ before { allow(api).to receive(:query).and_raise('Stub') }
31
+
32
+ it 'wraps errors' do
33
+ expect { api.imis_id_for('E231625') }.to raise_error(
34
+ Usps::Imis::Error::Api, 'Member not found'
35
+ )
36
+ end
37
+ end
12
38
  end
13
39
 
14
40
  describe '#put' do
@@ -17,6 +43,29 @@ describe Usps::Imis::Api do
17
43
  it 'sends an update' do
18
44
  expect(api.put_fields('ABC_ASC_Individual_Demog', { 'TotMMS' => 15 })).to be_a(Hash)
19
45
  end
46
+
47
+ context 'when receiving a response error' do
48
+ let(:warning_text) do
49
+ <<~WARNING.chomp
50
+ Usps::Imis::Error::Response: [INTERNAL_SERVER_ERROR] The iMIS API returned an error.
51
+ Something went wrong
52
+ WARNING
53
+ end
54
+
55
+ before do
56
+ error = Struct.new(:code, :body).new('500', 'Something went wrong')
57
+
58
+ # rubocop:disable RSpec/AnyInstance
59
+ allow_any_instance_of(Net::HTTP).to receive(:request).and_return(error)
60
+ # rubocop:enable RSpec/AnyInstance
61
+ end
62
+
63
+ it 'wraps the error' do
64
+ expect { api.put_fields('ABC_ASC_Individual_Demog', { 'TotMMS' => 15 }) }.to raise_error(
65
+ Usps::Imis::Error::Api, warning_text
66
+ )
67
+ end
68
+ end
20
69
  end
21
70
 
22
71
  describe '#with' do
@@ -46,4 +95,49 @@ describe Usps::Imis::Api do
46
95
  expect(api.inspect).not_to match(/ @token="/)
47
96
  end
48
97
  end
98
+
99
+ describe '#authorize' do
100
+ before { allow(api).to receive(:authenticate) }
101
+
102
+ it 'automatically refreshes an expired token' do
103
+ api.instance_variable_set(:@token_expiration, Time.now - 60)
104
+
105
+ request = Net::HTTP::Put.new('/')
106
+ api.send(:authorize, request)
107
+
108
+ expect(api).to have_received(:authenticate)
109
+ end
110
+ end
111
+
112
+ describe '#filter_fields' do
113
+ let(:expected) do
114
+ {
115
+ 'Properties' => {
116
+ '$values' => [
117
+ { 'Name' => 'Stub iMIS ID', 'Value' => { '$value' => '31092' } },
118
+ { 'Name' => 'Stub Integer', 'Value' => { '$value' => 43 } },
119
+ { 'Name' => 'Stub String', 'Value' => 'other' }
120
+ ]
121
+ }
122
+ }
123
+ end
124
+
125
+ before do
126
+ allow(api).to receive(:get).and_return({
127
+ 'Properties' => {
128
+ '$values' => [
129
+ { 'Name' => 'Stub iMIS ID', 'Value' => { '$value' => '31092' } },
130
+ { 'Name' => 'Stub Integer', 'Value' => { '$value' => 42 } },
131
+ { 'Name' => 'Stub String', 'Value' => 'something' }
132
+ ]
133
+ }
134
+ })
135
+ end
136
+
137
+ it 'formats fields correctly' do
138
+ updated = api.send(:filter_fields, 'Stub', { 'Stub Integer' => 43, 'Stub String' => 'other' })
139
+
140
+ expect(updated).to eq(expected)
141
+ end
142
+ end
49
143
  end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Usps::Imis::Config do
6
+ let(:config) { described_class.new }
7
+
8
+ it 'sets values on initialize' do
9
+ config = described_class.new { |c| c.environment = 'test' }
10
+
11
+ expect(config.environment).to eq('test')
12
+ end
13
+
14
+ describe '#hostname' do
15
+ context 'with production environment' do
16
+ before { config.environment = 'production' }
17
+
18
+ it 'returns the production hostname' do
19
+ expect(config.hostname).to eq(described_class::IMIS_ROOT_URL_PROD)
20
+ end
21
+ end
22
+
23
+ context 'with unrecognized environment' do
24
+ before { config.environment = 'nothing' }
25
+
26
+ it 'raises an error' do
27
+ expect { config.hostname }.to raise_error(
28
+ Usps::Imis::Error::Api, 'Unexpected API environment: nothing'
29
+ )
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Usps::Imis::Error::Api do
6
+ it 'builds Bugsnag metadata' do
7
+ error = described_class.new('Example', something: :else)
8
+
9
+ expect(error.bugsnag_meta_data).to eq(api: { something: :else })
10
+ end
11
+
12
+ it 'ignores Bugsnag metadata with none provided' do
13
+ error = described_class.new('Example')
14
+
15
+ expect(error.bugsnag_meta_data).to eq({})
16
+ end
17
+ end
@@ -5,15 +5,103 @@ require 'spec_helper'
5
5
  ApiResponseStub = Struct.new(:code, :body)
6
6
 
7
7
  describe Usps::Imis::Error::Response do
8
- let(:response) { ApiResponseStub.new('500', 'Body of the API response error') }
9
- let(:warning_text) do
10
- <<~WARNING.chomp
11
- Usps::Imis::Error::Response: [INTERNAL_SERVER_ERROR] The iMIS API returned an error.
12
- Body of the API response error
13
- WARNING
8
+ let(:error) { described_class.from(response) }
9
+
10
+ describe 'error codes' do
11
+ context 'with a 400' do
12
+ let(:response) { ApiResponseStub.new('400', 'body') }
13
+
14
+ it 'builds the Bugsnag metadata correctly' do
15
+ expect(error.bugsnag_meta_data).to eq(api: { status: :bad_request, body: 'body' })
16
+ end
17
+ end
18
+
19
+ context 'with a 401' do
20
+ let(:response) { ApiResponseStub.new('401', 'body') }
21
+
22
+ it 'builds the Bugsnag metadata correctly' do
23
+ expect(error.bugsnag_meta_data).to eq(api: { status: :unauthorized, body: 'body' })
24
+ end
25
+ end
26
+
27
+ context 'with a 404' do
28
+ let(:response) { ApiResponseStub.new('404', 'body') }
29
+
30
+ it 'builds the Bugsnag metadata correctly' do
31
+ expect(error.bugsnag_meta_data).to eq(api: { status: :not_found, body: 'body' })
32
+ end
33
+ end
34
+
35
+ context 'with a 422' do
36
+ let(:response) { ApiResponseStub.new('422', 'body') }
37
+
38
+ it 'builds the Bugsnag metadata correctly' do
39
+ expect(error.bugsnag_meta_data).to eq(api: { status: :unprocessable_entity, body: 'body' })
40
+ end
41
+ end
42
+
43
+ context 'with a 500' do
44
+ let(:response) { ApiResponseStub.new('500', 'body') }
45
+
46
+ it 'builds the Bugsnag metadata correctly' do
47
+ expect(error.bugsnag_meta_data).to eq(api: { status: :internal_server_error, body: 'body' })
48
+ end
49
+ end
50
+
51
+ context 'with a 429' do
52
+ let(:response) { ApiResponseStub.new('429', 'body') }
53
+
54
+ it 'builds the Bugsnag metadata correctly' do
55
+ expect(error.bugsnag_meta_data).to eq(api: { status: '429', body: 'body' })
56
+ end
57
+ end
58
+ end
59
+
60
+ context 'with a string response body' do
61
+ let(:response) { ApiResponseStub.new('500', 'Body of the API response error') }
62
+ let(:warning_text) do
63
+ <<~WARNING.chomp
64
+ Usps::Imis::Error::Response: [INTERNAL_SERVER_ERROR] The iMIS API returned an error.
65
+ Body of the API response error
66
+ WARNING
67
+ end
68
+
69
+ it 'builds the correct message' do
70
+ expect(error.message).to eq(warning_text)
71
+ end
14
72
  end
15
73
 
16
- it 'handles an API response correctly' do
17
- expect(described_class.from(response).message).to eq(warning_text)
74
+ context 'with an invalid_grant hash response body' do
75
+ let(:response_body) do
76
+ { 'error' => 'invalid_grant', 'error_description' => 'description' }
77
+ end
78
+ let(:response) { ApiResponseStub.new('500', response_body) }
79
+ let(:warning_text) do
80
+ <<~WARNING.chomp
81
+ Usps::Imis::Error::Response: [INTERNAL_SERVER_ERROR] The iMIS API returned an error.
82
+ description
83
+ WARNING
84
+ end
85
+
86
+ it 'builds the correct message' do
87
+ expect(error.message).to eq(warning_text)
88
+ end
89
+ end
90
+
91
+ context 'with a generic hash response body' do
92
+ let(:response_body) do
93
+ { 'error' => 'summary', 'error_description' => 'description' }
94
+ end
95
+ let(:response) { ApiResponseStub.new('500', response_body) }
96
+ let(:warning_text) do
97
+ <<~WARNING.chomp
98
+ Usps::Imis::Error::Response: [INTERNAL_SERVER_ERROR] The iMIS API returned an error.
99
+ #{response_body}
100
+ WARNING
101
+ end
102
+
103
+ it 'builds the correct message' do
104
+ expect(error.message).to eq(warning_text)
105
+ end
18
106
  end
19
107
  end
@@ -5,6 +5,14 @@ require 'spec_helper'
5
5
  describe Usps::Imis::Mapper do
6
6
  let(:api) { described_class.new.api }
7
7
 
8
+ describe 'initialize with imis_id' do
9
+ it 'stores the initial imis_id' do
10
+ mapper = described_class.new(imis_id: 42)
11
+
12
+ expect(mapper.api.imis_id).to eq('42')
13
+ end
14
+ end
15
+
8
16
  describe '#update' do
9
17
  before { api.imis_id = 31092 }
10
18
 
@@ -0,0 +1,32 @@
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::Api, '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::Api,
29
+ 'Usps::Imis::Panel::InvalidPanelWithBusinessObject must implement #payload(data)'
30
+ )
31
+ end
32
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Usps::Imis do
6
+ it 'returns configuration from configure without a block' do
7
+ described_class.configuration.environment = 'development'
8
+
9
+ expect(described_class.configure.environment).to eq('development')
10
+ end
11
+ end
data/spec/spec_helper.rb CHANGED
@@ -3,10 +3,7 @@
3
3
  require 'bundler/setup'
4
4
  Bundler.setup
5
5
  require 'simplecov'
6
- SimpleCov.start do
7
- add_filter '/spec'
8
- end
9
- # SimpleCov.minimum_coverage(100)
6
+ SimpleCov.minimum_coverage(line: 100, branch: 100)
10
7
 
11
8
  require 'dotenv/load'
12
9
  require 'usps/imis'
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.3
4
+ version: 0.4.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julian Fiander
@@ -20,6 +20,7 @@ files:
20
20
  - ".rspec"
21
21
  - ".rubocop.yml"
22
22
  - ".ruby-version"
23
+ - ".simplecov"
23
24
  - Gemfile
24
25
  - Gemfile.lock
25
26
  - Rakefile
@@ -39,10 +40,14 @@ files:
39
40
  - lib/usps/imis/panel/vsc.rb
40
41
  - lib/usps/imis/version.rb
41
42
  - spec/lib/usps/imis/api_spec.rb
43
+ - spec/lib/usps/imis/config_spec.rb
44
+ - spec/lib/usps/imis/error/api_spec.rb
42
45
  - spec/lib/usps/imis/error/response_spec.rb
43
46
  - spec/lib/usps/imis/mapper_spec.rb
47
+ - spec/lib/usps/imis/panel/base_panel_spec.rb
44
48
  - spec/lib/usps/imis/panel/education_spec.rb
45
49
  - spec/lib/usps/imis/panel/vsc_spec.rb
50
+ - spec/lib/usps/imis_spec.rb
46
51
  - spec/spec_helper.rb
47
52
  - usps-imis-api.gemspec
48
53
  homepage: http://rubygems.org/gems/usps-imis-api