checkr-canada 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.rubocop.yml +76 -0
- data/.travis.yml +5 -0
- data/Gemfile +5 -0
- data/LICENSE.txt +21 -0
- data/README.md +140 -0
- data/Rakefile +6 -0
- data/bin/console +16 -0
- data/bin/setup +8 -0
- data/checkr-canada.gemspec +27 -0
- data/lib/checkr-canada.rb +3 -0
- data/lib/checkr/canada.rb +9 -0
- data/lib/checkr/canada/client.rb +34 -0
- data/lib/checkr/canada/entities/address.rb +51 -0
- data/lib/checkr/canada/entities/candidate.rb +113 -0
- data/lib/checkr/canada/entities/criminal_record.rb +49 -0
- data/lib/checkr/canada/entities/document.rb +48 -0
- data/lib/checkr/canada/entities/report.rb +104 -0
- data/lib/checkr/canada/ext/stringify_json_patch.rb +11 -0
- data/lib/checkr/canada/types.rb +60 -0
- data/lib/checkr/canada/version.rb +7 -0
- data/spec/cases/addresses_spec.rb +66 -0
- data/spec/cases/authentication_spec.rb +42 -0
- data/spec/cases/candidates_spec.rb +148 -0
- data/spec/cases/criminal_records_spec.rb +57 -0
- data/spec/cases/document_spec.rb +63 -0
- data/spec/cases/reports_spec.rb +150 -0
- data/spec/checkr/canada/types_spec.rb +109 -0
- data/spec/checkr/canada_spec.rb +9 -0
- data/spec/fixtures/address.json +14 -0
- data/spec/fixtures/candidate.json +24 -0
- data/spec/fixtures/candidates.json +30 -0
- data/spec/fixtures/criminal_record.json +10 -0
- data/spec/fixtures/document.json +8 -0
- data/spec/fixtures/report.json +17 -0
- data/spec/fixtures/reports.json +23 -0
- data/spec/spec_helper.rb +22 -0
- metadata +166 -0
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Checkr
|
4
|
+
module Canada
|
5
|
+
module Entities
|
6
|
+
class CriminalRecordForm < Evil::Struct
|
7
|
+
attribute :offence, Types::Strict::String
|
8
|
+
attribute :location, Types::Strict::String
|
9
|
+
attribute :sentence_date, Types::Date
|
10
|
+
end
|
11
|
+
|
12
|
+
class CriminalRecord < CriminalRecordForm
|
13
|
+
attribute :id, Types::Strict::String
|
14
|
+
attribute :object, Types::String, optional: true
|
15
|
+
attribute :uri, Types::Strict::String
|
16
|
+
attribute :created_at, Types::Json::DateTime
|
17
|
+
attribute :updated_at, Types::Json::DateTime, optional: true
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Client
|
22
|
+
operation :create_criminal_record do |_settings|
|
23
|
+
http_method :post
|
24
|
+
|
25
|
+
path do |candidate_id:, **|
|
26
|
+
"candidates/#{candidate_id}/criminal_records"
|
27
|
+
end
|
28
|
+
|
29
|
+
body format: "json", model: Entities::CriminalRecordForm
|
30
|
+
|
31
|
+
response :success, 201, format: :json, model: Entities::CriminalRecord
|
32
|
+
|
33
|
+
response :not_authorized, 401, format: :json, raise: true do
|
34
|
+
attribute :error
|
35
|
+
end
|
36
|
+
|
37
|
+
response :invalid, 400, format: :json, raise: true do
|
38
|
+
attribute :error
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
scope :criminal_records do
|
43
|
+
def create(data)
|
44
|
+
operations[:create_criminal_record].call(data)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Checkr
|
4
|
+
module Canada
|
5
|
+
module Entities
|
6
|
+
class Document < Evil::Struct
|
7
|
+
attribute :id, Types::Strict::String
|
8
|
+
attribute :object, Types::String, optional: true
|
9
|
+
attribute :filename, Types::String, optional: true
|
10
|
+
attribute :uri, Types::Strict::String
|
11
|
+
attribute :download_uri, Types::Strict::String
|
12
|
+
attribute :created_at, Types::Json::DateTime
|
13
|
+
attribute :content_type, Types::String, optional: true
|
14
|
+
attribute :filesize, Types::Int, optional: true
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class Client
|
19
|
+
operation :upload_document do |_settings|
|
20
|
+
http_method :post
|
21
|
+
|
22
|
+
path { |candidate_id:, **| "candidates/#{candidate_id}/documents" }
|
23
|
+
|
24
|
+
body format: "json" do
|
25
|
+
attribute :type, Types::DocumentType
|
26
|
+
attribute :url, Types::Strict::String
|
27
|
+
attribute :filename, Types::Strict::String, optional: true
|
28
|
+
end
|
29
|
+
|
30
|
+
response :success, 201, format: :json, model: Entities::Document
|
31
|
+
|
32
|
+
response :not_authorized, 401, format: :json, raise: true do
|
33
|
+
attribute :error
|
34
|
+
end
|
35
|
+
|
36
|
+
response :invalid, 400, format: :json, raise: true do
|
37
|
+
attribute :error
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
scope :documents do
|
42
|
+
def upload(data)
|
43
|
+
operations[:upload_document].call(data)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Checkr
|
4
|
+
module Canada
|
5
|
+
module Entities
|
6
|
+
class Report < Evil::Struct
|
7
|
+
attribute :id, Types::Strict::String
|
8
|
+
attribute :object, Types::Strict::String
|
9
|
+
attribute :uri, Types::Strict::String
|
10
|
+
attribute :package, Types::Package
|
11
|
+
attribute :status, Types::Status
|
12
|
+
attribute :adjudication, Types::String, optional: true
|
13
|
+
attribute :created_at, Types::Json::DateTime
|
14
|
+
attribute :completed_at, Types::Json::DateTime
|
15
|
+
attribute :turnaround_time, Types::Int, optional: true
|
16
|
+
attribute :account_id, Types::Strict::String, optional: true
|
17
|
+
attribute :candidate_id, Types::Strict::String, optional: true
|
18
|
+
attribute :motor_vehicle_report_id, Types::String, optional: true
|
19
|
+
attribute :national_criminal_search_id, Types::String, optional: true
|
20
|
+
attribute :criminal_record_ids, Types::Array.member(Types::Strict::String), optional: true
|
21
|
+
attribute :document_ids, Types::Array.member(Types::Strict::String), optional: true
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class Client
|
26
|
+
operation :list_reports do |_settings|
|
27
|
+
http_method :get
|
28
|
+
path { "reports" }
|
29
|
+
|
30
|
+
query do
|
31
|
+
attributes optional: true do
|
32
|
+
attribute :page
|
33
|
+
attribute :per_page
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
response :success, 200, format: :json do
|
38
|
+
attribute :object, Types::Strict::String
|
39
|
+
attribute :next_href, Types::String, optional: true
|
40
|
+
attribute :previous_href, Types::String, optional: true
|
41
|
+
attribute :count, Types::Strict::Int
|
42
|
+
attribute :data, Types::Coercible::Array.member(Entities::Report)
|
43
|
+
end
|
44
|
+
|
45
|
+
response :not_authorized, 401, format: :json, raise: true do
|
46
|
+
attribute :error
|
47
|
+
end
|
48
|
+
|
49
|
+
response :not_found, 404, format: :json, raise: true do
|
50
|
+
attribute :error
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
operation :get_report do |_settings|
|
55
|
+
http_method :get
|
56
|
+
path { |id:, **| "reports/#{id}" }
|
57
|
+
|
58
|
+
response :success, 200, format: :json, model: Entities::Report
|
59
|
+
|
60
|
+
response :not_authorized, 401, format: :json, raise: true do
|
61
|
+
attribute :error
|
62
|
+
end
|
63
|
+
|
64
|
+
response :not_found, 404, format: :json, raise: true do
|
65
|
+
attribute :message, as: :error
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
operation :create_report do |_settings|
|
70
|
+
http_method :post
|
71
|
+
|
72
|
+
path { |candidate_id:, **| "candidates/#{candidate_id}/reports" }
|
73
|
+
|
74
|
+
body format: "json" do
|
75
|
+
attribute :package, Types::Package
|
76
|
+
end
|
77
|
+
|
78
|
+
response :success, 201, format: :json, model: Entities::Report
|
79
|
+
|
80
|
+
response :not_authorized, 401, format: :json, raise: true do
|
81
|
+
attribute :error
|
82
|
+
end
|
83
|
+
|
84
|
+
response :invalid, 400, format: :json, raise: true do
|
85
|
+
attribute :error
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
scope :reports do
|
90
|
+
def all(**data)
|
91
|
+
operations[:list_reports].call(**data)
|
92
|
+
end
|
93
|
+
|
94
|
+
def get(id, data = {})
|
95
|
+
operations[:get_report].call(data.merge(id: id))
|
96
|
+
end
|
97
|
+
|
98
|
+
def create(data)
|
99
|
+
operations[:create_report].call(data)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Fix setting body to '{}' when it is blank
|
4
|
+
module StringifyJsonPatch
|
5
|
+
def build(env)
|
6
|
+
return env unless env[:format] == "json"
|
7
|
+
new_env = super
|
8
|
+
new_env.delete(:body_string) if env[:body].nil? || env[:body].empty?
|
9
|
+
new_env
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry-types"
|
4
|
+
|
5
|
+
module Checkr
|
6
|
+
module Canada
|
7
|
+
PROVINCE_CODES = %w[
|
8
|
+
AB
|
9
|
+
BC
|
10
|
+
MB
|
11
|
+
NB
|
12
|
+
NL
|
13
|
+
NT
|
14
|
+
NS
|
15
|
+
NU
|
16
|
+
ON
|
17
|
+
PE
|
18
|
+
QC
|
19
|
+
SK
|
20
|
+
YT
|
21
|
+
].freeze
|
22
|
+
|
23
|
+
# Dry types + custom types
|
24
|
+
module Types
|
25
|
+
include Dry::Types.module
|
26
|
+
|
27
|
+
Status = Strict::String.enum(
|
28
|
+
'pending', 'clear', 'consider', 'suspended'
|
29
|
+
)
|
30
|
+
|
31
|
+
Package = Strict::String.enum(
|
32
|
+
'mvr', 'criminal', 'criminal_mvr'
|
33
|
+
)
|
34
|
+
|
35
|
+
DocumentType = Strict::String.enum(
|
36
|
+
'identification', 'consent'
|
37
|
+
)
|
38
|
+
|
39
|
+
Province = Strict::String.enum(*PROVINCE_CODES)
|
40
|
+
|
41
|
+
Gender = Strict::String.enum('M', 'F')
|
42
|
+
Email = Strict::String
|
43
|
+
|
44
|
+
Date = Strict::String
|
45
|
+
.constrained(format: /\A\d{4}-\d{2}-\d{2}\z/)
|
46
|
+
.constructor do |value|
|
47
|
+
begin
|
48
|
+
date = value.to_date if value.respond_to? :to_date
|
49
|
+
date ||= ::Date.parse(value.to_s)
|
50
|
+
date.strftime "%Y-%m-%d"
|
51
|
+
rescue
|
52
|
+
raise Dry::Types::ConstraintError.new(
|
53
|
+
"#{value.inspect} cannot be coerced to date",
|
54
|
+
value
|
55
|
+
)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
describe "Addresses" do
|
6
|
+
let(:client) { Checkr::Canada::Client.new("test_api_key") }
|
7
|
+
|
8
|
+
describe "#create" do
|
9
|
+
let(:answer) do
|
10
|
+
File.read("./spec/fixtures/address.json")
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:params) do
|
14
|
+
{
|
15
|
+
candidate_id: 'abc123xyz',
|
16
|
+
street1: "Mission st",
|
17
|
+
street2: "4-2",
|
18
|
+
region: "BC",
|
19
|
+
city: "San Francisco",
|
20
|
+
postal_code: "BC341",
|
21
|
+
start_date: "2017-01-02"
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
subject(:doc) { client.addresses.create(**params) }
|
26
|
+
|
27
|
+
before do
|
28
|
+
stub_request(:post, /candidates\/abc123xyz\/addresses/)
|
29
|
+
.to_return(
|
30
|
+
body: answer,
|
31
|
+
status: 201
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "makes request" do
|
36
|
+
subject
|
37
|
+
|
38
|
+
expect(
|
39
|
+
a_request(:post, "https://api.checkr.com/ca/v1/candidates/abc123xyz/addresses")
|
40
|
+
).to have_been_made
|
41
|
+
end
|
42
|
+
|
43
|
+
it "returns an address", :aggregate_failures do
|
44
|
+
expect(doc.country).to eq "CA"
|
45
|
+
expect(doc.created_at).to be_a(DateTime)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "raises when missing params" do
|
49
|
+
params.delete(:region)
|
50
|
+
|
51
|
+
expect { subject }.to raise_error(ArgumentError)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "raises when unknown region" do
|
55
|
+
params[:region] = "Arizona"
|
56
|
+
|
57
|
+
expect { subject }.to raise_error(TypeError)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "raises when missing candidate_id" do
|
61
|
+
params.delete(:candidate_id)
|
62
|
+
|
63
|
+
expect { subject }.to raise_error(ArgumentError)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
describe "Authentication" do
|
6
|
+
let(:client) { Checkr::Canada::Client.new("test_api_key") }
|
7
|
+
subject { client.reports.all }
|
8
|
+
|
9
|
+
context "successful" do
|
10
|
+
before do
|
11
|
+
stub_request(:get, "https://api.checkr.com/ca/v1/reports").to_return(
|
12
|
+
body: { data: [], object: "list", count: 0 }.to_json
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "build basic auth from api_key" do
|
17
|
+
subject
|
18
|
+
|
19
|
+
expect(
|
20
|
+
a_request(:get, "https://api.checkr.com/ca/v1/reports")
|
21
|
+
.with(basic_auth: ["test_api_key", ""])
|
22
|
+
).to have_been_made
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context "failed" do
|
27
|
+
before do
|
28
|
+
stub_request(:get, "https://api.checkr.com/ca/v1/reports").to_return(
|
29
|
+
body: { error: 'Not authorized' }.to_json, status: 401
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "raises error" do
|
34
|
+
expect { subject }.to raise_error(Evil::Client::Operation::ResponseError)
|
35
|
+
|
36
|
+
expect(
|
37
|
+
a_request(:get, "https://api.checkr.com/ca/v1/reports")
|
38
|
+
.with(basic_auth: ["test_api_key", ""])
|
39
|
+
).to have_been_made
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,148 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
describe "Candidates" do
|
6
|
+
let(:client) { Checkr::Canada::Client.new("test_api_key") }
|
7
|
+
|
8
|
+
describe "#all" do
|
9
|
+
let(:answer) { { data: [], object: "list", count: 0 }.to_json }
|
10
|
+
let(:options) { {} }
|
11
|
+
|
12
|
+
subject { client.candidates.all(**options) }
|
13
|
+
|
14
|
+
before do
|
15
|
+
stub_request(:get, /candidates/)
|
16
|
+
.to_return(
|
17
|
+
body: answer
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "builds response", :aggregate_failures do
|
22
|
+
expect(subject.count).to eq 0
|
23
|
+
expect(subject.object).to eq 'list'
|
24
|
+
expect(subject.next_href).to be_nil
|
25
|
+
expect(subject.previous_href).to be_nil
|
26
|
+
expect(subject.data.size).to eq 0
|
27
|
+
end
|
28
|
+
|
29
|
+
context "with params" do
|
30
|
+
let(:options) { { per_page: 1, page: 2, foo: "bar" } }
|
31
|
+
|
32
|
+
it "recognizes only valid params" do
|
33
|
+
subject
|
34
|
+
|
35
|
+
expect(
|
36
|
+
a_request(:get, "https://api.checkr.com/ca/v1/candidates")
|
37
|
+
.with(query: { per_page: 1, page: 2 })
|
38
|
+
).to have_been_made
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "with data" do
|
43
|
+
let(:answer) do
|
44
|
+
File.read("./spec/fixtures/candidates.json")
|
45
|
+
end
|
46
|
+
|
47
|
+
it "builds candidate", :aggregate_failures do
|
48
|
+
expect(subject.data.size).to eq 1
|
49
|
+
|
50
|
+
candidate = subject.data.first
|
51
|
+
|
52
|
+
expect(candidate.dob).to eq "1975-03-19"
|
53
|
+
expect(candidate.created_at).to be_a(DateTime)
|
54
|
+
expect(candidate.created_at.to_date).to eq Date.new(2017, 3, 23)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "#get" do
|
60
|
+
let(:answer) do
|
61
|
+
File.read("./spec/fixtures/candidate.json")
|
62
|
+
end
|
63
|
+
|
64
|
+
subject(:candidate) { client.candidates.get('123abc') }
|
65
|
+
|
66
|
+
before do
|
67
|
+
stub_request(:get, /candidates\/123/)
|
68
|
+
.to_return(
|
69
|
+
body: answer
|
70
|
+
)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "makes request" do
|
74
|
+
subject
|
75
|
+
|
76
|
+
expect(
|
77
|
+
a_request(:get, "https://api.checkr.com/ca/v1/candidates/123abc")
|
78
|
+
).to have_been_made
|
79
|
+
end
|
80
|
+
|
81
|
+
it "builds candidate", :aggregate_failures do
|
82
|
+
expect(candidate.dob).to eq "1975-03-19"
|
83
|
+
expect(candidate.created_at).to be_a(DateTime)
|
84
|
+
expect(candidate.created_at.to_date).to eq Date.new(2017, 3, 23)
|
85
|
+
end
|
86
|
+
|
87
|
+
context "not found" do
|
88
|
+
before do
|
89
|
+
stub_request(:get, /candidates\/123/)
|
90
|
+
.to_return(
|
91
|
+
body: { message: 'Not found' }.to_json,
|
92
|
+
status: 404
|
93
|
+
)
|
94
|
+
end
|
95
|
+
|
96
|
+
it "raises error" do
|
97
|
+
expect { subject }.to raise_error(Evil::Client::Operation::ResponseError)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe "#create" do
|
103
|
+
let(:answer) do
|
104
|
+
File.read("./spec/fixtures/candidate.json")
|
105
|
+
end
|
106
|
+
|
107
|
+
let(:params) do
|
108
|
+
{
|
109
|
+
first_name: "Test",
|
110
|
+
last_name: "Candidate",
|
111
|
+
email: "testonboard@test.com",
|
112
|
+
phone: "000-000-0002",
|
113
|
+
birth_place: "Toronto",
|
114
|
+
dob: Date.new(2017, 3, 23),
|
115
|
+
gender: "F"
|
116
|
+
}
|
117
|
+
end
|
118
|
+
|
119
|
+
subject(:candidate) { client.candidates.create(params) }
|
120
|
+
|
121
|
+
before do
|
122
|
+
stub_request(:post, /candidates/)
|
123
|
+
.to_return(
|
124
|
+
body: answer,
|
125
|
+
status: 201
|
126
|
+
)
|
127
|
+
end
|
128
|
+
|
129
|
+
it "makes request" do
|
130
|
+
subject
|
131
|
+
|
132
|
+
expect(
|
133
|
+
a_request(:post, "https://api.checkr.com/ca/v1/candidates")
|
134
|
+
).to have_been_made
|
135
|
+
end
|
136
|
+
|
137
|
+
it "returns a candidate", :aggregate_failures do
|
138
|
+
expect(candidate.first_name).to eq "Test"
|
139
|
+
expect(candidate.last_name).to eq "Candidate"
|
140
|
+
end
|
141
|
+
|
142
|
+
it "raises when missing params" do
|
143
|
+
params.delete(:first_name)
|
144
|
+
|
145
|
+
expect { subject }.to raise_error(ArgumentError)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|