add schema validations
This commit is contained in:
parent
75043070da
commit
57604b9c89
4 changed files with 220 additions and 43 deletions
|
@ -1,4 +1,10 @@
|
|||
class APIParticulier::CNAFAdapter
|
||||
class InvalidSchemaError < ::StandardError
|
||||
def initialize(errors)
|
||||
super(errors.map(&:to_json).join("\n"))
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(api_particulier_token, numero_allocataire, code_postal, requested_sources)
|
||||
@api = APIParticulier::API.new(api_particulier_token)
|
||||
@numero_allocataire = numero_allocataire
|
||||
|
@ -8,11 +14,23 @@ class APIParticulier::CNAFAdapter
|
|||
|
||||
def to_params
|
||||
@api.composition_familiale(@numero_allocataire, @code_postal)
|
||||
.tap { |d| ensure_valid_schema!(d) }
|
||||
.then { |d| extract_requested_sources(d) }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def ensure_valid_schema!(data)
|
||||
if !schemer.valid?(data)
|
||||
errors = schemer.validate(data).to_a
|
||||
raise InvalidSchemaError.new(errors)
|
||||
end
|
||||
end
|
||||
|
||||
def schemer
|
||||
@schemer ||= JSONSchemer.schema(Rails.root.join('app/schemas/composition-familiale.json'))
|
||||
end
|
||||
|
||||
def extract_requested_sources(data)
|
||||
@requested_sources['cnaf']&.map do |(scope, sources)|
|
||||
case scope
|
||||
|
|
70
app/schemas/composition-familiale.json
Normal file
70
app/schemas/composition-familiale.json
Normal file
|
@ -0,0 +1,70 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"$id": "http://demarches-simplifiees.fr/composition-familiale.schema.json",
|
||||
"title": "composition familiale",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"adresse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"codePostalVille": {
|
||||
"type": "string"
|
||||
},
|
||||
"identite": {
|
||||
"type": "string"
|
||||
},
|
||||
"complementIdentite": {
|
||||
"type": "string"
|
||||
},
|
||||
"numeroRue": {
|
||||
"type": "string"
|
||||
},
|
||||
"pays": {
|
||||
"type": "string"
|
||||
},
|
||||
"complementIdentiteGeo": {
|
||||
"type": "string"
|
||||
},
|
||||
"lieuDit": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"allocataires": {
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/$defs/person" }
|
||||
},
|
||||
"enfants": {
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/$defs/person" }
|
||||
},
|
||||
"quotientFamilial": {
|
||||
"type": "integer"
|
||||
},
|
||||
"annee": {
|
||||
"type": "integer"
|
||||
},
|
||||
"mois": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 12
|
||||
}
|
||||
},
|
||||
"$defs": {
|
||||
"person": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"nomPrenom": {
|
||||
"type": "string"
|
||||
},
|
||||
"dateDeNaissance": {
|
||||
"type": "string",
|
||||
"pattern": "^[0-9]{8}$"
|
||||
},
|
||||
"sexe": {
|
||||
"enum": ["F", "M"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
79
spec/fixtures/cassettes/api_particulier/success/composition_familiale_invalid.yml
vendored
Normal file
79
spec/fixtures/cassettes/api_particulier/success/composition_familiale_invalid.yml
vendored
Normal file
|
@ -0,0 +1,79 @@
|
|||
---
|
||||
http_interactions:
|
||||
- request:
|
||||
method: get
|
||||
uri: https://particulier-test.api.gouv.fr/api/v2/composition-familiale?codePostal=92110&numeroAllocataire=5843972
|
||||
body:
|
||||
encoding: US-ASCII
|
||||
string: ''
|
||||
headers:
|
||||
User-Agent:
|
||||
- demarches-simplifiees.fr
|
||||
Accept:
|
||||
- application/json
|
||||
X-Api-Key:
|
||||
- 29eb50b65f64e8e00c0847a8bbcbd150e1f847
|
||||
Content-Type:
|
||||
- text/html; charset=utf-8
|
||||
Expect:
|
||||
- ''
|
||||
response:
|
||||
status:
|
||||
code: 200
|
||||
message: ''
|
||||
headers:
|
||||
Server:
|
||||
- nginx
|
||||
Date:
|
||||
- Mon, 20 Sep 2021 20:01:39 GMT
|
||||
Content-Type:
|
||||
- application/json; charset=utf-8
|
||||
Content-Length:
|
||||
- '387'
|
||||
X-Powered-By:
|
||||
- Express
|
||||
Vary:
|
||||
- Origin
|
||||
Etag:
|
||||
- W/"183-5m9o/ng+PfdMOPeC0VBn5lqbziQ"
|
||||
Strict-Transport-Security:
|
||||
- max-age=15724800; includeSubdomains
|
||||
body:
|
||||
encoding: UTF-8
|
||||
string: '
|
||||
{
|
||||
"adresse": {
|
||||
"codePostalVille": "92110 Clichy",
|
||||
"identite": "Mr SNOW Eric",
|
||||
"complementIdentite": "ne connait rien",
|
||||
"numeroRue": "109 rue La Boétie",
|
||||
"pays": "FRANCE",
|
||||
"complementIdentiteGeo": "au nord de paris",
|
||||
"lieuDit": "glagla"
|
||||
},
|
||||
"allocataires": [
|
||||
{
|
||||
"nomPrenom": "ERIC SNOW",
|
||||
"dateDeNaissance": "07011991",
|
||||
"sexe": "M"
|
||||
},
|
||||
{
|
||||
"nomPrenom": "SANSA SNOW",
|
||||
"dateDeNaissance": "15011992",
|
||||
"sexe": "F"
|
||||
}
|
||||
],
|
||||
"enfants": [
|
||||
{
|
||||
"nomPrenom": "PAUL SNOW",
|
||||
"dateDeNaissance": "04012018",
|
||||
"sexe": "M"
|
||||
}
|
||||
],
|
||||
"quotientFamilial": 1856,
|
||||
"annee": 2021,
|
||||
"mois": 13
|
||||
}
|
||||
'
|
||||
recorded_at: Mon, 20 Sep 2021 20:01:39 GMT
|
||||
recorded_with: VCR 6.0.0
|
|
@ -4,56 +4,66 @@ describe APIParticulier::CNAFAdapter do
|
|||
before { stub_const("API_PARTICULIER_URL", "https://particulier-test.api.gouv.fr/api") }
|
||||
|
||||
describe '#to_params' do
|
||||
subject do
|
||||
VCR.use_cassette("api_particulier/success/composition_familiale") do
|
||||
adapter.to_params
|
||||
let(:api_particulier_token) { '29eb50b65f64e8e00c0847a8bbcbd150e1f847' }
|
||||
let(:numero_allocataire) { '5843972' }
|
||||
let(:code_postal) { '92110' }
|
||||
|
||||
subject { VCR.use_cassette(cassette) { adapter.to_params } }
|
||||
|
||||
context 'when the api answer is valid' do
|
||||
let(:cassette) { "api_particulier/success/composition_familiale" }
|
||||
|
||||
context 'when the token has all the cnaf scopes' do
|
||||
context 'and all the sources are requested' do
|
||||
let(:requested_sources) do
|
||||
{
|
||||
'cnaf' => {
|
||||
'allocataires' => ['nomPrenom', 'dateDeNaissance', 'sexe'],
|
||||
'enfants' => ['nomPrenom', 'dateDeNaissance', 'sexe'],
|
||||
'adresse' => ['identite', 'complementIdentite', 'complementIdentiteGeo', 'numeroRue', 'lieuDit', 'codePostalVille', 'pays'],
|
||||
'quotient_familial' => ['quotientFamilial', 'annee', 'mois']
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
let(:result) { JSON.parse(File.read('spec/fixtures/files/api_particulier/composition_familiale.json')) }
|
||||
|
||||
it { is_expected.to eq(result) }
|
||||
end
|
||||
|
||||
context 'when no sources is requested' do
|
||||
let(:requested_sources) { {} }
|
||||
|
||||
it { is_expected.to eq({}) }
|
||||
end
|
||||
|
||||
context 'when a scalar is requested' do
|
||||
let(:requested_sources) { { 'cnaf' => { 'adresse' => ['pays'] } } }
|
||||
|
||||
it { is_expected.to eq({ "adresse" => { "pays" => "FRANCE" } }) }
|
||||
end
|
||||
|
||||
context 'when a quotient_familial is requested' do
|
||||
let(:requested_sources) { { 'cnaf' => { 'quotient_familial' => ['annee'] } } }
|
||||
|
||||
it { is_expected.to eq({ "quotient_familial" => { "annee" => 2021 } }) }
|
||||
end
|
||||
|
||||
context 'when a vector is requested' do
|
||||
let(:requested_sources) { { 'cnaf' => { 'allocataires' => ['nomPrenom'] } } }
|
||||
|
||||
it { is_expected.to eq({ "allocataires" => [{ "nomPrenom" => "ERIC SNOW" }, { "nomPrenom" => "SANSA SNOW" }] }) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the token has all the cnaf scopes' do
|
||||
let(:api_particulier_token) { '29eb50b65f64e8e00c0847a8bbcbd150e1f847' }
|
||||
let(:numero_allocataire) { '5843972' }
|
||||
let(:code_postal) { '92110' }
|
||||
|
||||
context 'and all the sources are requested' do
|
||||
let(:requested_sources) do
|
||||
{
|
||||
'cnaf' => {
|
||||
'allocataires' => ['nomPrenom', 'dateDeNaissance', 'sexe'],
|
||||
'enfants' => ['nomPrenom', 'dateDeNaissance', 'sexe'],
|
||||
'adresse' => ['identite', 'complementIdentite', 'complementIdentiteGeo', 'numeroRue', 'lieuDit', 'codePostalVille', 'pays'],
|
||||
'quotient_familial' => ['quotientFamilial', 'annee', 'mois']
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
let(:result) { JSON.parse(File.read('spec/fixtures/files/api_particulier/composition_familiale.json')) }
|
||||
|
||||
it { is_expected.to eq(result) }
|
||||
end
|
||||
context 'when the api answer is valid' do
|
||||
let(:cassette) { "api_particulier/success/composition_familiale_invalid" }
|
||||
|
||||
context 'when no sources is requested' do
|
||||
let(:requested_sources) { {} }
|
||||
|
||||
it { is_expected.to eq({}) }
|
||||
end
|
||||
|
||||
context 'when a scalar is requested' do
|
||||
let(:requested_sources) { { 'cnaf' => { 'adresse' => ['pays'] } } }
|
||||
|
||||
it { is_expected.to eq({ "adresse" => { "pays" => "FRANCE" } }) }
|
||||
end
|
||||
|
||||
context 'when a quotient_familial is requested' do
|
||||
let(:requested_sources) { { 'cnaf' => { 'quotient_familial' => ['annee'] } } }
|
||||
|
||||
it { is_expected.to eq({ "quotient_familial" => { "annee" => 2021 } }) }
|
||||
end
|
||||
|
||||
context 'when a vector is requested' do
|
||||
let(:requested_sources) { { 'cnaf' => { 'allocataires' => ['nomPrenom'] } } }
|
||||
|
||||
it { is_expected.to eq({ "allocataires" => [{ "nomPrenom" => "ERIC SNOW" }, { "nomPrenom" => "SANSA SNOW" }] }) }
|
||||
it { expect { subject }.to raise_error(APIParticulier::CNAFAdapter::InvalidSchemaError) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue