passerelle/tests/test_astregs.py

558 lines
25 KiB
Python

# -*- coding: utf-8 -*-
import os
import logging
import mock
import pytest
import re
from requests.exceptions import ConnectionError
from requests import Request
from django.utils.encoding import force_text
from passerelle.apps.astregs.models import AstreGS, Link
from . import utils
BASE_URL = 'https://test-ws-astre-gs.departement06.fr/axis2/services/'
def get_xml_file(filename):
return file(os.path.join(os.path.dirname(__file__),
'data', 'astregs', filename)).read()
def contact_search_side_effect(wsdl_url, **kwargs):
if 'Tiers' in wsdl_url:
response_content = get_xml_file('Tiers.xml')
else:
response_content = get_xml_file('Contact.xml')
return mock.Mock(content=response_content, status_code=200,
headers={'Content-Type': 'text/xml'})
def search_wsdl_side_effect(wsdl_url, **kwargs):
if 'Tiers' in wsdl_url:
response_content = get_xml_file('Tiers.wsdl')
else:
response_content = get_xml_file('Contact.wsdl')
return mock.Mock(content=response_content, status_code=200,
headers={'Content-Type': 'text/xml'})
def contact_wsdl_side_effect(wsdl_url, **kwargs):
if 'ContactAdresses' in wsdl_url:
response_content = get_xml_file('ContactAdresses.wsdl')
else:
response_content = get_xml_file('Contact.wsdl')
return mock.Mock(content=response_content, status_code=200,
headers={'Content-Type': 'text/xml'})
def contact_side_effect(wsdl_url, **kwargs):
if 'ContactAdresses' in wsdl_url:
response_content = get_xml_file('ContactAddressCreationResponse.xml')
else:
response_content = get_xml_file('ContactCreationResponse.xml')
return mock.Mock(content=response_content, status_code=200,
headers={'Content-Type': 'text/xml'})
@pytest.fixture
def connector(db):
return utils.make_resource(AstreGS,
title='Test', slug='test',
description='test', wsdl_base_url=BASE_URL,
username='CS-FORML', password='secret',
organism='CG06', budget='01',
exercice='2019'
)
@pytest.fixture
def recherche_tiers_details_wsdl():
return get_xml_file('RechercheTiersDetails.wsdl')
@pytest.fixture
def recherche_tiers_details_result():
return get_xml_file('RechercheTiersDetails.xml')
@pytest.fixture
def recherche_tiers_details_empty_result():
content = get_xml_file('RechercheTiersDetails.xml')
return re.sub('<ns1:liste>.*</ns1:liste>', '<ns1:liste></ns1:liste>',
content)
@pytest.fixture
def tiers_creation_response():
return get_xml_file('TiersCreationResponse.xml')
@pytest.fixture
def tiers_creation_error_response():
return get_xml_file('TiersCreationErrorResponse.xml')
@pytest.fixture
def tiers_response():
return get_xml_file('TiersResponse.xml')
@pytest.fixture
def tiers_error_response():
return get_xml_file('TiersErrorResponse.xml')
@mock.patch('passerelle.utils.Request.get')
@mock.patch('passerelle.utils.Request.post')
def test_search_association_by_siren(mocked_post, mocked_get, recherche_tiers_details_wsdl,
recherche_tiers_details_result, connector, app):
mocked_get.return_value = mock.Mock(content=recherche_tiers_details_wsdl)
mocked_post.return_value = mock.Mock(content=recherche_tiers_details_result, status_code=200,
headers={'Content-Type': 'text/xml'})
resp = app.get('/astregs/test/associations', params={'siren': '500433909'})
assert mocked_get.call_args[0][0] == '%sRechercheTiersDetails?wsdl' % BASE_URL
assert mocked_post.call_args[0][0] == '%sRechercheTiersDetails/' % BASE_URL
assert isinstance(resp.json['data'], list)
assert len(resp.json['data']) > 0
assert resp.json['data'][0]['id'] == '50043390900016'
assert resp.json['data'][0]['text'] == '50043390900016 - ASSOCIATION OMNISPORTS DES MONTS D AZUR'
assert resp.json['data'][0]['code'] == '173957'
assert resp.json['data'][0]['name'] == 'ASSOCIATION OMNISPORTS DES MONTS D AZUR'
@mock.patch('passerelle.utils.Request.get')
@mock.patch('passerelle.utils.Request.post')
def test_check_association_presence(mocked_post, mocked_get, connector, app):
wsdl_content = file(os.path.join(os.path.dirname(__file__),
'data', 'astregs', 'RechercheTiers.wsdl')).read()
response_content = file(os.path.join(os.path.dirname(__file__),
'data', 'astregs', 'RechercheTiers.xml')).read()
mocked_get.return_value = mock.Mock(content=wsdl_content)
mocked_post.return_value = mock.Mock(content=response_content, status_code=200,
headers={'Content-Type': 'text/xml'})
resp = app.get('/astregs/test/check-association-by-siret', params={'siret': '50043390900014'})
assert resp.json['exists'] == True
response_content = file(os.path.join(os.path.dirname(__file__),
'data', 'astregs', 'RechercheTiersNoResult.xml')).read()
mocked_post.return_value = mock.Mock(content=response_content, status_code=200,
headers={'Content-Type': 'text/xml'})
resp = app.get('/astregs/test/check-association-by-siret', params={'siret': 'unknown'})
assert resp.json['exists'] == False
@mock.patch('passerelle.utils.Request.get', side_effect=search_wsdl_side_effect)
@mock.patch('passerelle.utils.Request.post', side_effect=contact_search_side_effect)
def test_association_linking_means(mocked_post, mocked_get, client, connector, app):
resp = app.get('/astregs/test/get-association-link-means', params={'association_id': '42'})
assert resp.json['already_paired'] == False
assert resp.json['data'] == [
{'id': 'email', 'text': 'par courriel vers fo***@***com',
'value': 'foo@example.com', 'type': 'email'},
{'id': 'mobile', 'text': 'par SMS vers 06*****990',
'value': '0667788990', 'type': 'mobile'}
]
assert resp.json['raw_data']['AdresseMail'] == 'foo@example.com'
assert resp.json['raw_data']['TelephoneMobile'] == '06 67 78 89 90'
Link.objects.create(name_id='user_name_id', association_id='42', resource=connector)
resp = app.get('/astregs/test/get-association-link-means',
params={'association_id': '42', 'NameID': 'user_name_id'})
assert resp.json['already_paired'] == True
for bad_mobile_number in ('', '01 43 35 01 35', '00 33 7 01 02 03 04', 'letters', '06 01 02'):
mocked_post.side_effect = [
mock.Mock(content=get_xml_file('Tiers.xml'), status_code=200,
headers={'Content-Type': 'text/xml'}),
mock.Mock(content=get_xml_file('Contact.xml').replace(
'<ns1:TelephoneMobile>06 67 78 89 90<',
'<ns1:TelephoneMobile>%s<' % bad_mobile_number),
status_code=200, headers={'Content-Type': 'text/xml'})
]
resp = app.get('/astregs/test/get-association-link-means', params={'association_id': '42'})
assert resp.json['data'] == [
{'id': 'email', 'text': 'par courriel vers fo***@***com',
'value': 'foo@example.com', 'type': 'email'}
]
assert resp.json['raw_data']['AdresseMail'] == 'foo@example.com'
assert resp.json['raw_data']['TelephoneMobile'] == (bad_mobile_number or None)
@mock.patch('passerelle.utils.Request.get', side_effect=search_wsdl_side_effect)
@mock.patch('passerelle.utils.Request.post', side_effect=contact_search_side_effect)
def test_link_user_to_association(mocked_post, mocked_get, client, recherche_tiers_details_wsdl,
recherche_tiers_details_result, connector, app):
assert Link.objects.count() == 0
resp = app.get('/astregs/test/get-association-link-means', params={'association_id': '42'})
assert len(resp.json['data']) == 2
mocked_get.side_effect = None
mocked_post.side_effect = None
mocked_get.return_value = mock.Mock(content=recherche_tiers_details_wsdl)
mocked_post.return_value = mock.Mock(content=recherche_tiers_details_result, status_code=200,
headers={'Content-Type': 'text/xml'})
resp = app.get('/astregs/test/link', params={'association_id': '42', 'NameID': 'user_name_id'})
assert Link.objects.filter(name_id='user_name_id', association_id='42').count() == 1
link = Link.objects.get(name_id='user_name_id', association_id='42')
assert link.association_label == '50043390900016 - ASSOCIATION OMNISPORTS DES MONTS D AZUR'
assert resp.json['association_id'] == link.association_id
assert resp.json['link'] == link.pk
assert resp.json['created'] == True
resp = app.get('/astregs/test/link', params={'association_id': '42', 'NameID': 'user_name_id'})
assert resp.json['created'] == False
@mock.patch('passerelle.utils.Request.get', side_effect=search_wsdl_side_effect)
@mock.patch('passerelle.utils.Request.post', side_effect=contact_search_side_effect)
def test_unlink_user_from_association(mocked_post, mocked_get, connector, recherche_tiers_details_wsdl,
recherche_tiers_details_result, app):
resp = app.get('/astregs/test/get-association-link-means', params={'association_id': '42'})
mocked_get.side_effect = None
mocked_post.side_effect = None
mocked_get.return_value = mock.Mock(content=recherche_tiers_details_wsdl)
mocked_post.return_value = mock.Mock(content=recherche_tiers_details_result, status_code=200,
headers={'Content-Type': 'text/xml'})
resp = app.get('/astregs/test/link', params={'association_id': '42', 'NameID': 'user_name_id'})
resp = app.get('/astregs/test/unlink', params={'NameID': 'user_name_id', 'association_id': '42'})
assert resp.json['deleted']
resp = app.get('/astregs/test/unlink', params={'NameID': 'user_name_id', 'association_id': '42'}, status=404)
@mock.patch('passerelle.utils.Request.get')
@mock.patch('passerelle.utils.Request.post')
def test_list_user_associations(mocked_post, mocked_get, recherche_tiers_details_wsdl,
recherche_tiers_details_result, recherche_tiers_details_empty_result,
connector, app, caplog):
mocked_get.return_value = mock.Mock(content=recherche_tiers_details_wsdl)
mocked_post.return_value = mock.Mock(content=recherche_tiers_details_result, status_code=200,
headers={'Content-Type': 'text/xml'})
resp = app.get('/astregs/test/link', params={'association_id': '42', 'NameID': 'user_name_id'})
resp = app.get('/astregs/test/links', params={'NameID': 'user_name_id'})
mocked_get.assert_called()
mocked_post.assert_called()
assert resp.json['data']
assert resp.json['data'][0]['id'] == '42'
assert resp.json['data'][0]['text'] == '50043390900016 - ASSOCIATION OMNISPORTS DES MONTS D AZUR'
mocked_post.return_value = mock.Mock(content=recherche_tiers_details_empty_result, status_code=200,
headers={'Content-Type': 'text/xml'})
resp = app.get('/astregs/test/links', params={'NameID': 'user_name_id'})
assert resp.json['data']
assert resp.json['data'][0]['id'] == '42'
assert resp.json['data'][0]['text'] == '50043390900016 - ASSOCIATION OMNISPORTS DES MONTS D AZUR'
assert len(caplog.records)
assert caplog.records[-1].levelno == logging.ERROR
assert caplog.records[-1].message == 'No data found for association 42'
@mock.patch('passerelle.utils.Request.get', side_effect=search_wsdl_side_effect)
@mock.patch('passerelle.utils.Request.post')
def test_association_creation(mocked_post, mocked_get, tiers_creation_response,
tiers_creation_error_response, connector, app):
payload = {
'CodeFamille': '51',
'CatTiers': '42',
'EncodeKeyContact': '4242',
'Sigle': 'EO',
'NomEnregistrement': 'My association',
'Organisme': 'CG06',
'NumeroSiret': '112233445',
'NumeroSiretFin': '00024',
'StatutTiers': 'PROPOSE',
'Type': '*',
'AdresseTitre': 'AdressePrincipale',
'AdresseLibelleRue': '169, rue du Château',
'Sigle': 'EO',
'Financier': 'true',
'AdresseIsAdresseDeFacturation': 'false',
'AdresseIsAdresseDeCommande': 'false'
}
mocked_post.return_value = mock.Mock(content=tiers_creation_response, status_code=200,
headers={'Content-Type': 'text/xml'})
resp = app.post_json('/astregs/test/create-association', params=payload)
assert resp.json['data']
data = resp.json['data']
assert data['CodeTiers'] == '487464'
assert data['CodeFamille'] == '51'
assert data['CatTiers'] == '42'
assert data['EncodeKeyContact'] == '4242'
assert data['NomEnregistrement'] == 'My association'
assert data['Organisme'] == 'CG06'
assert data['NumeroSiret'] == '112233445'
assert data['NumeroSiretFin'] == '00024'
assert data['StatutTiers'] == 'PROPOSE'
assert data['Type'] == '*'
assert data['AdresseTitre'] == 'AdressePrincipale'
assert data['AdresseLibelleRue'] == force_text('169, rue du Château')
assert data['Sigle'] == 'EO'
assert data['AdresseIsAdresseDeCommande'] == 'false'
assert data['AdresseIsAdresseDeFacturation'] == 'false'
mocked_post.return_value = mock.Mock(content=tiers_creation_error_response,
status_code=500,
headers={'Content-Type': 'text/xml'})
resp = app.post_json('/astregs/test/create-association', params=payload)
assert resp.json['err'] == 1
assert resp.json['err_class'] == 'passerelle.utils.jsonresponse.APIError'
assert "Erreur technique dans le service 'Tiers'" in resp.json['err_desc']
assert not resp.json['data']
@mock.patch('passerelle.utils.Request.get', side_effect=search_wsdl_side_effect)
@mock.patch('passerelle.utils.Request.post')
def test_get_association_by_id(mocked_post, mocked_get, tiers_response, tiers_error_response,
connector, app):
mocked_post.return_value = mock.Mock(content=tiers_response, status_code=200,
headers={'Content-Type': 'text/xml'})
resp = app.get('/astregs/test/get-association-by-id', params={'association_id': '487464'})
assert resp.json['data']
data = resp.json['data']
data['CodeTiers'] == '487464'
data['CodeFamille'] == '51'
data['CatTiers'] == '42'
data['NomEnregistrement'] == 'My association'
data['Organisme'] == 'CG06'
data['NumeroSiret'] == '112233445'
data['NumeroSiretFin'] == '00024'
data['StatutTiers'] == 'PROPOSE'
resp = app.get('/astregs/test/get-association-by-id',
params={'association_id': '487464',
'NameID': 'user_name_id'},
status=404)
Link.objects.create(name_id='user_name_id', association_id='487464', resource=connector)
resp = app.get('/astregs/test/get-association-by-id', params={'association_id': '487464',
'NameID': 'user_name_id'})
assert resp.json['data']
mocked_post.return_value = mock.Mock(content=tiers_error_response, status_code=500,
headers={'Content-Type': 'text/xml'})
resp = app.get('/astregs/test/get-association-by-id', params={'association_id': 'unknown'}, status=200)
assert resp.json['err'] == 1
assert resp.json['err_class'] == 'passerelle.utils.jsonresponse.APIError'
assert "Erreur technique dans le service 'Tiers'" in resp.json['err_desc']
assert not resp.json['data']
@mock.patch('passerelle.utils.Request.get')
@mock.patch('passerelle.utils.Request.post')
def test_get_contact_details(mocked_post, mocked_get, connector, app):
mocked_get.return_value = mock.Mock(content=get_xml_file('Contact.wsdl'))
mocked_post.return_value = mock.Mock(content=get_xml_file('ContactResponse.xml'), status_code=200,
headers={'Content-Type': 'text/xml'})
resp = app.get('/astregs/test/get-contact',
params={'contact_id': '1111'})
assert resp.json['err'] == 0
assert resp.json['data']
data = resp.json['data']
assert data['idContact'] == '1111'
assert data['CodeContact'] == 'POL14466'
assert data['Nom'] == 'NARDELLI'
assert data['Prenom'] == 'Robert'
assert data['ComplementGeographique'] == 'Mairie'
assert data['CodePostal'] == '06340'
assert data['Ville'] == 'DRAP'
assert data['LibellePays'] == 'France'
mocked_post.return_value = mock.Mock(content=get_xml_file('ContactResponse.xml'), status_code=500,
headers={'Content-Type': 'text/xml'})
resp = app.get('/astregs/test/get-contact',
params={'contact_id': '4242'})
assert not resp.json['data']
assert resp.json['err'] == 1
assert resp.json['err_class'] == 'passerelle.utils.jsonresponse.APIError'
@mock.patch('passerelle.utils.Request.get', side_effect=ConnectionError('mocked error', request=Request()))
@mock.patch('passerelle.utils.Request.post', side_effect=NotImplementedError)
def test_low_level_connection_error(mocked_post, mocked_get, tiers_response, tiers_error_response,
connector, app):
resp = app.get('/astregs/test/get-association-by-id', params={'association_id': '487464'})
assert resp.json['err'] == 1
assert resp.json['data'] is None
assert 'mocked error' in resp.json['err_desc']
@mock.patch('passerelle.utils.Request.get', side_effect=contact_wsdl_side_effect)
@mock.patch('passerelle.utils.Request.post', side_effect=contact_side_effect)
def test_create_association_contact(mocked_post, mocked_get, connector, app):
payload = {
'AdresseDestinataire': '169 rue du Ch\xc3\xa2teau',
'Ville': 'Nice',
'CodeContact': 'AS207002',
'Commentaire': 'Contact creation',
'country_code': 'FR',
'AdresseMail': 'foo@example.com',
'Prenom': 'Foo',
'Nom': 'Bar',
'TelephoneMobile': '0607080900',
'TelephoneBureau': '0102030405',
'CodeTitreCivilite': '035',
'PageWeb': 'http://example.com',
'CodePostal': '06000',
'CodeFonction': '01',
'EncodeKeyStatut': 'VALIDE'
}
resp = app.post_json('/astregs/test/create-contact', params=payload)
assert resp.json['data']
data = resp.json['data']
assert data['idContact'] == '437309'
assert data['Prenom'] == 'Foo'
assert data['Nom'] == 'Bar'
assert data['CodeFonction'] == '01'
assert data['PageWeb'] == 'http://example.com'
assert data['AdresseMail'] == 'foo@example.com'
assert data['LibellePays'] == 'France'
assert data['CodePays'] == 'FR'
assert data['CodeTitreCivilite'] == '035'
assert data['CodeContact'] == 'AS207002'
assert data['TelephoneBureau'] == '0102030405'
assert data['TelephoneMobile'] == '0607080900'
@mock.patch('passerelle.utils.Request.get')
@mock.patch('passerelle.utils.Request.post')
def test_delete_association_contact(mocked_post, mocked_get, connector, app):
mocked_get.return_value = mock.Mock(content=get_xml_file('Contact.wsdl'))
mocked_post.return_value = mock.Mock(content=get_xml_file('ContactDeletionResponse.xml'),
headers={'Content-Type': 'text/xml'},
status_code=200)
resp = app.get('/astregs/test/delete-contact', params={'contact_id': '437307'})
assert resp.json['data']
# if contact is deleted the its id is None
assert resp.json['data']['idContact'] is None
@mock.patch('passerelle.utils.Request.get')
@mock.patch('passerelle.utils.Request.post')
def test_create_document(mocked_post, mocked_get, connector, app):
mocked_get.return_value = mock.Mock(content=get_xml_file('DocumentAnnexe.wsdl'))
mocked_post.return_value = mock.Mock(content=get_xml_file('DocumentCreationResponse.xml'),
headers={'Content-Type': 'text/xml'},
status_code=200)
payload = {
'Sujet': 'Test',
'Entite': 'COMMANDE',
'CodType': 'COMMANDE',
'Type': 'Type label',
'hdnCodeTrt': 'UPDATE',
'EncodeKeyEntite': '|25901|',
'CodeDomaine': 'GF',
'CodDom': 'GF',
'Metadonnees': '|Organisme *CG06|Code Tiers *1|',
'document': {
'filename': 'test.pdf',
'content_type': 'application/pdf',
'content': 'base64encodedcontent'
}
}
resp = app.post_json('/astregs/test/create-document', params=payload)
assert resp.json['data']
assert resp.json['data']['RefDocument'] == '111'
assert resp.json['data']['NumVersion'] == '1'
@mock.patch('passerelle.utils.Request.get')
@mock.patch('passerelle.utils.Request.post')
def test_create_grant_demand(mocked_post, mocked_get, connector, app):
mocked_get.return_value = mock.Mock(content=get_xml_file('Dossier.wsdl'))
mocked_post.return_value = mock.Mock(content=get_xml_file('DossierCreationResponse.xml'),
headers={'Content-Type': 'text/xml'},
status_code=200)
payload = {
'Libelle': 'test grant demand',
'LibelleCourt': 'test',
'ModGestion': '1',
'TypeAide': 'F',
'Sens': 'D',
'CodeTiersDem': '487473',
'CodeServiceGestionnaire': 'SGG',
'CodeAide': '030105',
'CodeServiceUtilisateur': '030105',
}
resp = app.post_json('/astregs/test/create-grant-demand', params=payload)
assert resp.json['data']
data = resp.json['data']
assert data['CodeDossier'] =='2019_06407'
assert data['Exercice'] == '2019'
assert data['Libelle'] == 'test grant demand'
assert data['LibelleCourt'] == 'test'
assert data['ModGestion'] == '1'
assert data['CodeServiceGestionnaire'] == 'SGG'
assert data['CodeServiceUtilisateur'] == 'SUG4'
assert data['LibelleServiceUtilisateur'] == 'SPORTS ET JEUNESSE'
assert data['TypeAide'] == 'F'
assert data['CodeAide'] == '030105'
assert data['LibelleAide'] == 'Actions culturelles - Etab publics locaux'
assert data['Sens'] == 'D'
assert data['CodeTiersDem'] == '487463'
assert data['NomTiersDem'] == 'My Tiers'
assert data['CodeStatut'] == 'ENR'
assert data['DateCreation'] == '11/07/2019'
@mock.patch('passerelle.utils.Request.get')
@mock.patch('passerelle.utils.Request.post')
def test_create_indana_indicator(mocked_post, mocked_get, connector, app):
mocked_get.return_value = mock.Mock(content=get_xml_file('DossierIndicateur.wsdl'))
mocked_post.return_value = mock.Mock(content=get_xml_file('DossierIndicateurCreationResponse.xml'),
headers={'Content-Type': 'text/xml'},
status_code=200)
payload = {
'CodeDossier': '2019_06407',
'CodeInd_1': '501',
'AnneeInd_1': '2019',
'ValInd_1': 'O'
}
resp = app.post_json('/astregs/test/create-indana-indicator', params=payload)
assert resp.json['err'] == 0
assert resp.json['data']
data = resp.json['data']
assert data['CodeDossier'] == '2019_06407'
assert data['CodeInd_1'] == '501'
assert data['AnneeInd_1'] == '2019'
assert data['ValInd_1'] == 'O'
assert data['IndAide'] == 'Non'
@mock.patch('passerelle.utils.Request.get')
@mock.patch('passerelle.utils.Request.post')
def test_update_indana_indicator(mocked_post, mocked_get, connector, app):
mocked_get.return_value = mock.Mock(content=get_xml_file('DossierIndicateur.wsdl'))
mocked_post.return_value = mock.Mock(content=get_xml_file('DossierIndicateurModificationResponse.xml'),
headers={'Content-Type': 'text/xml'},
status_code=200)
payload = {
'CodeDossier': '2019_06407',
'CodeInd_1': '501',
'AnneeInd_1': '2019',
'ValInd_1': 'N'
}
resp = app.post_json('/astregs/test/update-indana-indicator', params=payload)
assert resp.json == {
'err': 0,
'data': {
'CodeDossier':'2019_06407',
'CodeInd_1': '501',
'AnneeInd_1': '2019',
'ValInd_1': 'N',
'IndAide': 'Non'
}
}
@mock.patch('passerelle.utils.Request.get')
@mock.patch('passerelle.utils.Request.post')
def test_delete_indana_indicator(mocked_post, mocked_get, connector, app):
mocked_get.return_value = mock.Mock(content=get_xml_file('DossierIndicateur.wsdl'))
mocked_post.return_value = mock.Mock(content=get_xml_file('DossierIndicateurSuppressionResponse.xml'),
headers={'Content-Type': 'text/xml'},
status_code=200)
payload = {
'CodeDossier': '2019_06407',
'CodeInd_1': '501',
'AnneeInd_1': '2019'
}
resp = app.post_json('/astregs/test/delete-indana-indicator', params=payload)
assert resp.json == {
'err': 0,
'data': {
'CodeDossier':'2019_06407',
'CodeInd_1': '501',
'AnneeInd_1': '2019',
'ValInd_1': 'N',
'IndAide': 'Non'
}
}