onfido 1.1.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/gem-push.yml +31 -0
  3. data/.github/workflows/ruby.yml +25 -0
  4. data/.rubocop.yml +5 -49
  5. data/.travis.yml +2 -8
  6. data/CHANGELOG.md +26 -1
  7. data/Gemfile +2 -0
  8. data/README.md +37 -148
  9. data/lib/onfido.rb +3 -3
  10. data/lib/onfido/api.rb +18 -12
  11. data/lib/onfido/errors/connection_error.rb +2 -0
  12. data/lib/onfido/errors/onfido_error.rb +2 -0
  13. data/lib/onfido/errors/request_error.rb +2 -0
  14. data/lib/onfido/errors/server_error.rb +2 -0
  15. data/lib/onfido/options.rb +38 -0
  16. data/lib/onfido/resource.rb +48 -59
  17. data/lib/onfido/resources/address.rb +3 -4
  18. data/lib/onfido/resources/applicant.rb +2 -0
  19. data/lib/onfido/resources/check.rb +6 -0
  20. data/lib/onfido/resources/document.rb +2 -0
  21. data/lib/onfido/resources/extraction.rb +2 -0
  22. data/lib/onfido/resources/live_photo.rb +2 -0
  23. data/lib/onfido/resources/live_video.rb +2 -0
  24. data/lib/onfido/resources/report.rb +2 -0
  25. data/lib/onfido/resources/sdk_token.rb +2 -0
  26. data/lib/onfido/resources/webhook.rb +4 -2
  27. data/lib/onfido/version.rb +3 -1
  28. data/onfido.gemspec +5 -6
  29. data/spec/integrations/address_spec.rb +4 -2
  30. data/spec/integrations/applicant_spec.rb +12 -7
  31. data/spec/integrations/check_spec.rb +17 -4
  32. data/spec/integrations/document_spec.rb +7 -3
  33. data/spec/integrations/extraction_spec.rb +6 -2
  34. data/spec/integrations/live_photo_spec.rb +7 -3
  35. data/spec/integrations/live_video_spec.rb +6 -1
  36. data/spec/integrations/report_spec.rb +6 -1
  37. data/spec/integrations/resource_spec.rb +106 -0
  38. data/spec/integrations/sdk_token_spec.rb +5 -1
  39. data/spec/integrations/webhook_spec.rb +28 -24
  40. data/spec/onfido/api_spec.rb +14 -25
  41. data/spec/onfido/connection_error_spec.rb +4 -2
  42. data/spec/onfido/options_spec.rb +39 -0
  43. data/spec/onfido/request_error_spec.rb +4 -2
  44. data/spec/spec_helper.rb +3 -5
  45. data/spec/support/fake_onfido_api.rb +63 -49
  46. data/spec/support/fixtures/applicant.json +1 -1
  47. data/spec/support/fixtures/check.json +1 -1
  48. data/spec/support/fixtures/checks.json +1 -1
  49. data/spec/support/fixtures/document.json +1 -1
  50. data/spec/support/fixtures/documents.json +2 -2
  51. data/spec/support/fixtures/live_photo.json +2 -2
  52. data/spec/support/fixtures/live_photos.json +4 -4
  53. data/spec/support/fixtures/live_video.json +2 -2
  54. data/spec/support/fixtures/live_videos.json +2 -2
  55. data/spec/support/fixtures/report.json +1 -1
  56. data/spec/support/fixtures/reports.json +2 -2
  57. data/spec/support/fixtures/webhook.json +1 -1
  58. data/spec/support/fixtures/webhooks.json +2 -2
  59. metadata +16 -33
  60. data/Rakefile +0 -1
  61. data/lib/onfido/configuration.rb +0 -47
  62. data/lib/onfido/null_logger.rb +0 -5
  63. data/spec/integrations/exceptions_spec.rb +0 -73
  64. data/spec/onfido/resource_spec.rb +0 -133
  65. data/spec/onfido_spec.rb +0 -83
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  describe Onfido::Address do
2
- subject(:api) { Onfido::API.new }
4
+ include_context 'fake onfido api'
3
5
 
4
6
  describe '#all' do
5
7
  it 'returns the addresses matching the postcode' do
