287 lines
11 KiB
Python
287 lines
11 KiB
Python
# Passerelle - uniform access to data and services
|
|
# 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; exclude 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.deepcopy of the GNU Affero General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
import json
|
|
import os
|
|
import shutil
|
|
import stat
|
|
|
|
import pytest
|
|
from django.core.files.storage import default_storage
|
|
from lxml import etree
|
|
from lxml import objectify as xobject
|
|
|
|
import tests.utils
|
|
from passerelle.apps.cityweb.cityweb import DateType
|
|
from passerelle.apps.cityweb.models import CityWeb
|
|
from passerelle.utils import SFTP
|
|
from passerelle.utils.jsonresponse import APIError
|
|
|
|
|
|
def get_test_base_dir(name):
|
|
return os.path.join(os.path.dirname(__file__), 'data', name)
|
|
|
|
|
|
def get_file_from_test_base_dir(filename):
|
|
path = os.path.join(get_test_base_dir('cityweb'), filename)
|
|
with open(path) as fd:
|
|
return fd.read()
|
|
|
|
|
|
@pytest.fixture
|
|
def setup(db):
|
|
return tests.utils.setup_access_rights(CityWeb.objects.create(slug='test'))
|
|
|
|
|
|
PAYLOAD = [
|
|
{'birth': json.loads(get_file_from_test_base_dir('payload_birth.json'))},
|
|
{'mariage': json.loads(get_file_from_test_base_dir('payload_mariage.json'))},
|
|
{'death': json.loads(get_file_from_test_base_dir('payload_death.json'))},
|
|
]
|
|
|
|
|
|
@pytest.fixture(params=PAYLOAD)
|
|
def payload(request):
|
|
return request.param
|
|
|
|
|
|
def assert_xml_doc(filename, assertions):
|
|
with open(os.path.join(get_test_base_dir('cityweb'), 'cityweb.xsd')) as fd:
|
|
schema = etree.XMLSchema(etree.parse(fd))
|
|
|
|
with open(filename) as fd:
|
|
content = fd.read()
|
|
xml_content = etree.fromstring(content)
|
|
assert len(xml_content.nsmap) == 1
|
|
assert xml_content.nsmap['xs'] == "http://tempuri.org/XMLSchema.xsd"
|
|
schema.assertValid(xml_content)
|
|
root = xobject.fromstring(content)
|
|
for epath, value in assertions.items():
|
|
path = xobject.ObjectPath('demandeEtatCivil.%s' % epath)
|
|
assert path.find(root) == value
|
|
|
|
|
|
def test_demand_creation(app, setup, payload):
|
|
url = '/cityweb/test/create/'
|
|
if 'birth' in payload:
|
|
response = app.post_json(url, params=payload['birth'])
|
|
assert response.json['data']['demand_id'] == 'N201610154'
|
|
filename = default_storage.path(os.path.join('cityweb', 'test', 'N201610154.xml'))
|
|
assertions = {
|
|
'identifiant': 'N201610154',
|
|
'demandeur.qualiteDemandeur': 'concerne',
|
|
'demandeur.individu.noms.nomDeFamille': 'Whatever',
|
|
'demandeur.individu.prenoms': 'Kim Chelsea',
|
|
'demandeur.individu.adresse.ligneAdr1': "37 Rue de l'Aigle Blanc",
|
|
'demandeur.individu.adresse.codePostal': 54000,
|
|
'demandeur.individu.adresse.lieu.ville': 'Nancy',
|
|
'demandeur.individu.adresse.lieu.pays': 'France',
|
|
'demandeur.individu.adresse.mail': 'chelsea@whatever.com',
|
|
'natureDocument': 'CPI',
|
|
'nbExemplaire': 1,
|
|
'dateDemande': '2016-10-20T14:41:20Z',
|
|
'evenement.natureEvenement': 'NAI',
|
|
'evenement.dateEvenement.dateDebut': '2012-07-14',
|
|
'evenement.lieuEvenement.ville': 'Nancy',
|
|
'evenement.interesse.pere.noms.nomDeFamille': 'Smith',
|
|
'evenement.interesse.pere.prenoms': 'John Oliver',
|
|
'evenement.interesse.mere.noms.nomDeFamille': 'Smith',
|
|
'evenement.interesse.mere.prenoms': 'Kim',
|
|
}
|
|
assert bool(os.stat(filename).st_mode & stat.S_IRUSR)
|
|
assert bool(os.stat(filename).st_mode & stat.S_IRGRP)
|
|
assert_xml_doc(filename, assertions)
|
|
|
|
elif 'mariage' in payload:
|
|
response = app.post_json(url, params=payload['mariage'])
|
|
assert response.json['data']['demand_id'] == 'M201610161'
|
|
filename = default_storage.path(os.path.join('cityweb', 'test', 'M201610161.xml'))
|
|
assertions = {
|
|
'identifiant': 'M201610161',
|
|
'demandeur.qualiteDemandeur': 'concerne',
|
|
'demandeur.individu.noms.nomDeFamille': 'Whatever',
|
|
'demandeur.individu.prenoms': 'Kim Chelsea',
|
|
'demandeur.individu.adresse.ligneAdr1': "37 Rue de l'Aigle Blanc",
|
|
'demandeur.individu.adresse.codePostal': 54000,
|
|
'demandeur.individu.adresse.lieu.ville': 'Nancy',
|
|
'demandeur.individu.adresse.lieu.pays': 'France',
|
|
'demandeur.individu.adresse.mail': 'chelsea@whatever.com',
|
|
'natureDocument': 'CPI',
|
|
'nbExemplaire': 1,
|
|
'dateDemande': '2016-10-20T14:41:20Z',
|
|
'evenement.natureEvenement': 'MAR',
|
|
'evenement.dateEvenement.dateDebut': '2012-07-14',
|
|
'evenement.lieuEvenement.ville': 'Nancy',
|
|
'evenement.interesse.pere.noms.nomDeFamille': 'Smith',
|
|
'evenement.interesse.pere.prenoms': 'John Oliver',
|
|
'evenement.interesse.mere.noms.nomDeFamille': 'Smith',
|
|
'evenement.interesse.mere.prenoms': 'Kim',
|
|
'evenement.conjoint.noms.nomDeFamille': 'Contrao',
|
|
'evenement.conjoint.pere.noms.nomDeFamille': 'Scaramucci',
|
|
'evenement.conjoint.pere.prenoms': 'Antonio',
|
|
'evenement.conjoint.mere.noms.nomDeFamille': 'Scaramucci',
|
|
'evenement.conjoint.mere.prenoms': 'Marguerite',
|
|
}
|
|
assert bool(os.stat(filename).st_mode & stat.S_IRUSR)
|
|
assert bool(os.stat(filename).st_mode & stat.S_IRGRP)
|
|
assert_xml_doc(filename, assertions)
|
|
else:
|
|
response = app.post_json(url, params=payload['death'])
|
|
assert response.json['data']['demand_id'] == 'D201610171'
|
|
filename = default_storage.path(os.path.join('cityweb', 'test', 'D201610171.xml'))
|
|
assertions = {
|
|
'identifiant': 'D201610171',
|
|
'demandeur.qualiteDemandeur': 'concerne',
|
|
'demandeur.individu.noms.nomDeFamille': 'Whatever',
|
|
'demandeur.individu.prenoms': 'Kim Chelsea',
|
|
'demandeur.individu.adresse.ligneAdr1': "37 Rue de l'Aigle Blanc",
|
|
'demandeur.individu.adresse.codePostal': 54000,
|
|
'demandeur.individu.adresse.lieu.ville': 'Nancy',
|
|
'demandeur.individu.adresse.lieu.pays': 'France',
|
|
'demandeur.individu.adresse.mail': 'chelsea@whatever.com',
|
|
'natureDocument': 'EXTSF',
|
|
'nbExemplaire': 1,
|
|
'dateDemande': '2016-10-20T14:41:20Z',
|
|
'evenement.natureEvenement': 'DEC',
|
|
'evenement.dateEvenement.dateDebut': '2012-07-14',
|
|
'evenement.lieuEvenement.ville': 'Nancy',
|
|
}
|
|
assert bool(os.stat(filename).st_mode & stat.S_IRUSR)
|
|
assert bool(os.stat(filename).st_mode & stat.S_IRGRP)
|
|
assert_xml_doc(filename, assertions)
|
|
|
|
|
|
def test_date_type_parsing():
|
|
class BirthDate(DateType):
|
|
tagname = 'date'
|
|
|
|
with pytest.raises(APIError, match=r'Invalid date \(toto\) for <date>'):
|
|
BirthDate('toto')
|
|
|
|
with pytest.raises(
|
|
APIError, match=r'Invalid date \(2017-02-30\) for <date>: day is out of range for month'
|
|
):
|
|
BirthDate('2017-02-30')
|
|
|
|
assert BirthDate('2017-02-22').value == '2017-02-22'
|
|
|
|
|
|
def test_datasource_titles(app, setup):
|
|
response = app.get('/cityweb/test/titles/')
|
|
data = response.json['data']
|
|
assert len(data) == 3
|
|
for datum in data:
|
|
if datum['id'] == 'M':
|
|
assert datum['text'] == 'Monsieur'
|
|
elif datum['id'] == 'Mme':
|
|
assert datum['text'] == 'Madame'
|
|
else:
|
|
assert datum['id'] == 'Mlle'
|
|
assert datum['text'] == 'Mademoiselle'
|
|
|
|
|
|
def test_datasource_sexes(app, setup):
|
|
response = app.get('/cityweb/test/sexes/')
|
|
data = response.json['data']
|
|
assert len(data) == 3
|
|
for datum in data:
|
|
if datum['id'] == 'M':
|
|
assert datum['text']
|
|
elif datum['id'] == 'F':
|
|
assert datum['text'] == 'Femme'
|
|
else:
|
|
assert datum['id'] == 'NA'
|
|
assert datum['text'] == 'Autre'
|
|
|
|
|
|
def test_datasource_concerned(app, setup):
|
|
response = app.get('/cityweb/test/concerned/')
|
|
data = response.json['data']
|
|
assert len(data) == 2
|
|
for datum in data:
|
|
if datum['id'] == 'reconnu':
|
|
assert datum['text'] == 'Reconnu'
|
|
else:
|
|
assert datum['id'] == 'auteur'
|
|
assert datum['text'] == 'Auteur'
|
|
|
|
|
|
def test_datasource_origins(app, setup):
|
|
response = app.get('/cityweb/test/origins/')
|
|
data = response.json['data']
|
|
assert len(data) == 3
|
|
for datum in data:
|
|
if datum['id'] == 'internet':
|
|
assert datum['text'] == 'Internet'
|
|
elif datum['id'] == 'guichet':
|
|
assert datum['text'] == 'Guichet'
|
|
else:
|
|
assert datum['id'] == 'courrier'
|
|
assert datum['text'] == 'Courrier'
|
|
|
|
|
|
def test_datasource_document_types(app, setup):
|
|
response = app.get('/cityweb/test/document-types/')
|
|
data = response.json['data']
|
|
assert len(data) == 4
|
|
for datum in data:
|
|
if datum['id'] == 'CPI':
|
|
assert datum['text'] == 'Copie intégrale'
|
|
elif datum['id'] == 'EXTAF':
|
|
assert datum['text'] == 'Extrait avec filiation'
|
|
elif datum['id'] == 'EXTSF':
|
|
assert datum['text'] == 'Extrait sans filiation'
|
|
else:
|
|
assert datum['id'] == 'EXTPL'
|
|
assert datum['text'] == 'Extrait plurilingue'
|
|
|
|
params = {'exclude': 'EXTAF,EXTSF,EXTPL'}
|
|
response = app.get('/cityweb/test/document-types/', params=params)
|
|
data = response.json['data']
|
|
assert len(data) == 1
|
|
assert data[0]['id'] == 'CPI'
|
|
assert data[0]['text'] == 'Copie intégrale'
|
|
|
|
|
|
def test_datasource_certificate_types(app, setup):
|
|
response = app.get('/cityweb/test/certificate-types/')
|
|
data = response.json['data']
|
|
assert len(data) == 4
|
|
for datum in data:
|
|
if datum['id'] == 'NAI':
|
|
assert datum['text'] == 'Naissance'
|
|
elif datum['id'] == 'MAR':
|
|
assert datum['text'] == 'Mariage'
|
|
elif datum['id'] == 'REC':
|
|
assert datum['text'] == 'Reconnaissance'
|
|
else:
|
|
assert datum['id'] == 'DEC'
|
|
assert datum['text'] == 'Décès'
|
|
|
|
|
|
def teardown_module(module):
|
|
shutil.rmtree(os.path.join(get_test_base_dir('cityweb'), 'test'), ignore_errors=True)
|
|
|
|
|
|
def test_demand_creation_with_remote_sftp(app, setup, payload, sftpserver):
|
|
setup.incoming_sftp = SFTP('sftp://foo:bar@{server.host}:{server.port}/input/'.format(server=sftpserver))
|
|
setup.save()
|
|
for payload_value in payload.values():
|
|
resp = app.post_json('/cityweb/test/create', params=payload_value, status=200)
|
|
expected_filename = '%s.xml' % resp.json['data']['demand_id']
|
|
with sftpserver.serve_content({'input': {expected_filename: 'content'}}):
|
|
setup.jobs()
|