creditsafe 0.6.2 → 0.6.3

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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +17 -17
  3. data/.gitignore +4 -3
  4. data/.rspec +1 -1
  5. data/.rubocop.yml +14 -11
  6. data/.ruby-version +1 -1
  7. data/CHANGELOG.md +57 -53
  8. data/Gemfile +5 -5
  9. data/LICENSE.txt +22 -22
  10. data/README.md +175 -175
  11. data/creditsafe.gemspec +34 -35
  12. data/data/creditsafe-live.xml +342 -342
  13. data/data/creditsafe-test.xml +342 -342
  14. data/lib/creditsafe.rb +4 -4
  15. data/lib/creditsafe/client.rb +165 -165
  16. data/lib/creditsafe/constants.rb +49 -49
  17. data/lib/creditsafe/errors.rb +17 -17
  18. data/lib/creditsafe/match_type.rb +115 -115
  19. data/lib/creditsafe/messages.rb +98 -98
  20. data/lib/creditsafe/namespace.rb +20 -20
  21. data/lib/creditsafe/request/company_report.rb +42 -42
  22. data/lib/creditsafe/request/find_company.rb +120 -120
  23. data/lib/creditsafe/version.rb +5 -5
  24. data/spec/creditsafe/client_spec.rb +431 -431
  25. data/spec/creditsafe/messages_spec.rb +76 -76
  26. data/spec/fixtures/company-report-not-found.xml +13 -13
  27. data/spec/fixtures/company-report-request.xml +1 -1
  28. data/spec/fixtures/company-report-successful.xml +582 -582
  29. data/spec/fixtures/error-fault.xml +8 -8
  30. data/spec/fixtures/error-invalid-credentials.html +31 -31
  31. data/spec/fixtures/find-companies-error-no-text.xml +11 -11
  32. data/spec/fixtures/find-companies-error.xml +11 -11
  33. data/spec/fixtures/find-companies-none-found.xml +13 -13
  34. data/spec/fixtures/find-companies-request.xml +1 -1
  35. data/spec/fixtures/find-companies-successful-multi.xml +493 -493
  36. data/spec/fixtures/find-companies-successful.xml +29 -29
  37. data/spec/spec_helper.rb +14 -14
  38. metadata +39 -40
  39. data/Gemfile.lock +0 -129