6
- response = api.address.all('SW1 4NG')
8
+ response = onfido.address.all('SW1 4NG')
7
9
 
8
10
  expect(response['addresses'].count).to eq(2)
9
11
  end
@@ -1,5 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  describe Onfido::Applicant do
2
- subject(:applicant) { described_class.new }
4
+ include_context 'fake onfido api'
5
+
6
+ subject(:applicant) { onfido.applicant }
7
+
3
8
  let(:applicant_id) { '61f659cb-c90b-4067-808a-6136b5c01351' }
4
9
  let(:params) do
5
10
  {
@@ -29,9 +34,9 @@ describe Onfido::Applicant do
29
34
 
30
35
  it 'serializes the payload correctly' do
31
36
  WebMock.after_request do |request_signature, _response|
32
- if request_signature.uri.path == 'v3/applicants'
33
- expect(Rack::Utils.parse_nested_query(request_signature.body)).
34
- to eq(params)
37
+ if request_signature.uri.path == 'v3.2/applicants'
38
+ expect(Rack::Utils.parse_nested_query(request_signature.body))
39
+ .to eq(params)
35
40
  end
36
41
  end
37
42
  end
@@ -93,13 +98,13 @@ describe Onfido::Applicant do
93
98
  it 'returns an error' do
94
99
  applicant_id = 'a2fb9c62-ab10-4898-a8ec-342c4b552ad5'
95
100
 
96
- expect { applicant.restore(applicant_id) }.to raise_error { |error|
101
+ expect { applicant.restore(applicant_id) }.to raise_error do |error|
97
102
  expect(error).to be_a(Onfido::RequestError)
98
103
  expect(error.message).to eq('There was a validation error on this request')
99
104
  expect(error.fields).to eq(
100
- "Applicant a2fb9c62-ab10-4898-a8ec-342c4b552ad5 is not scheduled for deletion"
105
+ 'Applicant a2fb9c62-ab10-4898-a8ec-342c4b552ad5 is not scheduled for deletion'
101
106
  )
102
- }
107
+ end
103
108
  end
104
109
  end
105
110
  end
@@ -1,5 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  describe Onfido::Check do
2
- subject(:check) { described_class.new }
4
+ include_context 'fake onfido api'
5
+
6
+ subject(:check) { onfido.check }
7
+
3
8
  let(:applicant_id) { '61f659cb-c90b-4067-808a-6136b5c01351' }
4
9
  let(:check_id) { '8546921-123123-123123' }
5
10
 
@@ -20,7 +25,7 @@ describe Onfido::Check do
20
25
  expect(response['id']).to eq(check_id)
21
26
  end
22
27
 
23
- it "returns report_ids" do
28
+ it 'returns report_ids' do
24
29
  response = check.find(check_id)
25
30
 
26
31
  expect(response['report_ids'].first).to be_a(String)
@@ -36,16 +41,24 @@ describe Onfido::Check do
36
41
  end
37
42
  end
38
43
 
39
- it "returns report_ids" do
44
+ it 'returns report_ids' do
40
45
  response = check.all(applicant_id)
41
46
 
42
47
  expect(response['checks'].first['report_ids'].first).to be_a(String)
43
48
  end
44
49
  end
45
50
 
46
- describe "#resume" do
51
+ describe '#resume' do
47
52
  it 'returns success response' do
48
53
  expect { check.resume(check_id) }.not_to raise_error
49
54
  end
50
55
  end
56
+
57
+ describe '#download' do
58
+ it 'returns the file data' do
59
+ response = check.download(check_id)
60
+
61
+ expect(response).not_to be_nil
62
+ end
63
+ end
51
64
  end
@@ -1,7 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'tempfile'
2
4
 
3
5
  describe Onfido::Document do
4
- subject(:document) { described_class.new }
6
+ include_context 'fake onfido api'
7
+
8
+ subject(:document) { onfido.document }
5
9
 
6
10
  describe '#create' do
7
11
  let(:params) do
@@ -32,8 +36,8 @@ describe Onfido::Document do
32
36
  let(:file) { 'https://onfido.com/images/logo.png' }
33
37
 
34
38
  it 'raises an ArgumentError' do
35
- expect { document.create(**params) }.
36
- to raise_error(ArgumentError, /must be a `File`-like object/)
39
+ expect { document.create(**params) }
40
+ .to raise_error(ArgumentError, /must be a `File`-like object/)
37
41
  end
38
42
  end
39
43
  end
@@ -1,7 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'tempfile'
2
4
 
3
5
  describe Onfido::Extraction do
4
- subject(:extraction) { described_class.new }
6
+ include_context 'fake onfido api'
7
+
8
+ subject(:extraction) { onfido.extraction }
5
9
 
6
10
  describe '#create' do
7
11
  let(:params) do
@@ -11,7 +15,7 @@ describe Onfido::Extraction do
11
15
  end
12
16
 
13
17
  it 'creates a new extraction' do
14
- response = extraction.create(params)
18
+ response = extraction.create(**params)
15
19
 
16
20
  expect(response['document_id']).to eq('7568415-123123-123123')
17
21
  end
@@ -1,7 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'tempfile'
2
4
 
3
5
  describe Onfido::LivePhoto do
4
- subject(:live_photo) { described_class.new }
6
+ include_context 'fake onfido api'
7
+
8
+ subject(:live_photo) { onfido.live_photo }
5
9
 
6
10
  describe '#create' do
7
11
  let(:params) { { applicant_id: '123456', file: file } }
@@ -25,8 +29,8 @@ describe Onfido::LivePhoto do
25
29
  let(:file) { 'https://onfido.com/images/photo.jpg' }
26
30
 
27
31
  it 'raises an ArgumentError' do
28
- expect { live_photo.create(**params) }.
29
- to raise_error(ArgumentError, /must be a `File`-like object/)
32
+ expect { live_photo.create(**params) }
33
+ .to raise_error(ArgumentError, /must be a `File`-like object/)
30
34
  end
31
35
  end
32
36
  end
@@ -1,7 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'tempfile'
2
4
 
3
5
  describe Onfido::LiveVideo do
4
- subject(:live_video) { described_class.new }
6
+ include_context 'fake onfido api'
7
+
8
+ subject(:live_video) { onfido.live_video }
9
+
5
10
  let(:live_video_id) { 'c9701e9b-83aa-442f-995b-20320ee8fb01' }
6
11
 
7
12
  describe '#find' do
@@ -1,5 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  describe Onfido::Report do
2
- subject(:report) { described_class.new }
4
+ include_context 'fake onfido api'
5
+
6
+ subject(:report) { onfido.report }
7
+
3
8
  describe '#find' do
4
9
  it 'returns a report for an existing check' do
5
10
  report_id = '6951786-123123-422221'
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ class TestResource < Onfido::Resource
4
+ def get(path:)
5
+ super(path: path)
6
+ end
7
+ end
8
+
9
+ describe Onfido::Resource do
10
+ include_context 'fake onfido api'
11
+
12
+ subject(:resource) { TestResource.new(Onfido::Options.new(api_key: 'test', region: :eu)) }
13
+
14
+ context '4xx response' do
15
+ it 'raises a custom error' do
16
+ path = '4xx_response'
17
+
18
+ expect { resource.get(path: path) }
19
+ .to raise_error(Onfido::RequestError, 'Something went wrong')
20
+ end
21
+ end
22
+
23
+ context 'unexpected error format' do
24
+ it 'raises a custom error' do
25
+ path = 'unexpected_error_format'
26
+
27
+ expect { resource.get(path: path) }
28
+ .to raise_error(Onfido::RequestError, /response code was 400/)
29
+ end
30
+ end
31
+
32
+ context 'unparseable JSON 5xx' do
33
+ it 'raises a server error' do
34
+ path = 'unparseable_response'
35
+
36
+ expect { resource.get(path: path) }
37
+ .to raise_error(Onfido::ServerError, /response code was 504/)
38
+ end
39
+ end
40
+
41
+ context 'timeout' do
42
+ before do
43
+ allow(RestClient::Request)
44
+ .to receive(:execute)
45
+ .and_raise(RestClient::RequestTimeout)
46
+ end
47
+
48
+ it 'raises a ConnectionError' do
49
+ expect { resource.get(path: '') }
50
+ .to raise_error(Onfido::ConnectionError, /Could not connect/)
51
+ end
52
+ end
53
+
54
+ context 'RestClient : BadGateway' do
55
+ before do
56
+ allow(RestClient::Request)
57
+ .to receive(:execute)
58
+ .and_raise(RestClient::BadGateway)
59
+ end
60
+
61
+ it 'raises a ConnectionError' do
62
+ expect { resource.get(path: '') }
63
+ .to raise_error(Onfido::ConnectionError, /Could not connect/)
64
+ end
65
+ end
66
+
67
+ context 'broken connection' do
68
+ before do
69
+ allow(RestClient::Request)
70
+ .to receive(:execute)
71
+ .and_raise(RestClient::ServerBrokeConnection)
72
+ end
73
+
74
+ it 'raises a ConnectionError' do
75
+ expect { resource.get(path: '') }
76
+ .to raise_error(Onfido::ConnectionError, /connection to the server/)
77
+ end
78
+ end
79
+
80
+ context 'bad SSL certificate' do
81
+ before do
82
+ allow(RestClient::Request)
83
+ .to receive(:execute)
84
+ .and_raise(RestClient::SSLCertificateNotVerified.new(nil))
85
+ end
86
+
87
+ it 'raises a ConnectionError' do
88
+ expect { resource.get(path: '') }
89
+ .to raise_error(Onfido::ConnectionError, /SSL certificate/)
90
+ end
91
+ end
92
+
93
+ context 'with a timeout error response' do
94
+ before do
95
+ allow_any_instance_of(RestClient::ExceptionWithResponse)
96
+ .to receive(:response).and_return(double(body: '', code: '408'))
97
+ expect(RestClient::Request).to receive(:execute)
98
+ .and_raise(RestClient::ExceptionWithResponse)
99
+ end
100
+
101
+ it 'raises a ConnectionError' do
102
+ expect { resource.get(path: '') }
103
+ .to raise_error(Onfido::ConnectionError)
104
+ end
105
+ end
106
+ end
@@ -1,5 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  describe Onfido::SdkToken do
2
- subject(:sdk_token) { described_class.new }
4
+ include_context 'fake onfido api'
5
+
6
+ subject(:sdk_token) { onfido.sdk_token }
3
7
 
4
8
  describe '#create' do
5
9
  it 'creates a new SDK token for the applicant' do
@@ -1,28 +1,32 @@
1
+ # frozen_string_literal: true
2
+
1
3
  describe Onfido::Webhook do
2
- subject(:webhook) { described_class.new }
4
+ include_context 'fake onfido api'
5
+
6
+ subject(:webhook) { onfido.webhook }
3
7
 
4
- describe "#create" do
8
+ describe '#create' do
5
9
  let(:params) do
6
10
  {
7
- url: "https://webhookendpoint.url",
11
+ url: 'https://webhookendpoint.url',
8
12
  enabled: true,
9
13
  events: [
10
- "report.completed",
11
- "check.completed"
14
+ 'report.completed',
15
+ 'check.completed'
12
16
  ]
13
17
  }
14
18
  end
15
19
 
16
- it "creates the webhook" do
20
+ it 'creates the webhook' do
17
21
  response = webhook.create(**params)
18
22
 
19
23
  expect(response['id']).to_not be_nil
20
24
  end
21
25
 
22
- it "responds with the right url" do
26
+ it 'responds with the right url' do
23
27
  response = webhook.create(**params)
24
28
 
25
- expect(response["url"]).to eq params[:url]
29
+ expect(response['url']).to eq params[:url]
26
30
  end
27
31
  end
28
32
 
@@ -36,29 +40,29 @@ describe Onfido::Webhook do
36
40
  end
37
41
  end
38
42
 
39
- describe "#destroy" do
40
- it "removes the webhook" do
43
+ describe '#destroy' do
44
+ it 'removes the webhook' do
41
45
  webhook_id = 'fcb73186-0733-4f6f-9c57-d9d5ef979443'
42
46
  expect { webhook.destroy(webhook_id) }.not_to raise_error
43
47
  end
44
48
  end
45
49
 
46
- describe "#all" do
47
- it "returns all the registered webhooks" do
50
+ describe '#all' do
51
+ it 'returns all the registered webhooks' do
48
52
  response = webhook.all
49
53
 
50
- expect(response["webhooks"].count).to eq 2
54
+ expect(response['webhooks'].count).to eq 2
51
55
  end
52
56
 
53
- it "returns with id" do
57
+ it 'returns with id' do
54
58
  response = webhook.all
55
59
 
56
- expect(response["webhooks"][0]["id"]).to_not be_nil
57
- expect(response["webhooks"][1]["id"]).to_not be_nil
60
+ expect(response['webhooks'][0]['id']).to_not be_nil
61
+ expect(response['webhooks'][1]['id']).to_not be_nil
58
62
  end
59
63
  end
60
64
 
61
- describe ".valid?" do
65
+ describe '.valid?' do
62
66
  subject(:valid?) do
63
67
  described_class.valid?(request_body, request_signature, token)
64
68
  end
@@ -71,34 +75,34 @@ describe Onfido::Webhook do
71
75
 
72
76
  it { is_expected.to be(true) }
73
77
 
74
- context "with an invalid signature" do
78
+ context 'with an invalid signature' do
75
79
  let(:request_signature) do
76
80
  's21fd54ew2w1f5d15642132f3d7727ff9a32a7c87072ce514df1f6d3228bec'
77
81
  end
78
82
  it { is_expected.to be(false) }
79
83
  end
80
84
 
81
- context "with a nil request signature" do
85
+ context 'with a nil request signature' do
82
86
  let(:request_signature) { nil }
83
87
  specify { expect { valid? }.to raise_error(ArgumentError) }
84
88
  end
85
89
 
86
- context "with a token other than the one used to sign the request" do
87
- let(:token) { "quite_secret_token" }
90
+ context 'with a token other than the one used to sign the request' do
91
+ let(:token) { 'quite_secret_token' }
88
92
  it { is_expected.to be(false) }
89
93
  end
90
94
 
91
- context "with a nil token" do
95
+ context 'with a nil token' do
92
96
  let(:token) { nil }
93
97
  specify { expect { valid? }.to raise_error(ArgumentError) }
94
98
  end
95
99
 
96
- context "with a modified request body" do
100
+ context 'with a modified request body' do
97
101
  let(:request_body) { '{"bar":"baz"}' }
98
102
  it { is_expected.to be(false) }
99
103
  end
100
104
 
101
- context "with a nil request body" do
105
+ context 'with a nil request body' do
102
106
  let(:request_body) { nil }
103
107
  specify { expect { valid? }.to raise_error(ArgumentError) }
104
108
  end
@@ -1,33 +1,22 @@
1
- describe Onfido::API do
2
- subject(:api) { described_class.new }
3
-
4
- describe 'given a single-word resource' do
5
- specify { expect(api.address).to be_a(Onfido::Address) }
6
- end
1
+ # frozen_string_literal: true
7
2
 
8
- describe 'given a multi-word resource' do
9
- specify { expect(api.live_photo).to be_a(Onfido::LivePhoto) }
10
- end
11
-
12
- describe 'given an unknown resource' do
13
- specify { expect { api.blood_test }.to raise_error(NameError) }
3
+ describe Onfido::API do
4
+ before do
5
+ allow(Onfido::Options).to receive(:new).and_call_original
14
6
  end
15
7
 
16
- describe 'given no API key' do
17
- it 'uses nil for the resource API key' do
18
- expect(Onfido::Address).to receive(:new).with(nil)
19
- api.address
20
- end
8
+ let(:options) do
9
+ {
10
+ api_key: 'test',
11
+ region: :eu,
12
+ open_timeout: 1,
13
+ read_timeout: 2
14
+ }
21
15
  end
22
16
 
23
- describe 'given an API key' do
24
- let(:api_key) { 'some_key' }
25
-
26
- subject(:api) { described_class.new(api_key: api_key) }
17
+ it 'passes through options' do
18
+ described_class.new(**options)
27
19
 
28
- it 'uses that key to create the resource' do
29
- expect(Onfido::Address).to receive(:new).with(api_key)
30
- api.address
31
- end
20
+ expect(Onfido::Options).to have_received(:new).with(**options)
32
21
  end
33
22
  end