passerelle/tests/test_api_particulier.py

333 lines
10 KiB
Python

# -*- coding: utf-8 -*-
# tests/test_api_particulier.py
# Copyright (C) 2017 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import logging
import pytest
from httmock import urlmatch, HTTMock, response
from django.core.urlresolvers import reverse
import requests
from passerelle.apps.api_particulier.models import APIParticulier
from passerelle.base.models import ResourceLog
from utils import make_resource, endpoint_get
SVAIR_RESPONSE = {
"declarant1": {
"nom": "Martin",
"nomNaissance": "Martin",
"prenoms": "Pierre",
"dateNaissance": "22/03/1985"
},
"declarant2": {
"nom": "Martin",
"nomNaissance": "Honore",
"prenoms": "Marie",
"dateNaissance": "03/04/1986"
},
"foyerFiscal": {
"annee": 2015,
"adresse": "12 rue Balzac 75008 Paris"
},
"dateRecouvrement": "10/10/2015",
"dateEtablissement": "08/07/2015",
"nombreParts": 2,
"situationFamille": "Marié(e)s",
"nombrePersonnesCharge": 2,
"revenuBrutGlobal": 29880,
"revenuImposable": 29880,
"impotRevenuNetAvantCorrections": 2165,
"montantImpot": 2165,
"revenuFiscalReference": 29880,
"anneeImpots": "2015",
"anneeRevenus": "2014"
}
CAF_FAMILLE = {
"adresse": {
"codePostalVille": "12345 CONDAT",
"complementIdentiteGeo": "ESCALIER B",
"identite": "Madame MARIE DUPONT",
"numeroRue": "123 RUE BIDON",
"pays": "FRANCE"
},
"allocataires": [
{
"dateDeNaissance": "12111971",
"nomPrenom": "MARIE DUPONT",
"sexe": "F"
},
{
"dateDeNaissance": "18101969",
"nomPrenom": "JEAN DUPONT",
"sexe": "M"
}
],
"annee": 2017,
"enfants": [
{
"dateDeNaissance": "11122016",
"nomPrenom": "LUCIE DUPONT",
"sexe": "F"
}
],
"mois": 4,
"quotientFamilial": 1754
}
@urlmatch(netloc=r'^particulier.*\.api\.gouv\.fr$',
path=r'^/api/v2/avis-imposition$')
def api_particulier_v2_avis_imposition(url, request):
return response(200, SVAIR_RESPONSE, request=request)
@urlmatch(netloc=r'^particulier.*\.api\.gouv\.fr$',
path=r'^/api/v2/composition-familiale$')
def api_particulier_v2_situation_familiale(url, request):
return response(200, CAF_FAMILLE, request=request)
@urlmatch(netloc=r'^particulier.*\.api\.gouv\.fr$')
def api_particulier_error_500(url, request):
return response(500, {'error': 500}, request=request)
@urlmatch(netloc=r'^particulier.*\.api\.gouv\.fr$')
def api_particulier_connection_error(url, request):
raise requests.RequestException('connection timed-out')
@urlmatch(netloc=r'^particulier.*\.api\.gouv\.fr$')
def api_particulier_error_not_json(url, request):
return response(200, 'something bad happened', request=request)
@urlmatch(netloc=r'^particulier.*\.api\.gouv\.fr$')
def api_particulier_error_not_found(url, request):
return response(404, {
'error': 'not_found',
'message': u'Les paramètres fournis sont incorrects ou ne correspondent pas à un avis'
}, request=request)
@urlmatch(netloc=r'^particulier.*\.api\.gouv\.fr$')
def api_particulier_error_not_found_caf(url, request):
return response(404, {
'error': 'not_found',
'message': 'Dossier allocataire inexistant. Le document ne peut être édité.'
}, request=request)
@pytest.yield_fixture
def mock_api_particulier():
with HTTMock(api_particulier_v2_avis_imposition, api_particulier_v2_situation_familiale):
yield None
@pytest.fixture
def resource(db):
return make_resource(
APIParticulier,
slug='test',
title='API Particulier Prod',
description='API Particulier Prod',
platform='test',
api_key='83c68bf0b6013c4daf3f8213f7212aa5')
def test_error(app, resource, mock_api_particulier):
vector = [
(['impots_svair', 'avis-imposition'], {
'numero_fiscal': '1234567890123',
'reference_avis': '3210987654321',
}),
(['caf_famille', 'situation-familiale'], {
'code_postal': 12,
'numero_allocataire': 15
}),
]
with HTTMock(api_particulier_error_500):
def do(endpoint, params):
resp = endpoint_get(
'/api-particulier/test/%s' % endpoint,
app,
resource,
endpoint,
params=params)
assert resp.status_code == 200
assert resp.json['err'] == 1
assert resp.json['data']['status_code'] == 500
assert resp.json['data']['code'] == 'non-200'
for endpoints, params in vector:
for endpoint in endpoints:
do(endpoint, params)
with HTTMock(api_particulier_error_not_json):
def do(endpoint, params):
resp = endpoint_get(
'/api-particulier/test/%s' % endpoint,
app,
resource,
endpoint,
params=params)
assert resp.status_code == 200
assert resp.json['err'] == 1
assert 'returned non-JSON content' in resp.json['err_desc']
assert resp.json['data']['code'] == 'non-json'
for endpoints, params in vector:
for endpoint in endpoints:
do(endpoint, params)
with HTTMock(api_particulier_error_not_found):
def do(endpoint, params):
resp = endpoint_get(
'/api-particulier/test/%s' % endpoint,
app,
resource,
endpoint,
params=params)
assert resp.status_code == 200
assert resp.json['err'] == 1
assert resp.json['err_desc'] == 'No matching tax notice was found.'
assert resp.json['data']['code'] == 'not-found'
for endpoints, params in vector:
for endpoint in endpoints:
do(endpoint, params)
with HTTMock(api_particulier_connection_error):
def do(endpoint, params):
resp = endpoint_get(
'/api-particulier/test/%s' % endpoint,
app,
resource,
endpoint,
params=params)
assert resp.status_code == 200
assert resp.json['err'] == 1
assert resp.json['err_desc'] == 'API-particulier platform "test" connection error: connection timed-out'
for endpoints, params in vector:
for endpoint in endpoints:
do(endpoint, params)
resp = endpoint_get(
'/api-particulier/test/avis-imposition',
app,
resource,
'avis-imposition',
params={
'numero_fiscal': ' 1234567890', # too short
'reference_avis': '3210987654321',
'user': 'John Doe',
})
assert resp.status_code == 200
assert resp.json['err'] == 1
assert resp.json['data'] is None
assert 'must be 13 chars long' in resp.json['err_desc']
resp = endpoint_get(
'/api-particulier/test/avis-imposition',
app,
resource,
'avis-imposition',
params={
'numero_fiscal': '1234567890123',
'reference_avis': '32109876543 ', # too short
'user': 'John Doe',
})
assert resp.status_code == 200
assert resp.json['err'] == 1
assert resp.json['data'] is None
assert 'must be 13 chars long' in resp.json['err_desc']
def test_avis_imposition(app, resource, mock_api_particulier):
resp = endpoint_get(
'/api-particulier/test/avis-imposition',
app,
resource,
'avis-imposition',
params={
'numero_fiscal': '1234567890123',
'reference_avis': '3210987654321',
'user': 'John Doe',
})
assert resp.status_code == 200
assert resp.json['data']['montantImpot'] == 2165
assert resp.json['err'] == 0
resp = endpoint_get(
'/api-particulier/test/avis-imposition',
app,
resource,
'avis-imposition',
params={
'numero_fiscal': '1234567890123X', # 14 chars : will be cutted
'reference_avis': '3210987654321X', # idem
'user': 'John Doe',
})
assert resp.status_code == 200
assert resp.json['data']['montantImpot'] == 2165
assert resp.json['err'] == 0
def test_situation_familiale(app, resource, mock_api_particulier):
resp = endpoint_get(
'/api-particulier/test/situation-familiale',
app,
resource,
'situation-familiale',
params={
'code_postal': '99148',
'numero_allocataire': '000354',
'user': 'John Doe',
})
assert resp.json['data']['adresse']['codePostalVille'] == '12345 CONDAT'
def test_detail_page(app, resource):
response = app.get(reverse('view-connector', kwargs={
'connector': 'api-particulier',
'slug': 'test',
}))
assert 'API Particulier Prod' in response.text
assert 'family allowance' in response.text
assert 'fiscal information' in response.text
@pytest.mark.parametrize(
'mock,should_log', [
(api_particulier_error_not_found, False), (api_particulier_error_500, True),
(api_particulier_error_not_json, True), (api_particulier_error_not_found_caf, False)
]
)
def test_api_particulier_dont_log_not_found(app, resource, mock, should_log):
with HTTMock(mock):
resp = endpoint_get(
'/api-particulier/test/avis-imposition',
app,
resource,
'avis-imposition',
params={
'numero_fiscal': '1234567890123',
'reference_avis': '3210987654321',
})
logs = ResourceLog.objects.all()
assert logs.count() == 3
if should_log:
assert logs.filter(levelno=logging.ERROR).count() == 1
else:
assert not logs.filter(levelno=logging.ERROR).exists()