# 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 . 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 '): BirthDate('toto') with pytest.raises( APIError, match=r'Invalid date \(2017-02-30\) for : 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()