creditsafe 0.6.2 → 0.6.3

Sign up to get free protection for your applications and to get access to all the features.
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