addressfinder 1.9.1 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +31 -0
- data/CHANGELOG.md +7 -0
- data/README.md +23 -1
- data/lib/addressfinder/bulk.rb +8 -0
- data/lib/addressfinder/v1/base.rb +71 -0
- data/lib/addressfinder/v1/email/verification.rb +16 -0
- data/lib/addressfinder/v1/phone/verification.rb +16 -0
- data/lib/addressfinder/version.rb +1 -1
- data/lib/addressfinder.rb +10 -0
- data/spec/lib/addressfinder/bulk_spec.rb +92 -0
- data/spec/lib/addressfinder/v1/email/verification_spec.rb +148 -0
- data/spec/lib/addressfinder/v1/phone/verification_spec.rb +144 -0
- data/spec/lib/addressfinder/v2/au/verification_spec.rb +1 -1
- data/spec/lib/addressfinder_spec.rb +20 -0
- metadata +11 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8d84bdab006a12ff6f18d90d33986cf03172e1d8fedc52ffca604795631b8420
|
4
|
+
data.tar.gz: 933d6673ee1271440c17801ac410047a44761d6e1539de3f7c211cec9ee16bd7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 27b217ad366baf5b6e46d02ab14410a30133d7adfefb06292a92daedc271266ed7139d83be5d14cdee4a3e1128ee18d6604049cd41405f243496bfc24dc13cf6
|
7
|
+
data.tar.gz: 26861692d4d8936ae1f5a581390afb2d04cc1f9a870b43488e6f0e76d4bb33caacdbe92e28ee13e8b92960d1dc5bb410d0a01ffdba6fe83c4917214afbbbdf57
|
@@ -0,0 +1,31 @@
|
|
1
|
+
name: Ruby
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [ "master" ]
|
6
|
+
pull_request:
|
7
|
+
branches: [ "master" ]
|
8
|
+
|
9
|
+
permissions:
|
10
|
+
contents: read
|
11
|
+
|
12
|
+
jobs:
|
13
|
+
test:
|
14
|
+
|
15
|
+
runs-on: ubuntu-latest
|
16
|
+
strategy:
|
17
|
+
matrix:
|
18
|
+
ruby-version: ['2.6', '2.7', '3.0', '3.1']
|
19
|
+
|
20
|
+
steps:
|
21
|
+
- uses: actions/checkout@v3
|
22
|
+
- name: Set up Ruby
|
23
|
+
# To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
|
24
|
+
# change this to (see https://github.com/ruby/setup-ruby#versioning):
|
25
|
+
# uses: ruby/setup-ruby@v1
|
26
|
+
uses: ruby/setup-ruby@0a29871fe2b0200a17a4497bae54fe5df0d973aa # v1.115.3
|
27
|
+
with:
|
28
|
+
ruby-version: ${{ matrix.ruby-version }}
|
29
|
+
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
30
|
+
- name: Run tests
|
31
|
+
run: bundle exec rake
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
# AddressFinder 1.10.0 (August 2023) #
|
2
|
+
|
3
|
+
* Add support for Email Verification
|
4
|
+
* Add support for Phone Verification
|
5
|
+
* Add support for Bulk Email Verification
|
6
|
+
* Add support for Bulk Phone Verification
|
7
|
+
|
1
8
|
# AddressFinder 1.9.1 (October 2022) #
|
2
9
|
|
3
10
|
* Add missing kwarg `**` for ruby 3
|
data/README.md
CHANGED
@@ -157,6 +157,28 @@ rescue AddressFinder::RequestRejectedError => e
|
|
157
157
|
end
|
158
158
|
```
|
159
159
|
|
160
|
+
#### Email Verification
|
161
|
+
```ruby
|
162
|
+
begin
|
163
|
+
result = AddressFinder.email_verification(email: 'john.doe')
|
164
|
+
$stdout.puts "This email address is verified: #{result.is_verified}"
|
165
|
+
rescue AddressFinder::RequestRejectedError => e
|
166
|
+
response = JSON.parse(e.body)
|
167
|
+
$stdout.puts response['message']
|
168
|
+
end
|
169
|
+
```
|
170
|
+
|
171
|
+
#### Phone Verification
|
172
|
+
```ruby
|
173
|
+
begin
|
174
|
+
result = AddressFinder.phone_verification(phone_number: '1800 152 363', default_country_code: 'AU')
|
175
|
+
$stdout.puts "This phone number is verified: #{result.is_verified}"
|
176
|
+
rescue AddressFinder::RequestRejectedError => e
|
177
|
+
response = JSON.parse(e.body)
|
178
|
+
$stdout.puts response['message']
|
179
|
+
end
|
180
|
+
```
|
181
|
+
|
160
182
|
## Advanced Usage
|
161
183
|
|
162
184
|
#### Bulk Operations
|
@@ -164,7 +186,7 @@ end
|
|
164
186
|
If you have a series of API requests, you can use the
|
165
187
|
bulk method to re-use the HTTP connection.
|
166
188
|
|
167
|
-
**Note:** The bulk method is currently only available for Address Verification (`#verification`).
|
189
|
+
**Note:** The bulk method is currently only available for Address Verification, Email Verification and Phone Verification (`#verification`, `#email_verification`, `#phone_verifiction`).
|
168
190
|
|
169
191
|
```ruby
|
170
192
|
AddressFinder.bulk do |af|
|
data/lib/addressfinder/bulk.rb
CHANGED
@@ -36,6 +36,14 @@ module AddressFinder
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
+
def email_verification(args={})
|
40
|
+
AddressFinder::V1::Email::Verification.new(**args.merge(http: http)).perform.result
|
41
|
+
end
|
42
|
+
|
43
|
+
def phone_verification(args={})
|
44
|
+
AddressFinder::V1::Phone::Verification.new(**args.merge(http: http)).perform.result
|
45
|
+
end
|
46
|
+
|
39
47
|
private
|
40
48
|
|
41
49
|
attr_reader :http, :verification_version, :default_country
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
module AddressFinder
|
4
|
+
module V1
|
5
|
+
class Base
|
6
|
+
attr_reader :result
|
7
|
+
|
8
|
+
def initialize(params:, path:, http:)
|
9
|
+
@params = params
|
10
|
+
@params[:domain] ||= config.domain if config.domain
|
11
|
+
@params[:key] ||= config.api_key
|
12
|
+
@params[:secret] ||= config.api_secret
|
13
|
+
@params[:format] ||= 'json'
|
14
|
+
|
15
|
+
@path = path
|
16
|
+
@http = http
|
17
|
+
end
|
18
|
+
|
19
|
+
def perform
|
20
|
+
build_request
|
21
|
+
execute_request
|
22
|
+
build_result
|
23
|
+
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
attr_reader :request_uri, :params, :http, :path
|
30
|
+
attr_accessor :response_body, :response_status
|
31
|
+
attr_writer :result
|
32
|
+
|
33
|
+
def build_request
|
34
|
+
@request_uri = "#{path}?#{encoded_params}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def encoded_params
|
38
|
+
Util.encode_and_join_params(params)
|
39
|
+
end
|
40
|
+
|
41
|
+
def execute_request
|
42
|
+
request = Net::HTTP::Get.new(request_uri)
|
43
|
+
|
44
|
+
response = http.request(request)
|
45
|
+
|
46
|
+
self.response_body = response.body
|
47
|
+
self.response_status = response.code
|
48
|
+
end
|
49
|
+
|
50
|
+
def build_result
|
51
|
+
case response_status
|
52
|
+
when '200'
|
53
|
+
self.result = Result.new(response_hash)
|
54
|
+
else
|
55
|
+
raise AddressFinder::RequestRejectedError.new(response_status, response_body)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def response_hash
|
60
|
+
@_response_hash ||= MultiJson.load(response_body)
|
61
|
+
end
|
62
|
+
|
63
|
+
def config
|
64
|
+
@_config ||= AddressFinder.configuration
|
65
|
+
end
|
66
|
+
|
67
|
+
class Result < OpenStruct
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'addressfinder/v1/base'
|
2
|
+
|
3
|
+
module AddressFinder
|
4
|
+
module V1
|
5
|
+
module Email
|
6
|
+
class Verification < AddressFinder::V1::Base
|
7
|
+
attr_reader :result
|
8
|
+
|
9
|
+
def initialize(email:, http:, **args)
|
10
|
+
params = {email: email}.merge(args)
|
11
|
+
super(params: params, path: "/api/email/v1/verification", http: http)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'addressfinder/v1/base'
|
2
|
+
|
3
|
+
module AddressFinder
|
4
|
+
module V1
|
5
|
+
module Phone
|
6
|
+
class Verification < AddressFinder::V1::Base
|
7
|
+
attr_reader :result
|
8
|
+
|
9
|
+
def initialize(phone_number:, default_country_code:, http:, **args)
|
10
|
+
params = {phone_number: phone_number, default_country_code: default_country_code}.merge(args)
|
11
|
+
super(params: params, path: "/api/phone/v1/verification", http: http)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/addressfinder.rb
CHANGED
@@ -9,6 +9,8 @@ require 'addressfinder/address_info'
|
|
9
9
|
require 'addressfinder/address_search'
|
10
10
|
require 'addressfinder/address_autocomplete'
|
11
11
|
require 'addressfinder/bulk'
|
12
|
+
require 'addressfinder/v1/email/verification'
|
13
|
+
require 'addressfinder/v1/phone/verification'
|
12
14
|
require 'addressfinder/errors'
|
13
15
|
require 'addressfinder/util'
|
14
16
|
require 'addressfinder/http'
|
@@ -61,6 +63,14 @@ module AddressFinder
|
|
61
63
|
AddressFinder::AddressInfo.new(params: args, http: AddressFinder::HTTP.new(configuration)).perform.result
|
62
64
|
end
|
63
65
|
|
66
|
+
def email_verification(args={})
|
67
|
+
AddressFinder::V1::Email::Verification.new(**args.merge(http: AddressFinder::HTTP.new(configuration))).perform.result
|
68
|
+
end
|
69
|
+
|
70
|
+
def phone_verification(args={})
|
71
|
+
AddressFinder::V1::Phone::Verification.new(**args.merge(http: AddressFinder::HTTP.new(configuration))).perform.result
|
72
|
+
end
|
73
|
+
|
64
74
|
def bulk(&block)
|
65
75
|
AddressFinder::Bulk.new(http: AddressFinder::HTTP.new(configuration), verification_version: configuration.verification_version, default_country: configuration.default_country, &block).perform
|
66
76
|
end
|
@@ -111,5 +111,97 @@ RSpec.describe AddressFinder::Bulk do
|
|
111
111
|
AddressFinder::Bulk.new(http: http, verification_version: "v2", default_country: 'nz', &block).perform
|
112
112
|
end
|
113
113
|
end
|
114
|
+
|
115
|
+
context "email verification with 3 requests in the provided block" do
|
116
|
+
let(:response){ double(:response, body: %Q({"success": true}), code: "200") }
|
117
|
+
let(:block){
|
118
|
+
Proc.new do |proxy|
|
119
|
+
proxy.email_verification(email: "john.doe@addressfinder.com")
|
120
|
+
proxy.email_verification(email: "jane.doe@addressfinder.com")
|
121
|
+
proxy.email_verification(email: "tom.doe@addressfinder.com")
|
122
|
+
end
|
123
|
+
}
|
124
|
+
|
125
|
+
it "uses 1 http connection" do
|
126
|
+
expect(net_http).to receive(:do_start).once.and_call_original
|
127
|
+
expect(net_http).to receive(:transport_request).exactly(3).times.and_return(response)
|
128
|
+
expect(net_http).to receive(:do_finish).once.and_call_original
|
129
|
+
AddressFinder::Bulk.new(http: http, verification_version: 'v1', default_country: 'nz', &block).perform
|
130
|
+
end
|
131
|
+
|
132
|
+
it "calls the correct class with v1 verification and nz default" do
|
133
|
+
allow(net_http).to receive(:do_start).once.and_call_original
|
134
|
+
allow(net_http).to receive(:transport_request).exactly(3).times.and_return(response)
|
135
|
+
allow(net_http).to receive(:do_finish).once.and_call_original
|
136
|
+
expect(AddressFinder::V1::Email::Verification).to receive(:new).exactly(3).times.and_call_original
|
137
|
+
AddressFinder::Bulk.new(http: http, verification_version: 'v1', default_country: 'nz', &block).perform
|
138
|
+
end
|
139
|
+
|
140
|
+
it "calls the correct class without a verification version or default country" do
|
141
|
+
allow(net_http).to receive(:do_start).once.and_call_original
|
142
|
+
allow(net_http).to receive(:transport_request).exactly(3).times.and_return(response)
|
143
|
+
allow(net_http).to receive(:do_finish).once.and_call_original
|
144
|
+
expect(AddressFinder::V1::Email::Verification).to receive(:new).exactly(3).times.and_call_original
|
145
|
+
AddressFinder::Bulk.new(http: http, verification_version: nil, default_country: nil, &block).perform
|
146
|
+
end
|
147
|
+
|
148
|
+
it "re-establishes the http connection and continues where we left off when a Net::OpenTimeout, Net::ReadTimeout or SocketError is raised" do
|
149
|
+
expect(http).to receive(:re_establish_connection).exactly(3).times.and_call_original
|
150
|
+
expect(net_http).to receive(:do_start).exactly(4).times.and_call_original
|
151
|
+
expect(net_http).to receive(:transport_request).once.and_return(response) # john.doe@addressfinder.com (success)
|
152
|
+
expect(net_http).to receive(:transport_request).once.and_raise(Net::OpenTimeout) # jane.doe@addressfinder.com (error)
|
153
|
+
expect(net_http).to receive(:transport_request).once.and_raise(Net::ReadTimeout) # Retry jane.doe@addressfinder.com (error)
|
154
|
+
expect(net_http).to receive(:transport_request).once.and_raise(SocketError) # Retry jane.doe@addressfinder.com (error)
|
155
|
+
expect(net_http).to receive(:transport_request).exactly(2).and_return(response) # Retry jane.doe@addressfinder.com (success) & tom.doe@addressfinder.com (success)
|
156
|
+
expect(net_http).to receive(:do_finish).exactly(4).times.and_call_original
|
157
|
+
AddressFinder::Bulk.new(http: http, verification_version: 'v1', default_country: 'nz', &block).perform
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
context "phone verification with 3 requests in the provided block" do
|
162
|
+
let(:response){ double(:response, body: %Q({"success": true}), code: "200") }
|
163
|
+
let(:block){
|
164
|
+
Proc.new do |proxy|
|
165
|
+
proxy.phone_verification(phone_number: "+64274673830", default_country_code: "AU")
|
166
|
+
proxy.phone_verification(phone_number: "1800 152 363", default_country_code: "AU")
|
167
|
+
proxy.phone_verification(phone_number: "0274673830", default_country_code: "NZ")
|
168
|
+
end
|
169
|
+
}
|
170
|
+
|
171
|
+
it "uses 1 http connection" do
|
172
|
+
expect(net_http).to receive(:do_start).once.and_call_original
|
173
|
+
expect(net_http).to receive(:transport_request).exactly(3).times.and_return(response)
|
174
|
+
expect(net_http).to receive(:do_finish).once.and_call_original
|
175
|
+
AddressFinder::Bulk.new(http: http, verification_version: 'v1', default_country: 'nz', &block).perform
|
176
|
+
end
|
177
|
+
|
178
|
+
it "calls the correct class with v1 verification and nz default" do
|
179
|
+
allow(net_http).to receive(:do_start).once.and_call_original
|
180
|
+
allow(net_http).to receive(:transport_request).exactly(3).times.and_return(response)
|
181
|
+
allow(net_http).to receive(:do_finish).once.and_call_original
|
182
|
+
expect(AddressFinder::V1::Phone::Verification).to receive(:new).exactly(3).times.and_call_original
|
183
|
+
AddressFinder::Bulk.new(http: http, verification_version: 'v1', default_country: 'nz', &block).perform
|
184
|
+
end
|
185
|
+
|
186
|
+
it "calls the correct class without a verification version or default country" do
|
187
|
+
allow(net_http).to receive(:do_start).once.and_call_original
|
188
|
+
allow(net_http).to receive(:transport_request).exactly(3).times.and_return(response)
|
189
|
+
allow(net_http).to receive(:do_finish).once.and_call_original
|
190
|
+
expect(AddressFinder::V1::Phone::Verification).to receive(:new).exactly(3).times.and_call_original
|
191
|
+
AddressFinder::Bulk.new(http: http, verification_version: nil, default_country: nil, &block).perform
|
192
|
+
end
|
193
|
+
|
194
|
+
it "re-establishes the http connection and continues where we left off when a Net::OpenTimeout, Net::ReadTimeout or SocketError is raised" do
|
195
|
+
expect(http).to receive(:re_establish_connection).exactly(3).times.and_call_original
|
196
|
+
expect(net_http).to receive(:do_start).exactly(4).times.and_call_original
|
197
|
+
expect(net_http).to receive(:transport_request).once.and_return(response) # +64274673830 (success)
|
198
|
+
expect(net_http).to receive(:transport_request).once.and_raise(Net::OpenTimeout) # 1800 152 363 (error)
|
199
|
+
expect(net_http).to receive(:transport_request).once.and_raise(Net::ReadTimeout) # Retry 1800 152 363 (error)
|
200
|
+
expect(net_http).to receive(:transport_request).once.and_raise(SocketError) # Retry 1800 152 363 (error)
|
201
|
+
expect(net_http).to receive(:transport_request).exactly(2).and_return(response) # Retry 1800 152 363 (success) & 0274673830 (success)
|
202
|
+
expect(net_http).to receive(:do_finish).exactly(4).times.and_call_original
|
203
|
+
AddressFinder::Bulk.new(http: http, verification_version: 'v1', default_country: 'nz', &block).perform
|
204
|
+
end
|
205
|
+
end
|
114
206
|
end
|
115
207
|
end
|
@@ -0,0 +1,148 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
RSpec.describe AddressFinder::V1::Email::Verification do
|
4
|
+
before do
|
5
|
+
AddressFinder.configure do |af|
|
6
|
+
af.api_key = "XXX"
|
7
|
+
af.api_secret = "YYY"
|
8
|
+
af.timeout = 5
|
9
|
+
af.retries = 3
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:verification_module){ AddressFinder::V1::Email::Verification.new(**args) }
|
14
|
+
let(:http){ AddressFinder::HTTP.new(AddressFinder.configuration) }
|
15
|
+
let(:net_http){ http.send(:net_http) }
|
16
|
+
|
17
|
+
describe "#execute_request" do
|
18
|
+
let(:args){ {email: "john.doe@addressfinder.com", http: http} }
|
19
|
+
|
20
|
+
before do
|
21
|
+
WebMock.allow_net_connect!(net_http_connect_on_start: true)
|
22
|
+
allow(http).to receive(:sleep)
|
23
|
+
allow(verification_module).to receive(:request_uri).and_return("/test/path")
|
24
|
+
expect(http).to_not receive(:re_establish_connection)
|
25
|
+
end
|
26
|
+
|
27
|
+
after do
|
28
|
+
WebMock.disable_net_connect!
|
29
|
+
end
|
30
|
+
|
31
|
+
subject(:execute_request){ verification_module.send(:execute_request) }
|
32
|
+
|
33
|
+
it "retries an errored request another time before succeeding" do
|
34
|
+
expect(net_http).to receive(:do_start).twice.and_call_original
|
35
|
+
expect(net_http).to receive(:transport_request).once.and_raise(Net::OpenTimeout)
|
36
|
+
expect(net_http).to receive(:transport_request).once.and_return(double(:response, body: "OK", code: "200"))
|
37
|
+
expect(net_http).to receive(:do_finish).twice.and_call_original
|
38
|
+
execute_request
|
39
|
+
end
|
40
|
+
|
41
|
+
it "re-raises a Net::OpenTimeout error after 3 retries" do
|
42
|
+
expect(net_http).to receive(:do_start).exactly(4).times.and_call_original
|
43
|
+
expect(net_http).to receive(:transport_request).exactly(4).times.and_raise(Net::OpenTimeout)
|
44
|
+
expect(net_http).to receive(:do_finish).exactly(4).times.and_call_original
|
45
|
+
expect{execute_request}.to raise_error(Net::OpenTimeout)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "re-raises a Net::ReadTimeout error after 3 retries" do
|
49
|
+
expect(net_http).to receive(:do_start).exactly(4).times.and_call_original
|
50
|
+
expect(net_http).to receive(:transport_request).exactly(4).times.and_raise(Net::ReadTimeout)
|
51
|
+
expect(net_http).to receive(:do_finish).exactly(4).times.and_call_original
|
52
|
+
expect{execute_request}.to raise_error(Net::ReadTimeout)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "re-raises a SocketError error after 3 retries" do
|
56
|
+
expect(net_http).to receive(:do_start).exactly(4).times.and_call_original
|
57
|
+
expect(net_http).to receive(:transport_request).exactly(4).times.and_raise(SocketError)
|
58
|
+
expect(net_http).to receive(:do_finish).exactly(4).times.and_call_original
|
59
|
+
expect{execute_request}.to raise_error(SocketError)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "#build_request" do
|
64
|
+
subject(:request_uri){ verification_module.send(:build_request) }
|
65
|
+
|
66
|
+
context "with email argument" do
|
67
|
+
let(:args){ {email: "john.doe@addressfinder.com", http: http} }
|
68
|
+
|
69
|
+
it { expect(request_uri).to eq("/api/email/v1/verification?email=john.doe%40addressfinder.com&key=XXX&secret=YYY&format=json") }
|
70
|
+
end
|
71
|
+
|
72
|
+
context "with email and format arguments" do
|
73
|
+
let(:args){ {email: "john.doe@addressfinder.com", format: "xml", http: http} }
|
74
|
+
|
75
|
+
it { expect(request_uri).to eq("/api/email/v1/verification?email=john.doe%40addressfinder.com&format=xml&key=XXX&secret=YYY") }
|
76
|
+
end
|
77
|
+
|
78
|
+
context "with a reserved character in the email" do
|
79
|
+
let(:args){ {email: "john=doe@addressfinder.com", http: http} }
|
80
|
+
|
81
|
+
it { expect(request_uri).to eq("/api/email/v1/verification?email=john%3Ddoe%40addressfinder.com&key=XXX&secret=YYY&format=json") }
|
82
|
+
end
|
83
|
+
|
84
|
+
context "with a key override" do
|
85
|
+
let(:args){ {email: "john.doe@addressfinder.com", key: "AAA", http: http} }
|
86
|
+
|
87
|
+
it { expect(request_uri).to eq("/api/email/v1/verification?email=john.doe%40addressfinder.com&key=AAA&secret=YYY&format=json") }
|
88
|
+
end
|
89
|
+
|
90
|
+
context "with a secret override" do
|
91
|
+
let(:args){ {email: "john.doe@addressfinder.com", secret: "BBB", http: http} }
|
92
|
+
|
93
|
+
it { expect(request_uri).to eq("/api/email/v1/verification?email=john.doe%40addressfinder.com&secret=BBB&key=XXX&format=json") }
|
94
|
+
end
|
95
|
+
|
96
|
+
context "with a domain given" do
|
97
|
+
let(:args){ {email: "john.doe@addressfinder.com", domain: "testdomain.com", http: http} }
|
98
|
+
|
99
|
+
it { expect(request_uri).to eq("/api/email/v1/verification?email=john.doe%40addressfinder.com&domain=testdomain.com&key=XXX&secret=YYY&format=json") }
|
100
|
+
|
101
|
+
context "given in the AF configuration" do
|
102
|
+
let(:args){ {email: "john.doe@addressfinder.com", http: http} }
|
103
|
+
|
104
|
+
it "should use the config domain if set" do
|
105
|
+
AddressFinder.configuration.domain = "anotherdomain.com"
|
106
|
+
expect(request_uri).to eq("/api/email/v1/verification?email=john.doe%40addressfinder.com&domain=anotherdomain.com&key=XXX&secret=YYY&format=json")
|
107
|
+
AddressFinder.configuration.domain = nil # set back to nil after
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
context "with a all arguments included in request" do
|
113
|
+
let(:args){ {email: "john.doe@addressfinder.com", domain: "mysite.com", key: "AAA", secret: "BBB", format: "json", http: http} }
|
114
|
+
|
115
|
+
it { expect(request_uri).to eq("/api/email/v1/verification?email=john.doe%40addressfinder.com&domain=mysite.com&key=AAA&secret=BBB&format=json") }
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe "#build_result" do
|
120
|
+
let(:args){ {email: "ignored", http: nil} }
|
121
|
+
|
122
|
+
before do
|
123
|
+
verification_module.send("response_body=", body)
|
124
|
+
verification_module.send("response_status=", status)
|
125
|
+
end
|
126
|
+
|
127
|
+
subject(:result){ verification_module.send(:build_result) }
|
128
|
+
|
129
|
+
context "with a successful verification" do
|
130
|
+
let(:body){ '{"email_account": "john.doe", "email_domain": "addressfinder.com", "is_verified": true, "success": true}' }
|
131
|
+
let(:status){ "200" }
|
132
|
+
|
133
|
+
it { expect(result.class).to eq(AddressFinder::V1::Email::Verification::Result) }
|
134
|
+
it { expect(result.is_verified).to eq(true) }
|
135
|
+
it { expect(result.email_account).to eq("john.doe") }
|
136
|
+
end
|
137
|
+
|
138
|
+
context "with an unsuccessful verification" do
|
139
|
+
let(:body){ '{"email_account": "jane.doe", "email_domain": "addressfinder.com", "is_verified": false, "not_verified_reason": "The email account does not exist", "success": true}' }
|
140
|
+
let(:status){ "200" }
|
141
|
+
|
142
|
+
it { expect(result.class).to eq(AddressFinder::V1::Email::Verification::Result) }
|
143
|
+
it { expect(result.is_verified).to eq(false) }
|
144
|
+
it { expect(result.email_account).to eq("jane.doe") }
|
145
|
+
it { expect(result.not_verified_reason).to eq("The email account does not exist") }
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
RSpec.describe AddressFinder::V1::Phone::Verification do
|
4
|
+
before do
|
5
|
+
AddressFinder.configure do |af|
|
6
|
+
af.api_key = "XXX"
|
7
|
+
af.api_secret = "YYY"
|
8
|
+
af.timeout = 5
|
9
|
+
af.retries = 3
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:verification_module){ AddressFinder::V1::Phone::Verification.new(**args) }
|
14
|
+
let(:http){ AddressFinder::HTTP.new(AddressFinder.configuration) }
|
15
|
+
let(:net_http){ http.send(:net_http) }
|
16
|
+
|
17
|
+
describe "#execute_request" do
|
18
|
+
let(:args){ {phone_number: "1800 152 363", default_country_code: "AU", http: http} }
|
19
|
+
|
20
|
+
before do
|
21
|
+
WebMock.allow_net_connect!(net_http_connect_on_start: true)
|
22
|
+
allow(http).to receive(:sleep)
|
23
|
+
allow(verification_module).to receive(:request_uri).and_return("/test/path")
|
24
|
+
expect(http).to_not receive(:re_establish_connection)
|
25
|
+
end
|
26
|
+
|
27
|
+
after do
|
28
|
+
WebMock.disable_net_connect!
|
29
|
+
end
|
30
|
+
|
31
|
+
subject(:execute_request){ verification_module.send(:execute_request) }
|
32
|
+
|
33
|
+
it "retries an errored request another time before succeeding" do
|
34
|
+
expect(net_http).to receive(:do_start).twice.and_call_original
|
35
|
+
expect(net_http).to receive(:transport_request).once.and_raise(Net::OpenTimeout)
|
36
|
+
expect(net_http).to receive(:transport_request).once.and_return(double(:response, body: "OK", code: "200"))
|
37
|
+
expect(net_http).to receive(:do_finish).twice.and_call_original
|
38
|
+
execute_request
|
39
|
+
end
|
40
|
+
|
41
|
+
it "re-raises a Net::OpenTimeout error after 3 retries" do
|
42
|
+
expect(net_http).to receive(:do_start).exactly(4).times.and_call_original
|
43
|
+
expect(net_http).to receive(:transport_request).exactly(4).times.and_raise(Net::OpenTimeout)
|
44
|
+
expect(net_http).to receive(:do_finish).exactly(4).times.and_call_original
|
45
|
+
expect{execute_request}.to raise_error(Net::OpenTimeout)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "re-raises a Net::ReadTimeout error after 3 retries" do
|
49
|
+
expect(net_http).to receive(:do_start).exactly(4).times.and_call_original
|
50
|
+
expect(net_http).to receive(:transport_request).exactly(4).times.and_raise(Net::ReadTimeout)
|
51
|
+
expect(net_http).to receive(:do_finish).exactly(4).times.and_call_original
|
52
|
+
expect{execute_request}.to raise_error(Net::ReadTimeout)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "re-raises a SocketError error after 3 retries" do
|
56
|
+
expect(net_http).to receive(:do_start).exactly(4).times.and_call_original
|
57
|
+
expect(net_http).to receive(:transport_request).exactly(4).times.and_raise(SocketError)
|
58
|
+
expect(net_http).to receive(:do_finish).exactly(4).times.and_call_original
|
59
|
+
expect{execute_request}.to raise_error(SocketError)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "#build_request" do
|
64
|
+
subject(:request_uri){ verification_module.send(:build_request) }
|
65
|
+
|
66
|
+
context "with phone number and default country code arguments" do
|
67
|
+
let(:args){ {phone_number: "1800 152 363", default_country_code: "AU", http: http} }
|
68
|
+
|
69
|
+
it { expect(request_uri).to eq("/api/phone/v1/verification?phone_number=1800+152+363&default_country_code=AU&key=XXX&secret=YYY&format=json") }
|
70
|
+
end
|
71
|
+
|
72
|
+
context "with a reserved character in the phone number" do
|
73
|
+
let(:args){ {phone_number: "1800= 152 363", default_country_code: "AU", http: http} }
|
74
|
+
|
75
|
+
it { expect(request_uri).to eq("/api/phone/v1/verification?phone_number=1800%3D+152+363&default_country_code=AU&key=XXX&secret=YYY&format=json") }
|
76
|
+
end
|
77
|
+
|
78
|
+
context "with a key override" do
|
79
|
+
let(:args){ {phone_number: "1800 152 363", default_country_code: "AU", key: "AAA", http: http} }
|
80
|
+
|
81
|
+
it { expect(request_uri).to eq("/api/phone/v1/verification?phone_number=1800+152+363&default_country_code=AU&key=AAA&secret=YYY&format=json") }
|
82
|
+
end
|
83
|
+
|
84
|
+
context "with a secret override" do
|
85
|
+
let(:args){ {phone_number: "1800 152 363", default_country_code: "AU", secret: "BBB", http: http} }
|
86
|
+
|
87
|
+
it { expect(request_uri).to eq("/api/phone/v1/verification?phone_number=1800+152+363&default_country_code=AU&secret=BBB&key=XXX&format=json") }
|
88
|
+
end
|
89
|
+
|
90
|
+
context "with a domain given" do
|
91
|
+
let(:args){ {phone_number: "1800 152 363", default_country_code: "AU", domain: "testdomain.com", http: http} }
|
92
|
+
|
93
|
+
it { expect(request_uri).to eq("/api/phone/v1/verification?phone_number=1800+152+363&default_country_code=AU&domain=testdomain.com&key=XXX&secret=YYY&format=json") }
|
94
|
+
|
95
|
+
context "given in the AF configuration" do
|
96
|
+
let(:args){ {phone_number: "1800 152 363", default_country_code: "AU", http: http} }
|
97
|
+
|
98
|
+
it "should use the config domain if set" do
|
99
|
+
AddressFinder.configuration.domain = "anotherdomain.com"
|
100
|
+
expect(request_uri).to eq("/api/phone/v1/verification?phone_number=1800+152+363&default_country_code=AU&domain=anotherdomain.com&key=XXX&secret=YYY&format=json")
|
101
|
+
AddressFinder.configuration.domain = nil # set back to nil after
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context "with a all arguments included in request" do
|
107
|
+
let(:args){ {phone_number: "1800 152 363", default_country_code: "NZ", allowed_country_codes: "AU,NZ", mobile_only: true, timeout: "10", domain: "mysite.com", key: "AAA", secret: "BBB", format: "xml", http: http} }
|
108
|
+
|
109
|
+
it { expect(request_uri).to eq("/api/phone/v1/verification?phone_number=1800+152+363&default_country_code=NZ&allowed_country_codes=AU%2CNZ&mobile_only=true&timeout=10&domain=mysite.com&key=AAA&secret=BBB&format=xml") }
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe "#build_result" do
|
114
|
+
let(:args){ {phone_number: "ignored", default_country_code: "ignored", http: nil} }
|
115
|
+
|
116
|
+
before do
|
117
|
+
verification_module.send("response_body=", body)
|
118
|
+
verification_module.send("response_status=", status)
|
119
|
+
end
|
120
|
+
|
121
|
+
subject(:result){ verification_module.send(:build_result) }
|
122
|
+
|
123
|
+
context "with a successful verification" do
|
124
|
+
let(:body){ '{"raw_international": "+611800152353", "line_type": "toll_free", "line_status": "disconnected", "is_verified": true, "success": true}' }
|
125
|
+
let(:status){ "200" }
|
126
|
+
|
127
|
+
it { expect(result.class).to eq(AddressFinder::V1::Phone::Verification::Result) }
|
128
|
+
it { expect(result.is_verified).to eq(true) }
|
129
|
+
it { expect(result.raw_international).to eq("+611800152353") }
|
130
|
+
it { expect(result.line_type).to eq("toll_free") }
|
131
|
+
it { expect(result.line_status).to eq("disconnected") }
|
132
|
+
end
|
133
|
+
|
134
|
+
context "with an unsuccessful verification" do
|
135
|
+
let(:body){ '{"is_verified": false, "not_verified_reason": "Phone number format is incorrect", "not_verified_code": "INVALID_FORMAT", "success": true}' }
|
136
|
+
let(:status){ "200" }
|
137
|
+
|
138
|
+
it { expect(result.class).to eq(AddressFinder::V1::Phone::Verification::Result) }
|
139
|
+
it { expect(result.is_verified).to eq(false) }
|
140
|
+
it { expect(result.not_verified_code).to eq("INVALID_FORMAT") }
|
141
|
+
it { expect(result.not_verified_reason).to eq("Phone number format is incorrect") }
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -116,7 +116,7 @@ RSpec.describe AddressFinder::V2::Au::Verification do
|
|
116
116
|
|
117
117
|
it 'should use the config domain if set' do
|
118
118
|
AddressFinder.configuration.domain = 'anotherdomain.com'
|
119
|
-
|
119
|
+
expect(request_uri).to eq('/api/au/address/v2/verification?q=123&domain=anotherdomain.com&key=XXX&secret=YYY&format=json')
|
120
120
|
AddressFinder.configuration.domain = nil # set back to nil after
|
121
121
|
end
|
122
122
|
end
|
@@ -71,4 +71,24 @@ RSpec.describe AddressFinder do
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
end
|
74
|
+
|
75
|
+
context "#email_verification" do
|
76
|
+
subject(:verification) { AddressFinder.email_verification(args) }
|
77
|
+
let(:args){ {email: "john.doe@addressfinder.com"} }
|
78
|
+
|
79
|
+
it "calls the email verification class" do
|
80
|
+
expect(AddressFinder::V1::Email::Verification).to receive_message_chain(:new, :perform, :result)
|
81
|
+
subject
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context "#phone_verification" do
|
86
|
+
subject(:verification) { AddressFinder.phone_verification(args) }
|
87
|
+
let(:args){ {phone_number: "1800 152 363", default_country_code: "AU"} }
|
88
|
+
|
89
|
+
it "calls the phone verification class" do
|
90
|
+
expect(AddressFinder::V1::Phone::Verification).to receive_message_chain(:new, :perform, :result)
|
91
|
+
subject
|
92
|
+
end
|
93
|
+
end
|
74
94
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: addressfinder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nigel Ramsay
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date:
|
15
|
+
date: 2023-08-30 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: multi_json
|
@@ -109,6 +109,7 @@ executables: []
|
|
109
109
|
extensions: []
|
110
110
|
extra_rdoc_files: []
|
111
111
|
files:
|
112
|
+
- ".github/workflows/ruby.yml"
|
112
113
|
- ".gitignore"
|
113
114
|
- ".travis.yml"
|
114
115
|
- CHANGELOG.md
|
@@ -131,6 +132,9 @@ files:
|
|
131
132
|
- lib/addressfinder/location_info.rb
|
132
133
|
- lib/addressfinder/location_search.rb
|
133
134
|
- lib/addressfinder/util.rb
|
135
|
+
- lib/addressfinder/v1/base.rb
|
136
|
+
- lib/addressfinder/v1/email/verification.rb
|
137
|
+
- lib/addressfinder/v1/phone/verification.rb
|
134
138
|
- lib/addressfinder/v2/au/verification.rb
|
135
139
|
- lib/addressfinder/verification.rb
|
136
140
|
- lib/addressfinder/version.rb
|
@@ -141,6 +145,8 @@ files:
|
|
141
145
|
- spec/lib/addressfinder/location_info_spec.rb
|
142
146
|
- spec/lib/addressfinder/location_search_spec.rb
|
143
147
|
- spec/lib/addressfinder/util_spec.rb
|
148
|
+
- spec/lib/addressfinder/v1/email/verification_spec.rb
|
149
|
+
- spec/lib/addressfinder/v1/phone/verification_spec.rb
|
144
150
|
- spec/lib/addressfinder/v2/au/verification_spec.rb
|
145
151
|
- spec/lib/addressfinder/verification_spec.rb
|
146
152
|
- spec/lib/addressfinder_spec.rb
|
@@ -164,7 +170,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
164
170
|
- !ruby/object:Gem::Version
|
165
171
|
version: '0'
|
166
172
|
requirements: []
|
167
|
-
rubygems_version: 3.1.
|
173
|
+
rubygems_version: 3.1.4
|
168
174
|
signing_key:
|
169
175
|
specification_version: 4
|
170
176
|
summary: Provides easy access to AddressFinder APIs
|
@@ -176,6 +182,8 @@ test_files:
|
|
176
182
|
- spec/lib/addressfinder/location_info_spec.rb
|
177
183
|
- spec/lib/addressfinder/location_search_spec.rb
|
178
184
|
- spec/lib/addressfinder/util_spec.rb
|
185
|
+
- spec/lib/addressfinder/v1/email/verification_spec.rb
|
186
|
+
- spec/lib/addressfinder/v1/phone/verification_spec.rb
|
179
187
|
- spec/lib/addressfinder/v2/au/verification_spec.rb
|
180
188
|
- spec/lib/addressfinder/verification_spec.rb
|
181
189
|
- spec/lib/addressfinder_spec.rb
|