283 lines
9.8 KiB
Python
283 lines
9.8 KiB
Python
# passerelle - uniform access to multiple data sources and services
|
|
# Copyright (C) 2023 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 urllib.parse
|
|
|
|
import httmock
|
|
import pytest
|
|
from requests import ConnectionError, RequestException, Timeout
|
|
|
|
from passerelle.contrib.isere_esrh.models import IsereESRH
|
|
from tests.utils import setup_access_rights
|
|
|
|
|
|
@pytest.fixture()
|
|
def connector(db):
|
|
return setup_access_rights(IsereESRH.objects.create(slug='test', base_url='http://esrh.net'))
|
|
|
|
|
|
def test_connection_error_handling(app, connector):
|
|
def connection_error(url, request):
|
|
raise ConnectionError('oops')
|
|
|
|
def timeout(url, request):
|
|
raise Timeout('oops')
|
|
|
|
def request_error(url, request):
|
|
raise RequestException('oops')
|
|
|
|
for handler in [connection_error, timeout, request_error]:
|
|
with httmock.HTTMock(handler):
|
|
response = app.get('/isere-esrh/test/official?number=004242&authority=CG38', status=200)
|
|
assert response.json['err_desc'] == 'HTTP request failed'
|
|
assert response.json['data'] == {'exception': 'oops'}
|
|
|
|
def invalid_json(url, request):
|
|
return httmock.response(200, 'bad_json')
|
|
|
|
with httmock.HTTMock(invalid_json):
|
|
response = app.get('/isere-esrh/test/official?number=004242&authority=CG38', status=200)
|
|
assert response.json['err_desc'] == 'ESRH returned invalid json'
|
|
assert 'Expecting value' in response.json['data']['exception']
|
|
|
|
def invalid_json_content(url, request):
|
|
return httmock.response(200, '[]')
|
|
|
|
with httmock.HTTMock(invalid_json_content):
|
|
response = app.get('/isere-esrh/test/official?number=004242&authority=CG38', status=200)
|
|
assert (
|
|
response.json['err_desc']
|
|
== 'ESRH returned malformed json : expecting a dictionary with a "values" key containing a list of objects.'
|
|
)
|
|
|
|
|
|
def test_official(app, connector, freezer):
|
|
freezer.move_to('1871-03-18 13:13:00')
|
|
|
|
@httmock.urlmatch()
|
|
def error_handler(url, request):
|
|
assert False, 'should not be reached'
|
|
|
|
@httmock.urlmatch(path=r'^/api/v2/Agent$', query='numero=004242&collectivite=CG38')
|
|
def mock_official_not_found(url, request):
|
|
return httmock.response(200, {'values': []})
|
|
|
|
with httmock.HTTMock(mock_official_not_found, error_handler):
|
|
response = app.get('/isere-esrh/test/official?number=004242&authority=CG38')
|
|
assert response.json['err'] == 0
|
|
assert response.json['data'] is None
|
|
|
|
@httmock.urlmatch(path=r'^/api/v2/Agent$', query='numero=004242&collectivite=CG38')
|
|
def mock_malformed_response(url, request):
|
|
return httmock.response(200, {'values': [{}]})
|
|
|
|
with httmock.HTTMock(mock_malformed_response, error_handler):
|
|
response = app.get('/isere-esrh/test/official?number=004242&authority=CG38')
|
|
assert response.json['err'] == 1
|
|
assert (
|
|
response.json['err_desc']
|
|
== 'Malformed response : values elements are expected to be objects with an "agentId" key'
|
|
)
|
|
|
|
@httmock.urlmatch(path=r'^/api/v2/Agent$', query='numero=004242&collectivite=CG38')
|
|
def mock_official(url, request):
|
|
return httmock.response(
|
|
200,
|
|
{
|
|
'values': [
|
|
{
|
|
'nom': 'Abitbol',
|
|
'agentId': 12,
|
|
'prenom': 'Georges',
|
|
'matricule': '004242',
|
|
'observation': 'Agent polyvalent en gestion de classe',
|
|
},
|
|
]
|
|
},
|
|
)
|
|
|
|
@httmock.urlmatch(
|
|
path=r'^/api/v2/Agent/12/DossiersStatutaire$',
|
|
query=f'aDate={urllib.parse.quote("1871-03-18T13:13:00+00:00")}',
|
|
)
|
|
def mock_empty_file(url, request):
|
|
return httmock.response(200, {'values': []})
|
|
|
|
with httmock.HTTMock(mock_official, mock_empty_file, error_handler):
|
|
response = app.get('/isere-esrh/test/official?number=004242&authority=CG38')
|
|
assert response.json['data'] == {
|
|
'agentId': 12,
|
|
'nom': 'Abitbol',
|
|
'prenom': 'Georges',
|
|
'matricule': '004242',
|
|
'observation': 'Agent polyvalent en gestion de classe',
|
|
'DossiersStatutaire': [],
|
|
}
|
|
|
|
@httmock.urlmatch(
|
|
path=r'^/api/v2/Agent/12/DossiersStatutaire$',
|
|
query=f'aDate={urllib.parse.quote("1871-03-18T13:13:00+00:00")}',
|
|
)
|
|
def mock_file(url, request):
|
|
return httmock.response(
|
|
200,
|
|
{
|
|
'values': [
|
|
{
|
|
'dossierStatutaireId': 1,
|
|
'grade': {
|
|
'gradeId': 2,
|
|
'code': 'T34',
|
|
'libelle': 'Adjoint du sherif',
|
|
'cadreEmploiId': 3,
|
|
},
|
|
}
|
|
]
|
|
},
|
|
)
|
|
|
|
with httmock.HTTMock(mock_official, mock_file, error_handler):
|
|
response = app.get('/isere-esrh/test/official?number=004242&authority=CG38')
|
|
assert response.json['data'] == {
|
|
'agentId': 12,
|
|
'nom': 'Abitbol',
|
|
'prenom': 'Georges',
|
|
'matricule': '004242',
|
|
'observation': 'Agent polyvalent en gestion de classe',
|
|
'DossiersStatutaire': [
|
|
{
|
|
'dossierStatutaireId': 1,
|
|
'grade': {
|
|
'gradeId': 2,
|
|
'code': 'T34',
|
|
'libelle': 'Adjoint du sherif',
|
|
'cadreEmploiId': 3,
|
|
},
|
|
}
|
|
],
|
|
}
|
|
|
|
|
|
def test_entities(app, connector, freezer):
|
|
freezer.move_to('1871-03-18 13:13:00')
|
|
|
|
@httmock.urlmatch()
|
|
def error_handler(url, request):
|
|
assert False, 'should not be reached'
|
|
|
|
@httmock.urlmatch(
|
|
path=r'^/api/v2/Entite$', query=f'aDate={urllib.parse.quote("1871-03-18T13:13:00+00:00")}'
|
|
)
|
|
def mock_entites(url, request):
|
|
return httmock.response(
|
|
200,
|
|
{
|
|
'values': [
|
|
{
|
|
'entiteId': 1,
|
|
'code': '6500',
|
|
'libelle': 'dir. de la classe internationale',
|
|
'region': 'ouest',
|
|
},
|
|
{'entiteId': 2, 'code': '650001', 'libelle': 'sce. des sapes', 'region': 'nord'},
|
|
{
|
|
'entiteId': 3,
|
|
'code': '6400',
|
|
'libelle': 'dir. des dinosaures de droite',
|
|
'region': 'sud',
|
|
},
|
|
]
|
|
},
|
|
)
|
|
|
|
entity_1 = {
|
|
'id': 1,
|
|
'text': 'dir. de la classe internationale',
|
|
'code': '6500',
|
|
'region': 'ouest',
|
|
'entiteId': 1,
|
|
'libelle': 'dir. de la classe internationale',
|
|
}
|
|
|
|
entity_2 = {
|
|
'id': 2,
|
|
'text': 'sce. des sapes',
|
|
'code': '650001',
|
|
'region': 'nord',
|
|
'entiteId': 2,
|
|
'libelle': 'sce. des sapes',
|
|
}
|
|
|
|
entity_3 = {
|
|
'id': 3,
|
|
'code': '6400',
|
|
'text': 'dir. des dinosaures de droite',
|
|
'region': 'sud',
|
|
'entiteId': 3,
|
|
'libelle': 'dir. des dinosaures de droite',
|
|
}
|
|
|
|
with httmock.HTTMock(mock_entites, error_handler):
|
|
response = app.get('/isere-esrh/test/entities')
|
|
assert response.json['data'] == [entity_1, entity_2, entity_3]
|
|
|
|
response = app.get('/isere-esrh/test/entities?label_pattern=^dir\\..*')
|
|
assert response.json['data'] == [entity_1, entity_3]
|
|
|
|
response = app.get('/isere-esrh/test/entities?code_pattern=^6500\\d%2B')
|
|
assert response.json['data'] == [entity_2]
|
|
|
|
response = app.get('/isere-esrh/test/entities?code_pattern=^6500&label_pattern=^dir\\..*')
|
|
assert response.json['data'] == [entity_1]
|
|
|
|
|
|
def test_job_types(app, connector, freezer):
|
|
freezer.move_to('1871-03-18 13:13:00')
|
|
now = urllib.parse.quote('1871-03-18T13:13:00+00:00')
|
|
|
|
@httmock.urlmatch()
|
|
def error_handler(url, request):
|
|
assert False, 'should not be reached'
|
|
|
|
@httmock.urlmatch(
|
|
path=r'^/api/v2/Poste$', query=f'codeCollectivite=CG38&avecLibellePoste=True&aDate={now}'
|
|
)
|
|
def mock_entites(url, request):
|
|
return httmock.response(
|
|
200,
|
|
{
|
|
'values': [
|
|
{'posteId': 1, 'libelles': [{'libelle': 'Patron de l\'auberge'}], 'ravioles': 'non'},
|
|
{'posteId': 2, 'libelles': [], 'ravioles': 'oui'},
|
|
{'posteId': 3, 'ravioles': 'non'},
|
|
]
|
|
},
|
|
)
|
|
|
|
with httmock.HTTMock(mock_entites, error_handler):
|
|
response = app.get('/isere-esrh/test/job-types?authority=CG38')
|
|
assert response.json['data'] == [
|
|
{
|
|
'id': 1,
|
|
'text': 'Patron de l\'auberge',
|
|
'ravioles': 'non',
|
|
'posteId': 1,
|
|
'libelles': [{'libelle': 'Patron de l\'auberge'}],
|
|
},
|
|
{'id': 2, 'text': 'N/A', 'ravioles': 'oui', 'posteId': 2, 'libelles': []},
|
|
{'id': 3, 'text': 'N/A', 'ravioles': 'non', 'posteId': 3},
|
|
]
|