@@ -1,42 +1,42 @@
1
- # frozen_string_literal: true
2
-
3
- require "creditsafe/namespace"
4
-
5
- module Creditsafe
6
- module Request
7
- class CompanyReport
8
- def initialize(company_id, custom_data)
9
- @company_id = company_id
10
- @custom_data = custom_data
11
- end
12
-
13
- # rubocop:disable Metrics/MethodLength
14
- def message
15
- message = {
16
- "#{Creditsafe::Namespace::OPER}:companyId" => company_id.to_s,
17
- "#{Creditsafe::Namespace::OPER}:reportType" => "Full",
18
- "#{Creditsafe::Namespace::OPER}:language" => "EN",
19
- }
20
-
21
- unless custom_data.nil?
22
- message["#{Creditsafe::Namespace::OPER}:customData"] = {
23
- "#{Creditsafe::Namespace::DAT}:Entries" => {
24
- "#{Creditsafe::Namespace::DAT}:Entry" => custom_data_entries,
25
- },
26
- }
27
- end
28
-
29
- message
30
- end
31
- # rubocop:enable Metrics/MethodLength
32
-
33
- private
34
-
35
- def custom_data_entries
36
- custom_data.map { |key, value| { :@key => key, :content! => value } }
37
- end
38
-
39
- attr_reader :company_id, :custom_data
40
- end
41
- end
42
- end
1
+ # frozen_string_literal: true
2
+
3
+ require "creditsafe/namespace"
4
+
5
+ module Creditsafe
6
+ module Request
7
+ class CompanyReport
8
+ def initialize(company_id, custom_data)
9
+ @company_id = company_id
10
+ @custom_data = custom_data
11
+ end
12
+
13
+ # rubocop:disable Metrics/MethodLength
14
+ def message
15
+ message = {
16
+ "#{Creditsafe::Namespace::OPER}:companyId" => company_id.to_s,
17
+ "#{Creditsafe::Namespace::OPER}:reportType" => "Full",
18
+ "#{Creditsafe::Namespace::OPER}:language" => "EN",
19
+ }
20
+
21
+ unless custom_data.nil?
22
+ message["#{Creditsafe::Namespace::OPER}:customData"] = {
23
+ "#{Creditsafe::Namespace::DAT}:Entries" => {
24
+ "#{Creditsafe::Namespace::DAT}:Entry" => custom_data_entries,
25
+ },
26
+ }
27
+ end
28
+
29
+ message
30
+ end
31
+ # rubocop:enable Metrics/MethodLength
32
+
33
+ private
34
+
35
+ def custom_data_entries
36
+ custom_data.map { |key, value| { :@key => key, :content! => value } }
37
+ end
38
+
39
+ attr_reader :company_id, :custom_data
40
+ end
41
+ end
42
+ end
@@ -1,120 +1,120 @@
1
- # frozen_string_literal: true
2
-
3
- require "creditsafe/match_type"
4
- require "creditsafe/namespace"
5
- require "creditsafe/constants"
6
-
7
- module Creditsafe
8
- module Request
9
- class FindCompany
10
- def initialize(search_criteria)
11
- check_search_criteria(search_criteria)
12
- @country_code = search_criteria[:country_code]
13
- @registration_number = search_criteria[:registration_number]
14
- @company_name = search_criteria[:company_name]
15
- @vat_number = search_criteria[:vat_number]
16
- @city = search_criteria[:city]
17
- @postal_code = search_criteria[:postal_code]
18
- end
19
-
20
- # rubocop:disable Metrics/MethodLength
21
- # rubocop:disable Metrics/AbcSize
22
- def message
23
- search_criteria = {}
24
-
25
- unless company_name.nil?
26
- search_criteria["#{Creditsafe::Namespace::DAT}:Name"] = {
27
- "@MatchType" => match_type,
28
- :content! => company_name,
29
- }
30
- end
31
-
32
- unless registration_number.nil?
33
- search_criteria["#{Creditsafe::Namespace::DAT}:RegistrationNumber"] =
34
- registration_number
35
- end
36
-
37
- unless vat_number.nil?
38
- search_criteria["#{Creditsafe::Namespace::DAT}:VatNumber"] =
39
- vat_number
40
- end
41
-
42
- unless city.nil?
43
- search_criteria["#{Creditsafe::Namespace::DAT}:Address"] = {
44
- "#{Creditsafe::Namespace::DAT}:City" => city,
45
- }
46
- end
47
-
48
- unless postal_code.nil?
49
- search_criteria["#{Creditsafe::Namespace::DAT}:Address"] = {
50
- "#{Creditsafe::Namespace::DAT}:PostalCode" => postal_code,
51
- }
52
- end
53
-
54
- build_message(search_criteria)
55
- end
56
- # rubocop:enable Metrics/AbcSize
57
- # rubocop:enable Metrics/MethodLength
58
-
59
- private
60
-
61
- attr_reader :country_code, :registration_number, :city, :company_name, :postal_code,
62
- :vat_number
63
-
64
- def match_type
65
- Creditsafe::MatchType::ALLOWED[country_code.upcase.to_sym]&.first ||
66
- Creditsafe::MatchType::MATCH_BLOCK
67
- end
68
-
69
- def build_message(search_criteria)
70
- {
71
- "#{Creditsafe::Namespace::OPER}:countries" => {
72
- "#{Creditsafe::Namespace::CRED}:CountryCode" => country_code,
73
- },
74
- "#{Creditsafe::Namespace::OPER}:searchCriteria" => search_criteria,
75
- }
76
- end
77
-
78
- # rubocop:disable Metrics/CyclomaticComplexity
79
- # rubocop:disable Metrics/MethodLength
80
- # rubocop:disable Metrics/PerceivedComplexity
81
- # rubocop:disable Metrics/AbcSize
82
- def check_search_criteria(search_criteria)
83
- if search_criteria[:country_code].nil?
84
- raise ArgumentError, "country_code is a required search criteria"
85
- end
86
-
87
- unless only_one_required_criteria?(search_criteria)
88
- raise ArgumentError, "only one of registration_number, company_name or " \
89
- "vat number is required search criteria"
90
- end
91
-
92
- if search_criteria[:city] && search_criteria[:country_code] != "DE"
93
- raise ArgumentError, "city is only supported for German searches"
94
- end
95
-
96
- if search_criteria[:postal_code] && search_criteria[:country_code] != "DE"
97
- raise ArgumentError, "Postal code is only supported for German searches"
98
- end
99
-
100
- if search_criteria[:vat_number] && !Constants::Country::VAT_NUMBER_SUPPORTED.
101
- include?(search_criteria[:country_code])
102
- raise ArgumentError, "VAT number is not supported in this country"
103
- end
104
- end
105
- # rubocop:enable Metrics/AbcSize
106
- # rubocop:enable Metrics/PerceivedComplexity
107
- # rubocop:enable Metrics/MethodLength
108
- # rubocop:enable Metrics/CyclomaticComplexity
109
-
110
- def only_one_required_criteria?(search_criteria)
111
- by_registration_number = !search_criteria[:registration_number].nil?
112
- by_company_name = !search_criteria[:company_name].nil?
113
- by_vat_number = !search_criteria[:vat_number].nil?
114
-
115
- (by_registration_number ^ by_company_name ^ by_vat_number) &&
116
- !(by_registration_number && by_company_name && by_vat_number)
117
- end
118
- end
119
- end
120
- end
1
+ # frozen_string_literal: true
2
+
3
+ require "creditsafe/match_type"
4
+ require "creditsafe/namespace"
5
+ require "creditsafe/constants"
6
+
7
+ module Creditsafe
8
+ module Request
9
+ class FindCompany
10
+ def initialize(search_criteria)
11
+ check_search_criteria(search_criteria)
12
+ @country_code = search_criteria[:country_code]
13
+ @registration_number = search_criteria[:registration_number]
14
+ @company_name = search_criteria[:company_name]
15
+ @vat_number = search_criteria[:vat_number]
16
+ @city = search_criteria[:city]
17
+ @postal_code = search_criteria[:postal_code]
18
+ end
19
+
20
+ # rubocop:disable Metrics/MethodLength
21
+ # rubocop:disable Metrics/AbcSize
22
+ def message
23
+ search_criteria = {}
24
+
25
+ unless company_name.nil?
26
+ search_criteria["#{Creditsafe::Namespace::DAT}:Name"] = {
27
+ "@MatchType" => match_type,
28
+ :content! => company_name,
29
+ }
30
+ end
31
+
32
+ unless registration_number.nil?
33
+ search_criteria["#{Creditsafe::Namespace::DAT}:RegistrationNumber"] =
34
+ registration_number
35
+ end
36
+
37
+ unless vat_number.nil?
38
+ search_criteria["#{Creditsafe::Namespace::DAT}:VatNumber"] =
39
+ vat_number
40
+ end
41
+
42
+ unless city.nil?
43
+ search_criteria["#{Creditsafe::Namespace::DAT}:Address"] = {
44
+ "#{Creditsafe::Namespace::DAT}:City" => city,
45
+ }
46
+ end
47
+
48
+ unless postal_code.nil?
49
+ search_criteria["#{Creditsafe::Namespace::DAT}:Address"] = {
50
+ "#{Creditsafe::Namespace::DAT}:PostalCode" => postal_code,
51
+ }
52
+ end
53
+
54
+ build_message(search_criteria)
55
+ end
56
+ # rubocop:enable Metrics/AbcSize
57
+ # rubocop:enable Metrics/MethodLength
58
+
59
+ private
60
+
61
+ attr_reader :country_code, :registration_number, :city, :company_name, :postal_code,
62
+ :vat_number
63
+
64
+ def match_type
65
+ Creditsafe::MatchType::ALLOWED[country_code.upcase.to_sym]&.first ||
66
+ Creditsafe::MatchType::MATCH_BLOCK
67
+ end
68
+
69
+ def build_message(search_criteria)
70
+ {
71
+ "#{Creditsafe::Namespace::OPER}:countries" => {
72
+ "#{Creditsafe::Namespace::CRED}:CountryCode" => country_code,
73
+ },
74
+ "#{Creditsafe::Namespace::OPER}:searchCriteria" => search_criteria,
75
+ }
76
+ end
77
+
78
+ # rubocop:disable Metrics/CyclomaticComplexity
79
+ # rubocop:disable Metrics/MethodLength
80
+ # rubocop:disable Metrics/PerceivedComplexity
81
+ # rubocop:disable Metrics/AbcSize
82
+ def check_search_criteria(search_criteria)
83
+ if search_criteria[:country_code].nil?
84
+ raise ArgumentError, "country_code is a required search criteria"
85
+ end
86
+
87
+ unless only_one_required_criteria?(search_criteria)
88
+ raise ArgumentError, "only one of registration_number, company_name or " \
89
+ "vat number is required search criteria"
90
+ end
91
+
92
+ if search_criteria[:city] && search_criteria[:country_code] != "DE"
93
+ raise ArgumentError, "city is only supported for German searches"
94
+ end
95
+
96
+ if search_criteria[:postal_code] && search_criteria[:country_code] != "DE"
97
+ raise ArgumentError, "Postal code is only supported for German searches"
98
+ end
99
+
100
+ if search_criteria[:vat_number] && !Constants::Country::VAT_NUMBER_SUPPORTED.
101
+ include?(search_criteria[:country_code])
102
+ raise ArgumentError, "VAT number is not supported in this country"
103
+ end
104
+ end
105
+ # rubocop:enable Metrics/AbcSize
106
+ # rubocop:enable Metrics/PerceivedComplexity
107
+ # rubocop:enable Metrics/MethodLength
108
+ # rubocop:enable Metrics/CyclomaticComplexity
109
+
110
+ def only_one_required_criteria?(search_criteria)
111
+ by_registration_number = !search_criteria[:registration_number].nil?
112
+ by_company_name = !search_criteria[:company_name].nil?
113
+ by_vat_number = !search_criteria[:vat_number].nil?
114
+
115
+ (by_registration_number ^ by_company_name ^ by_vat_number) &&
116
+ !(by_registration_number && by_company_name && by_vat_number)
117
+ end
118
+ end
119
+ end
120
+ end
@@ -1,5 +1,5 @@
1
- # frozen_string_literal: true
2
-
3
- module Creditsafe
4
- VERSION = "0.6.2"
5
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Creditsafe
4
+ VERSION = "0.6.3"
5
+ end
@@ -1,431 +1,431 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
- require "creditsafe/client"
5
- require "timecop"
6
-
7
- URL = "https://webservices.creditsafe.com/GlobalData/1.3/"\
8
- "MainServiceBasic.svc"
9
-
10
- RSpec.describe(Creditsafe::Client) do
11
- notifications = []
12
- let(:username) { "AzureDiamond" }
13
- let(:password) { "hunter2" }
14
-
15
- # rubocop:disable RSpec/BeforeAfterAll
16
- before(:all) do
17
- ActiveSupport::Notifications.subscribe do |*args|
18
- notifications << ActiveSupport::Notifications::Event.new(*args)
19
- end
20
- end
21
- # rubocop:enable RSpec/BeforeAfterAll
22
-
23
- before { notifications = [] }
24
-
25
- shared_examples_for "sends notifications" do
26
- let(:time) { Time.local(1990) }
27
-
28
- it "records a SOAP event" do
29
- Timecop.freeze(time) { method_call }
30
-
31
- expect(notifications).to match(
32
- [
33
- have_attributes(
34
- name: "creditsafe.#{soap_verb}",
35
- transaction_id: match(/\A.{20}\Z/),
36
- time: time,
37
- end: time,
38
- payload: {
39
- request: be_truthy,
40
- response: be_truthy,
41
- },
42
- ),
43
- ],
44
- )
45
- end
46
- end
47
-
48
- shared_examples_for "handles api errors" do
49
- context "when an error occurs due to invalid credentials" do
50
- before do
51
- stub_request(:post, URL).to_return(
52
- body: load_fixture("error-invalid-credentials.html"),
53
- status: 401,
54
- )
55
- end
56
-
57
- it "raises an AccountError" do
58
- expect { method_call }.to raise_error(
59
- Creditsafe::AccountError, /invalid credentials/
60
- ) do |error|
61
- expect(notifications).to match(
62
- [
63
- have_attributes(
64
- name: "creditsafe.#{soap_verb}",
65
- payload: {
66
- request: be_truthy,
67
- error: error,
68
- },
69
- ),
70
- ],
71
- )
72
- end
73
- end
74
- end
75
-
76
- context "when an error occurs due to a fault" do
77
- before do
78
- stub_request(:post, URL).
79
- to_return(body: load_fixture("error-fault.xml"))
80
- end
81
-
82
- it "raises an UnknownApiError" do
83
- expect { method_call }.to raise_error(Creditsafe::UnknownApiError) do |error|
84
- expect(notifications).to match(
85
- [
86
- have_attributes(
87
- name: "creditsafe.#{soap_verb}",
88
- payload: {
89
- request: be_truthy,
90
- error: error,
91
- },
92
- ),
93
- ],
94
- )
95
- end
96
- end
97
- end
98
-
99
- context "when a timeout occurs" do
100
- before { stub_request(:post, URL).to_timeout }
101
-
102
- it "raises a TimeoutError" do
103
- expect { method_call }.to raise_error(Creditsafe::TimeoutError)
104
- end
105
- end
106
-
107
- context "when a bad gateway error occurs" do
108
- before { stub_request(:post, URL).to_raise(Excon::Errors::BadGateway) }
109
-
110
- it "raises a BadGatewayError" do
111
- expect { method_call }.to raise_error(Creditsafe::BadGatewayError)
112
- end
113
- end
114
- end
115
-
116
- describe "#new" do
117
- subject do
118
- -> { described_class.new(username: username, password: password) }
119
- end
120
-
121
- it { is_expected.to_not raise_error }
122
-
123
- context "without a username" do
124
- let(:username) { nil }
125
-
126
- it { is_expected.to raise_error(ArgumentError) }
127
- end
128
- end
129
-
130
- describe "#inspect" do
131
- subject { client.inspect }
132
-
133
- let(:client) { described_class.new(username: username, password: password) }
134
-
135
- it { is_expected.to_not include(password) }
136
- end
137
-
138
- describe "#find_company" do
139
- subject { -> { method_call } }
140
-
141
- let(:soap_verb) { "find_companies" }
142
- let(:client) { described_class.new(username: username, password: password) }
143
- let(:country_code) { "GB" }
144
- let(:registration_number) { "RN123" }
145
- let(:city) { nil }
146
- let(:postal_code) { nil }
147
- let(:company_name) { nil }
148
- let(:vat_number) { nil }
149
- let(:search_criteria) do
150
- {
151
- country_code: country_code,
152
- registration_number: registration_number,
153
- company_name: company_name,
154
- vat_number: vat_number,
155
- city: city,
156
- postal_code: postal_code,
157
- }.reject { |_, v| v.nil? }
158
- end
159
-
160
- let(:find_company) { client.find_company(search_criteria) }
161
- let(:method_call) { find_company }
162
-
163
- before do
164
- stub_request(:post, URL).to_return(
165
- body: load_fixture("find-companies-successful.xml"),
166
- status: 200,
167
- )
168
- end
169
-
170
- it { is_expected.to_not raise_error }
171
-
172
- context "without a country_code" do
173
- let(:country_code) { nil }
174
-
175
- it { is_expected.to raise_error(ArgumentError) }
176
- end
177
-
178
- context "without a registration_number" do
179
- let(:registration_number) { nil }
180
-
181
- it { is_expected.to raise_error(ArgumentError) }
182
- end
183
-
184
- context "with a city" do
185
- let(:city) { "Berlin" }
186
-
187
- it { is_expected.to raise_error(ArgumentError) }
188
-
189
- context "in Germany" do
190
- let(:country_code) { "DE" }
191
-
192
- it { is_expected.to_not raise_error }
193
- end
194
- end
195
-
196
- context "with a postal_code" do
197
- let(:postal_code) { "41199" }
198
-
199
- it { is_expected.to raise_error(ArgumentError) }
200
-
201
- context "in Germany" do
202
- let(:country_code) { "DE" }
203
-
204
- it { is_expected.to_not raise_error }
205
- end
206
- end
207
-
208
- context "with a company name" do
209
- let(:country_code) { "FR" }
210
- let(:registration_number) { nil }
211
- let(:company_name) { "Mimes Inc" }
212
-
213
- it { is_expected.to_not raise_error }
214
-
215
- it "selects a valid match type for the country code" do
216
- find_company
217
-
218
- request = a_request(:post, URL).with do |req|
219
- body = Nokogiri::XML(req.body)
220
- expect(body.xpath("//dat:Name").first.attributes["MatchType"].value).
221
- to eq("MatchBeginning")
222
- end
223
-
224
- expect(request).to have_been_made
225
- end
226
- end
227
-
228
- context "with a vat_number" do
229
- let(:vat_number) { "942404110" }
230
- let(:registration_number) { nil }
231
-
232
- it { is_expected.to raise_error(ArgumentError) }
233
-
234
- context "in US" do
235
- let(:country_code) { "US" }
236
-
237
- it { is_expected.to_not raise_error }
238
- end
239
- end
240
-
241
- context "with different invalid required criteria combinations used" do
242
- context "with registration number and company name" do
243
- let(:company_name) { "Mimes Inc" }
244
-
245
- it { is_expected.to raise_error(ArgumentError) }
246
- end
247
-
248
- context "with registration number and vat_number" do
249
- let(:vat_number) { "942404110" }
250
-
251
- it { is_expected.to raise_error(ArgumentError) }
252
- end
253
-
254
- context "with company name and vat_number" do
255
- let(:registration_number) { nil }
256
- let(:company_name) { "Mimes Inc" }
257
- let(:vat_number) { "942404110" }
258
-
259
- it { is_expected.to raise_error(ArgumentError) }
260
- end
261
-
262
- context "with all three required criteria" do
263
- let(:company_name) { "Mimes Inc" }
264
- let(:vat_number) { "942404110" }
265
-
266
- it { is_expected.to raise_error(ArgumentError) }
267
- end
268
-
269
- context "with no required criteria" do
270
- let(:registration_number) { nil }
271
-
272
- it { is_expected.to raise_error(ArgumentError) }
273
- end
274
- end
275
-
276
- it "requests the company deatils" do
277
- find_company
278
- expect(a_request(:post, URL).with do |req|
279
- expect(CompareXML.equivalent?(
280
- Nokogiri::XML(req.body),
281
- load_xml_fixture("find-companies-request.xml"),
282
- verbose: true,
283
- )).to eq([])
284
- end).to have_been_made
285
- end
286
-
287
- it "returns the company details" do
288
- expect(find_company).
289
- to eq(:name => "GOCARDLESS LTD",
290
- :type => "Ltd",
291
- :status => "Active",
292
- :registration_number => "07495895",
293
- :address => {
294
- simple_value: "338-346, GOSWELL, LONDON",
295
- postal_code: "EC1V7LQ",
296
- },
297
- :available_report_types => { available_report_type: "Full" },
298
- :available_languages => { available_language: "EN" },
299
- :@date_of_latest_accounts => "2014-01-31T00:00:00Z",
300
- :@online_reports => "true",
301
- :@monitoring => "false",
302
- :@country => "GB",
303
- :@id => "GB003/0/07495895")
304
- end
305
-
306
- include_examples "sends notifications"
307
- include_examples "handles api errors"
308
-
309
- context "when no companies are found" do
310
- before do
311
- stub_request(:post, URL).to_return(
312
- body: load_fixture("find-companies-none-found.xml"),
313
- status: 200,
314
- )
315
- end
316
-
317
- it "returns nil" do
318
- expect(find_company).to be_nil
319
- end
320
-
321
- it "records a nil payload" do
322
- find_company
323
- expect(notifications).to match([have_attributes(
324
- payload: {
325
- request: be_truthy,
326
- response: {
327
- find_companies_response: include(
328
- find_companies_result: include(
329
- messages: {
330
- message: include(
331
- "There are no results matching specified criteria.",
332
- ),
333
- },
334
- companies: be_nil,
335
- ),
336
- ),
337
- },
338
- },
339
- )])
340
- end
341
- end
342
-
343
- context "when an error occurs with further details" do
344
- before do
345
- stub_request(:post, URL).to_return(
346
- body: load_fixture("find-companies-error.xml"),
347
- status: 200,
348
- )
349
- end
350
-
351
- it "gives a useful error, with the specific error in the response" do
352
- expect { method_call }.to raise_error(
353
- Creditsafe::RequestError,
354
- "Invalid operation parameters (Invalid countries list specified.)",
355
- )
356
- end
357
-
358
- context "with further details provided in the response" do
359
- before do
360
- stub_request(:post, URL).to_return(
361
- body: load_fixture("find-companies-error-no-text.xml"),
362
- status: 200,
363
- )
364
- end
365
-
366
- it "gives a useful error, with the specific error in the response" do
367
- expect { method_call }.to raise_error(
368
- Creditsafe::RequestError,
369
- "Invalid operation parameters",
370
- )
371
- end
372
- end
373
- end
374
- end
375
-
376
- describe "#company_report" do
377
- before do
378
- stub_request(:post, URL).to_return(
379
- body: load_fixture("company-report-successful.xml"),
380
- status: 200,
381
- )
382
- end
383
-
384
- let(:soap_verb) { "retrieve_company_online_report" }
385
- let(:client) { described_class.new(username: username, password: password) }
386
- let(:custom_data) { { foo: "bar", bar: "baz" } }
387
- let(:company_report) do
388
- client.company_report("GB003/0/07495895", custom_data: custom_data)
389
- end
390
- let(:method_call) { company_report }
391
-
392
- it "requests the company details" do
393
- company_report
394
- request = a_request(:post, URL).with do |req|
395
- expect(
396
- CompareXML.equivalent?(
397
- Nokogiri::XML(req.body),
398
- load_xml_fixture("company-report-request.xml"),
399
- verbose: true,
400
- ),
401
- ).to eq([])
402
- end
403
-
404
- expect(request).to have_been_made
405
- end
406
-
407
- it "returns the company details" do
408
- expect(company_report).to include(:company_summary)
409
- end
410
-
411
- include_examples "sends notifications"
412
- include_examples "handles api errors"
413
-
414
- context "when a report is unavailable" do
415
- before do
416
- stub_request(:post, URL).
417
- to_return(body: load_fixture("company-report-not-found.xml"))
418
- end
419
-
420
- it "raises an error" do
421
- expect { company_report }.to raise_error(Creditsafe::DataError)
422
- end
423
-
424
- it "gives a useful error message" do
425
- expect { company_report }.to raise_error(
426
- Creditsafe::DataError, /Report unavailable/
427
- )
428
- end
429
- end
430
- end
431
- end
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+ require "creditsafe/client"
5
+ require "timecop"
6
+
7
+ URL = "https://webservices.creditsafe.com/GlobalData/1.3/"\
8
+ "MainServiceBasic.svc"
9
+
10
+ RSpec.describe(Creditsafe::Client) do
11
+ notifications = []
12
+ let(:username) { "AzureDiamond" }
13
+ let(:password) { "hunter2" }
14
+
15
+ # rubocop:disable RSpec/BeforeAfterAll
16
+ before(:all) do
17
+ ActiveSupport::Notifications.subscribe do |*args|
18
+ notifications << ActiveSupport::Notifications::Event.new(*args)
19
+ end
20
+ end
21
+ # rubocop:enable RSpec/BeforeAfterAll
22
+
23
+ before { notifications = [] }
24
+
25
+ shared_examples_for "sends notifications" do
26
+ let(:time) { Time.local(1990) }
27
+
28
+ it "records a SOAP event" do
29
+ Timecop.freeze(time) { method_call }
30
+
31
+ expect(notifications).to match(
32
+ [
33
+ have_attributes(
34
+ name: "creditsafe.#{soap_verb}",
35
+ transaction_id: match(/\A.{20}\Z/),
36
+ time: time,
37
+ end: time,
38
+ payload: {
39
+ request: be_truthy,
40
+ response: be_truthy,
41
+ },
42
+ ),
43
+ ],
44
+ )
45
+ end
46
+ end
47
+
48
+ shared_examples_for "handles api errors" do
49
+ context "when an error occurs due to invalid credentials" do
50
+ before do
51
+ stub_request(:post, URL).to_return(
52
+ body: load_fixture("error-invalid-credentials.html"),
53
+ status: 401,
54
+ )
55
+ end
56
+
57
+ it "raises an AccountError" do
58
+ expect { method_call }.to raise_error(
59
+ Creditsafe::AccountError, /invalid credentials/
60
+ ) do |error|
61
+ expect(notifications).to match(
62
+ [
63
+ have_attributes(
64
+ name: "creditsafe.#{soap_verb}",
65
+ payload: {
66
+ request: be_truthy,
67
+ error: error,
68
+ },
69
+ ),
70
+ ],
71
+ )
72
+ end
73
+ end
74
+ end
75
+
76
+ context "when an error occurs due to a fault" do
77
+ before do
78
+ stub_request(:post, URL).
79
+ to_return(body: load_fixture("error-fault.xml"))
80
+ end
81
+
82
+ it "raises an UnknownApiError" do
83
+ expect { method_call }.to raise_error(Creditsafe::UnknownApiError) do |error|
84
+ expect(notifications).to match(
85
+ [
86
+ have_attributes(
87
+ name: "creditsafe.#{soap_verb}",
88
+ payload: {
89
+ request: be_truthy,
90
+ error: error,
91
+ },
92
+ ),
93
+ ],
94
+ )
95
+ end
96
+ end
97
+ end
98
+
99
+ context "when a timeout occurs" do
100
+ before { stub_request(:post, URL).to_timeout }
101
+
102
+ it "raises a TimeoutError" do
103
+ expect { method_call }.to raise_error(Creditsafe::TimeoutError)
104
+ end
105
+ end
106
+
107
+ context "when a bad gateway error occurs" do
108
+ before { stub_request(:post, URL).to_raise(Excon::Errors::BadGateway) }
109
+
110
+ it "raises a BadGatewayError" do
111
+ expect { method_call }.to raise_error(Creditsafe::BadGatewayError)
112
+ end
113
+ end
114
+ end
115
+
116
+ describe "#new" do
117
+ subject do
118
+ -> { described_class.new(username: username, password: password) }
119
+ end
120
+
121
+ it { is_expected.to_not raise_error }
122
+
123
+ context "without a username" do
124
+ let(:username) { nil }
125
+
126
+ it { is_expected.to raise_error(ArgumentError) }
127
+ end
128
+ end
129
+
130
+ describe "#inspect" do
131
+ subject { client.inspect }
132
+
133
+ let(:client) { described_class.new(username: username, password: password) }
134
+
135
+ it { is_expected.to_not include(password) }
136
+ end
137
+
138
+ describe "#find_company" do
139
+ subject { -> { method_call } }
140
+
141
+ let(:soap_verb) { "find_companies" }
142
+ let(:client) { described_class.new(username: username, password: password) }
143
+ let(:country_code) { "GB" }
144
+ let(:registration_number) { "RN123" }
145
+ let(:city) { nil }
146
+ let(:postal_code) { nil }
147
+ let(:company_name) { nil }
148
+ let(:vat_number) { nil }
149
+ let(:search_criteria) do
150
+ {
151
+ country_code: country_code,
152
+ registration_number: registration_number,
153
+ company_name: company_name,
154
+ vat_number: vat_number,
155
+ city: city,
156
+ postal_code: postal_code,
157
+ }.reject { |_, v| v.nil? }
158
+ end
159
+
160
+ let(:find_company) { client.find_company(search_criteria) }
161
+ let(:method_call) { find_company }
162
+
163
+ before do
164
+ stub_request(:post, URL).to_return(
165
+ body: load_fixture("find-companies-successful.xml"),
166
+ status: 200,
167
+ )
168
+ end
169
+
170
+ it { is_expected.to_not raise_error }
171
+
172
+ context "without a country_code" do
173
+ let(:country_code) { nil }
174
+
175
+ it { is_expected.to raise_error(ArgumentError) }
176
+ end
177
+
178
+ context "without a registration_number" do
179
+ let(:registration_number) { nil }
180
+
181
+ it { is_expected.to raise_error(ArgumentError) }
182
+ end
183
+
184
+ context "with a city" do
185
+ let(:city) { "Berlin" }
186
+
187
+ it { is_expected.to raise_error(ArgumentError) }
188
+
189
+ context "in Germany" do
190
+ let(:country_code) { "DE" }
191
+
192
+ it { is_expected.to_not raise_error }
193
+ end
194
+ end
195
+
196
+ context "with a postal_code" do
197
+ let(:postal_code) { "41199" }
198
+
199
+ it { is_expected.to raise_error(ArgumentError) }
200
+
201
+ context "in Germany" do
202
+ let(:country_code) { "DE" }
203
+
204
+ it { is_expected.to_not raise_error }
205
+ end
206
+ end
207
+
208
+ context "with a company name" do
209
+ let(:country_code) { "FR" }
210
+ let(:registration_number) { nil }
211
+ let(:company_name) { "Mimes Inc" }
212
+
213
+ it { is_expected.to_not raise_error }
214
+
215
+ it "selects a valid match type for the country code" do
216
+ find_company
217
+
218
+ request = a_request(:post, URL).with do |req|
219
+ body = Nokogiri::XML(req.body)
220
+ expect(body.xpath("//dat:Name").first.attributes["MatchType"].value).
221
+ to eq("MatchBeginning")
222
+ end
223
+
224
+ expect(request).to have_been_made
225
+ end
226
+ end
227
+
228
+ context "with a vat_number" do
229
+ let(:vat_number) { "942404110" }
230
+ let(:registration_number) { nil }
231
+
232
+ it { is_expected.to raise_error(ArgumentError) }
233
+
234
+ context "in US" do
235
+ let(:country_code) { "US" }
236
+
237
+ it { is_expected.to_not raise_error }
238
+ end
239
+ end
240
+
241
+ context "with different invalid required criteria combinations used" do
242
+ context "with registration number and company name" do
243
+ let(:company_name) { "Mimes Inc" }
244
+
245
+ it { is_expected.to raise_error(ArgumentError) }
246
+ end
247
+
248
+ context "with registration number and vat_number" do
249
+ let(:vat_number) { "942404110" }
250
+
251
+ it { is_expected.to raise_error(ArgumentError) }
252
+ end
253
+
254
+ context "with company name and vat_number" do
255
+ let(:registration_number) { nil }
256
+ let(:company_name) { "Mimes Inc" }
257
+ let(:vat_number) { "942404110" }
258
+
259
+ it { is_expected.to raise_error(ArgumentError) }
260
+ end
261
+
262
+ context "with all three required criteria" do
263
+ let(:company_name) { "Mimes Inc" }
264
+ let(:vat_number) { "942404110" }
265
+
266
+ it { is_expected.to raise_error(ArgumentError) }
267
+ end
268
+
269
+ context "with no required criteria" do
270
+ let(:registration_number) { nil }
271
+
272
+ it { is_expected.to raise_error(ArgumentError) }
273
+ end
274
+ end
275
+
276
+ it "requests the company deatils" do
277
+ find_company
278
+ expect(a_request(:post, URL).with do |req|
279
+ expect(CompareXML.equivalent?(
280
+ Nokogiri::XML(req.body),
281
+ load_xml_fixture("find-companies-request.xml"),
282
+ verbose: true,
283
+ )).to eq([])
284
+ end).to have_been_made
285
+ end
286
+
287
+ it "returns the company details" do
288
+ expect(find_company).
289
+ to eq(:name => "GOCARDLESS LTD",
290
+ :type => "Ltd",
291
+ :status => "Active",
292
+ :registration_number => "07495895",
293
+ :address => {
294
+ simple_value: "338-346, GOSWELL, LONDON",
295
+ postal_code: "EC1V7LQ",
296
+ },
297
+ :available_report_types => { available_report_type: "Full" },
298
+ :available_languages => { available_language: "EN" },
299
+ :@date_of_latest_accounts => "2014-01-31T00:00:00Z",
300
+ :@online_reports => "true",
301
+ :@monitoring => "false",
302
+ :@country => "GB",
303
+ :@id => "GB003/0/07495895")
304
+ end
305
+
306
+ include_examples "sends notifications"
307
+ include_examples "handles api errors"
308
+
309
+ context "when no companies are found" do
310
+ before do
311
+ stub_request(:post, URL).to_return(
312
+ body: load_fixture("find-companies-none-found.xml"),
313
+ status: 200,
314
+ )
315
+ end
316
+
317
+ it "returns nil" do
318
+ expect(find_company).to be_nil
319
+ end
320
+
321
+ it "records a nil payload" do
322
+ find_company
323
+ expect(notifications).to match([have_attributes(
324
+ payload: {
325
+ request: be_truthy,
326
+ response: {
327
+ find_companies_response: include(
328
+ find_companies_result: include(
329
+ messages: {
330
+ message: include(
331
+ "There are no results matching specified criteria.",
332
+ ),
333
+ },
334
+ companies: be_nil,
335
+ ),
336
+ ),
337
+ },
338
+ },
339
+ )])
340
+ end
341
+ end
342
+
343
+ context "when an error occurs with further details" do
344
+ before do
345
+ stub_request(:post, URL).to_return(
346
+ body: load_fixture("find-companies-error.xml"),
347
+ status: 200,
348
+ )
349
+ end
350
+
351
+ it "gives a useful error, with the specific error in the response" do
352
+ expect { method_call }.to raise_error(
353
+ Creditsafe::RequestError,
354
+ "Invalid operation parameters (Invalid countries list specified.)",
355
+ )
356
+ end
357
+
358
+ context "with further details provided in the response" do
359
+ before do
360
+ stub_request(:post, URL).to_return(
361
+ body: load_fixture("find-companies-error-no-text.xml"),
362
+ status: 200,
363
+ )
364
+ end
365
+
366
+ it "gives a useful error, with the specific error in the response" do
367
+ expect { method_call }.to raise_error(
368
+ Creditsafe::RequestError,
369
+ "Invalid operation parameters",
370
+ )
371
+ end
372
+ end
373
+ end
374
+ end
375
+
376
+ describe "#company_report" do
377
+ before do
378
+ stub_request(:post, URL).to_return(
379
+ body: load_fixture("company-report-successful.xml"),
380
+ status: 200,
381
+ )
382
+ end
383
+
384
+ let(:soap_verb) { "retrieve_company_online_report" }
385
+ let(:client) { described_class.new(username: username, password: password) }
386
+ let(:custom_data) { { foo: "bar", bar: "baz" } }
387
+ let(:company_report) do
388
+ client.company_report("GB003/0/07495895", custom_data: custom_data)
389
+ end
390
+ let(:method_call) { company_report }
391
+
392
+ it "requests the company details" do
393
+ company_report
394
+ request = a_request(:post, URL).with do |req|
395
+ expect(
396
+ CompareXML.equivalent?(
397
+ Nokogiri::XML(req.body),
398
+ load_xml_fixture("company-report-request.xml"),
399
+ verbose: true,
400
+ ),
401
+ ).to eq([])
402
+ end
403
+
404
+ expect(request).to have_been_made
405
+ end
406
+
407
+ it "returns the company details" do
408
+ expect(company_report).to include(:company_summary)
409
+ end
410
+
411
+ include_examples "sends notifications"
412
+ include_examples "handles api errors"
413
+
414
+ context "when a report is unavailable" do
415
+ before do
416
+ stub_request(:post, URL).
417
+ to_return(body: load_fixture("company-report-not-found.xml"))
418
+ end
419
+
420
+ it "raises an error" do
421
+ expect { company_report }.to raise_error(Creditsafe::DataError)
422
+ end
423
+
424
+ it "gives a useful error message" do
425
+ expect { company_report }.to raise_error(
426
+ Creditsafe::DataError, /Report unavailable/
427
+ )
428
+ end
429
+ end
430
+ end
431
+ end