def test_post_form(app): from zam_repondeur.models import Lecture assert not Lecture.exists( chambre="an", session="15", num_texte=269, organe="PO717460" ) # We cannot use form.submit() given the form is dynamic and does not # contain choices for lectures (dynamically loaded via JS). resp = app.post( "/lectures/add", {"dossier": "DLR5L15N36030", "lecture": "PRJLANR5L15B0269-PO717460"}, ) assert resp.status_code == 302 assert resp.location == "http://localhost/lectures/an.15.269.PO717460/" resp = resp.follow() assert resp.status_code == 200 assert "Lecture créée avec succès." in resp.text lecture = Lecture.get(chambre="an", session="15", num_texte=269, organe="PO717460") assert lecture.chambre == "an" assert lecture.titre == "1ère lecture" assert lecture.dossier_legislatif == "Sécurité sociale : loi de financement 2018"
def test_upload_liasse_success( app, lecture_essoc2018_an_nouvelle_lecture_commission_fond, user_david): from zam_repondeur.models import Lecture resp = app.get("/lectures/an.15.806.PO744107/options", user=user_david) form = resp.forms["import-liasse-xml"] form["liasse"] = Upload("liasse.xml", (SAMPLE_DATA / "liasse.xml").read_bytes()) resp = form.submit() assert resp.status_code == 302 assert resp.location == "https://zam.test/lectures/an.15.806.PO744107/amendements" resp = resp.follow() assert "3 nouveaux amendements récupérés (import liasse XML)." in resp.text lecture = Lecture.get( chambre=lecture_essoc2018_an_nouvelle_lecture_commission_fond.chambre, session_or_legislature= lecture_essoc2018_an_nouvelle_lecture_commission_fond.session, # noqa num_texte=lecture_essoc2018_an_nouvelle_lecture_commission_fond.texte. numero, partie=None, organe=lecture_essoc2018_an_nouvelle_lecture_commission_fond.organe, ) assert lecture.events[0].render_summary() == ( "<abbr title='*****@*****.**'>[email protected]</abbr> a importé " "une liasse XML : 3 nouveaux amendements récupérés.")
def test_upload_liasse_with_table( app, lecture_essoc2018_an_nouvelle_lecture_commission_fond, user_david): from zam_repondeur.models import Lecture resp = app.get("/lectures/an.15.806.PO744107/options", user=user_david) form = resp.forms["import-liasse-xml"] form["liasse"] = Upload( "liasse.xml", (SAMPLE_DATA / "liasse_with_table.xml").read_bytes()) resp = form.submit() assert resp.status_code == 302 assert resp.location == "https://zam.test/lectures/an.15.806.PO744107/amendements" resp = resp.follow() assert "3 nouveaux amendements récupérés (import liasse XML)." in resp.text lecture = Lecture.get( chambre=lecture_essoc2018_an_nouvelle_lecture_commission_fond.chambre, session_or_legislature= lecture_essoc2018_an_nouvelle_lecture_commission_fond.session, # noqa num_texte=lecture_essoc2018_an_nouvelle_lecture_commission_fond.texte. numero, partie=None, organe=lecture_essoc2018_an_nouvelle_lecture_commission_fond.organe, ) assert ("<table>\n<tbody>\n<tr>\n<td>Durée minimale de services" in lecture.amendements[1].corps) assert ("<table>\n<tbody>\n<tr>\n<td>Durée minimale de services" in lecture.amendements[0].expose)
def test_upload_liasse_missing_file( app, lecture_essoc2018_an_nouvelle_lecture_commission_fond, user_david): from zam_repondeur.models import Lecture resp = app.get("/lectures/an.15.806.PO744107/options", user=user_david) form = resp.forms["import-liasse-xml"] resp = form.submit() assert resp.status_code == 302 assert resp.location == "https://zam.test/lectures/an.15.806.PO744107/options" resp = resp.follow() assert "Veuillez d’abord sélectionner un fichier" in resp.text # Check the update timestamp has NOT been updated. lecture = Lecture.get( chambre=lecture_essoc2018_an_nouvelle_lecture_commission_fond.chambre, session_or_legislature= lecture_essoc2018_an_nouvelle_lecture_commission_fond.session, # noqa num_texte=lecture_essoc2018_an_nouvelle_lecture_commission_fond.texte. numero, partie=None, organe=lecture_essoc2018_an_nouvelle_lecture_commission_fond.organe, ) assert lecture.events == []
def test_post_form(app, lecture_an, article1_an, user_david): from zam_repondeur.models import Amendement, Lecture # Initially, we only have one amendement (#135), with a response with transaction.manager: Amendement.create(lecture=lecture_an, article=article1_an, num=135, position=1) assert lecture_an.events == [] with setup_mock_responses( lecture=lecture_an, liste=read_sample_data("an/269/liste.xml"), amendements=( ("177", read_sample_data("an/269/177.xml")), ("270", read_sample_data("an/269/270.xml")), ("723", read_sample_data("an/269/723.xml")), ("135", read_sample_data("an/269/135.xml")), ("192", read_sample_data("an/269/192.xml")), ), ) as mock_resp: mock_resp.add( responses.GET, "http://www.assemblee-nationale.fr/15/projets/pl0269.asp", body=(Path(__file__).parent / "sample_data" / "pl0269.html").read_text( "utf-8", "ignore" ), status=200, ) # Then we ask for a refresh form = app.get("/lectures/an.15.269.PO717460/journal/", user=user_david).forms[ "manual-refresh" ] resp = form.submit() assert resp.status_code == 302 assert resp.location == "https://zam.test/lectures/an.15.269.PO717460/amendements" resp = resp.follow() assert resp.status_code == 200 lecture_an = Lecture.get( chambre=lecture_an.chambre, session_or_legislature=lecture_an.session, num_texte=lecture_an.texte.numero, partie=None, organe=lecture_an.organe, ) events = lecture_an.events assert len(events) == 2 assert events[0].render_summary() == "Le contenu des articles a été récupéré." assert events[1].render_summary() == "4 nouveaux amendements récupérés." assert "Rafraichissement des amendements et des articles en cours." in resp.text
def model(self, *options: Any) -> Lecture: lecture = Lecture.get( self.chambre, self.session_or_legislature, self.num_texte, self.partie, self.organe, *options, ) if lecture is None: raise ResourceNotFound(self) return lecture
def test_upload_adds_an_event(self, app, lecture_an, filename, user_david): from zam_repondeur.models import Lecture from zam_repondeur.models.events.lecture import ReponsesImportees self._upload_csv(app, filename, user=user_david) lecture = Lecture.get( chambre=lecture_an.chambre, session_or_legislature=lecture_an.session, num_texte=lecture_an.texte.numero, partie=None, organe=lecture_an.organe, ) events = {type(event): event for event in lecture.events} assert ReponsesImportees in events
def test_post_form_updates_modification_date(app, dummy_lecture, dummy_amendements): from zam_repondeur.models import Lecture with transaction.manager: initial_modified_at = dummy_lecture.modified_at form = app.get("/lectures/an.15.269.PO717460/amendements/").forms["import-form"] path = Path(__file__).parent / "sample_data" / "reponses.csv" form["reponses"] = Upload("file.csv", path.read_bytes()) form.submit() with transaction.manager: lecture = Lecture.get( chambre=dummy_lecture.chambre, session=dummy_lecture.session, num_texte=dummy_lecture.num_texte, organe=dummy_lecture.organe, ) assert lecture.modified_at != initial_modified_at
def test_post_reponse_edit_form_updates_modification_date( app, dummy_lecture, dummy_amendements): from zam_repondeur.models import Lecture with transaction.manager: initial_modified_at = dummy_lecture.modified_at resp = app.get( "http://localhost/lectures/an.15.269.PO717460/amendements/999/reponse") form = resp.forms["edit-reponse"] form["avis"] = "Favorable" form["observations"] = "Des observations très pertinentes" form["reponse"] = "Une réponse très appropriée" form.submit() with transaction.manager: lecture = Lecture.get( chambre=dummy_lecture.chambre, session=dummy_lecture.session, num_texte=dummy_lecture.num_texte, organe=dummy_lecture.organe, ) assert lecture.modified_at != initial_modified_at
def test_plfss_2018_an(self, app, user_sgg, dossier_plfss2018): from zam_repondeur.models import Chambre, DBSession, Dossier, Lecture, User with transaction.manager: DBSession.add(user_sgg) assert len(user_sgg.teams) == 0 assert not DBSession.query(Lecture).all() responses.add( responses.GET, "http://www.assemblee-nationale.fr/eloi/15/amendements/0269/AN/liste.xml", body=read_sample_data("an/269/liste.xml"), status=200, ) responses.add( responses.GET, "http://www.assemblee-nationale.fr/dyn/15/amendements/0269/AN/177.xml", body=read_sample_data("an/269/177.xml"), status=200, ) responses.add( responses.GET, "http://www.assemblee-nationale.fr/dyn/15/amendements/0269/AN/270.xml", body=read_sample_data("an/269/270.xml"), status=200, ) responses.add( responses.GET, "http://www.assemblee-nationale.fr/dyn/15/amendements/0269/AN/723.xml", body=read_sample_data("an/269/723.xml"), status=200, ) responses.add( responses.GET, "http://www.assemblee-nationale.fr/dyn/15/amendements/0269/AN/135.xml", body=read_sample_data("an/269/135.xml"), status=200, ) responses.add( responses.GET, "http://www.assemblee-nationale.fr/dyn/15/amendements/0269/AN/192.xml", body=read_sample_data("an/269/192.xml"), status=200, ) responses.add( responses.GET, "http://www.assemblee-nationale.fr/15/projets/pl0269.asp", body=(SAMPLE_DATA_DIR / "pl0269.html").read_text("utf-8", "ignore"), status=200, ) responses.add( responses.GET, "https://www.senat.fr/leg/pjl17-063.html", body=(SAMPLE_DATA_DIR / "pjl17-063.html").read_text("utf-8", "ignore"), status=200, ) responses.add( responses.GET, ( "https://www.senat.fr" "/amendements/2017-2018/63/jeu_complet_2017-2018_63.csv" ), body=read_sample_data_bytes("senat/jeu_complet_2017-2018_63.csv"), status=200, ) responses.add( responses.GET, "https://www.senat.fr/enseance/2017-2018/63/liste_discussion.json", json=json.loads(read_sample_data_bytes("senat/liste_discussion_63.json")), status=200, ) responses.add( responses.GET, "https://www.senat.fr/encommission/2017-2018/63/liste_discussion.json", status=404, ) responses.add( responses.GET, "https://data.senat.fr/data/senateurs/ODSEN_GENERAL.csv", body=(FETCH_SAMPLE_DATA_DIR / "senat" / "ODSEN_GENERAL.csv").read_bytes(), status=200, ) responses.add( responses.GET, "https://www.senat.fr/dossier-legislatif/rss/doslegplfss2018.xml", body=(SAMPLE_DATA_DIR / "doslegplfss2018.xml").read_bytes(), status=200, ) with transaction.manager: dossier_plfss2018.team = None DBSession.add(dossier_plfss2018) resp = app.get("/dossiers/add", user=user_sgg) form = resp.forms["add-dossier"] form["dossier"] = "plfss-2018" resp = form.submit() assert resp.status_code == 302 assert resp.location == "https://zam.test/dossiers/plfss-2018/" resp = resp.follow() assert resp.status_code == 200 assert "Dossier créé avec succès," in resp.text user_sgg = DBSession.query(User).filter(User.pk == user_sgg.pk).one() dossier_plfss2018 = ( DBSession.query(Dossier).filter(Dossier.slug == "plfss-2018").one() ) assert len(user_sgg.teams) == 1 assert dossier_plfss2018.team in user_sgg.teams assert len(dossier_plfss2018.events) == 2 assert ( dossier_plfss2018.events[0].render_summary() == "<abbr title='*****@*****.**'>SGG user</abbr> a activé le dossier." ) assert ( dossier_plfss2018.events[1].render_summary() == "De nouvelles lectures ont été récupérées." ) lecture = Lecture.get( chambre=Chambre.AN, session_or_legislature="15", num_texte=269, partie=None, organe="PO717460", ) assert lecture.chambre == Chambre.AN assert lecture.titre == "Première lecture – Titre lecture" assert lecture.dossier.titre == "Sécurité sociale : loi de financement 2018" result = ( "Assemblée nationale, 15e législature, Séance publique, Première lecture, " "texte nº\u00a0269" ) assert str(lecture) == result # We should have an event entry for articles, and one for amendements assert len(lecture.events) == 3 assert lecture.events[0].render_summary() == "5 nouveaux amendements récupérés." assert ( lecture.events[1].render_summary() == "Le contenu des articles a été récupéré." ) assert ( lecture.events[2].render_summary() == "<abbr title='*****@*****.**'>SGG user</abbr> a créé la lecture." ) # We expect articles from the page (1, 2) and from the amendements (3, 8, 9) assert {article.num for article in lecture.articles} == { "1", "2", "3", "8", "9", } # We should have loaded 5 amendements assert [amdt.num for amdt in lecture.amendements] == [177, 270, 723, 135, 192]
def test_plfss_2019_senat(self, app, user_sgg, dossier_plfss2019): from zam_repondeur.models import Chambre, DBSession, Lecture assert not DBSession.query(Lecture).all() responses.add( responses.GET, "https://www.senat.fr/amendements/2018-2019/106/jeu_complet_2018-2019_106.csv", # noqa body=( FETCH_SAMPLE_DATA_DIR / "senat" / "jeu_complet_2018-2019_106.csv" ).read_bytes(), status=200, ) responses.add( responses.GET, "https://www.senat.fr/enseance/2018-2019/106/liste_discussion.json", body=( FETCH_SAMPLE_DATA_DIR / "senat" / "liste_discussion_106.json" ).read_bytes(), status=200, ) responses.add( responses.GET, "https://www.senat.fr/dossier-legislatif/rss/doslegplfss2019.xml", body=(SAMPLE_DATA_DIR / "doslegplfss2019.xml").read_bytes(), status=200, ) responses.add( responses.GET, "https://www.senat.fr/leg/pjl18-106.html", body=(SAMPLE_DATA_DIR / "pjl18-106.html").read_text("utf-8", "ignore"), status=200, ) responses.add( responses.GET, "https://data.senat.fr/data/senateurs/ODSEN_GENERAL.csv", body=(FETCH_SAMPLE_DATA_DIR / "senat" / "ODSEN_GENERAL.csv").read_bytes(), status=200, ) resp = app.get("/dossiers/add", user=user_sgg) form = resp.forms["add-dossier"] form["dossier"] = "plfss-2019" resp = form.submit() assert resp.status_code == 302 assert resp.location == "https://zam.test/dossiers/plfss-2019/" resp = resp.follow() assert resp.status_code == 200 assert "Dossier créé avec succès," in resp.text lecture = Lecture.get( chambre=Chambre.SENAT, session_or_legislature="2018-2019", num_texte=106, partie=None, organe="PO78718", ) assert lecture.chambre == Chambre.SENAT assert lecture.titre == "Première lecture – Séance publique" assert lecture.dossier.titre == "Sécurité sociale : loi de financement 2019" result = ( "Sénat, session 2018-2019, Séance publique, Première lecture, texte nº 106" ) assert str(lecture) == result # We should have an event entry for articles, and one for amendements assert len(lecture.events) == 3 assert lecture.events[0].render_summary() == "2 nouveaux amendements récupérés." assert ( lecture.events[1].render_summary() == "Le contenu des articles a été récupéré." ) assert ( lecture.events[2].render_summary() == "<abbr title='*****@*****.**'>SGG user</abbr> a créé la lecture." ) # We should have articles from the page (1) and from the amendements (19, 29) assert {article.num for article in lecture.articles} == {"1", "19", "29"} # We should have loaded 2 amendements assert [amdt.num for amdt in lecture.amendements] == [629, 1]
def test_post_form(app, user_david): from zam_repondeur.models import DBSession, Lecture assert not DBSession.query(Lecture).all() responses.add( responses.GET, "http://www.assemblee-nationale.fr/eloi/15/amendements/0269/AN/liste.xml", body=read_sample_data("an/269/liste.xml"), status=200, ) responses.add( responses.GET, "http://www.assemblee-nationale.fr/15/xml/amendements/0269/AN/177.xml", body=read_sample_data("an/269/177.xml"), status=200, ) responses.add( responses.GET, "http://www.assemblee-nationale.fr/15/xml/amendements/0269/AN/270.xml", body=read_sample_data("an/269/270.xml"), status=200, ) responses.add( responses.GET, "http://www.assemblee-nationale.fr/15/xml/amendements/0269/AN/723.xml", body=read_sample_data("an/269/723.xml"), status=200, ) responses.add( responses.GET, "http://www.assemblee-nationale.fr/15/xml/amendements/0269/AN/135.xml", body=read_sample_data("an/269/135.xml"), status=200, ) responses.add( responses.GET, "http://www.assemblee-nationale.fr/15/xml/amendements/0269/AN/192.xml", body=read_sample_data("an/269/192.xml"), status=200, ) responses.add( responses.GET, re.compile( r"http://www\.assemblee-nationale\.fr/15/xml/amendements/0269/AN/\d+\.xml" ), status=404, ) responses.add( responses.GET, "http://www.assemblee-nationale.fr/15/projets/pl0269.asp", body=(HERE.parent / "sample_data" / "pl0269.html").read_text("utf-8", "ignore"), status=200, ) # We cannot use form.submit() given the form is dynamic and does not # contain choices for lectures (dynamically loaded via JS). resp = app.post( "/lectures/add", {"dossier": "DLR5L15N36030", "lecture": "PRJLANR5L15B0269-PO717460-"}, user=user_david, ) assert resp.status_code == 302 assert resp.location == "https://zam.test/lectures/an.15.269.PO717460/amendements" resp = resp.follow() assert resp.status_code == 200 assert "Lecture créée avec succès," in resp.text lecture = Lecture.get( chambre="an", session_or_legislature="15", num_texte=269, partie=None, organe="PO717460", ) assert lecture.chambre == "an" assert lecture.titre == "Première lecture – Titre lecture" assert lecture.dossier.titre == "Sécurité sociale : loi de financement 2018" result = ( "Assemblée nationale, 15e législature, Séance publique, Première lecture, " "texte nº\u00a0269" ) assert str(lecture) == result # We should have an event entry for articles, and one for amendements assert len(lecture.events) == 3 assert lecture.events[0].render_summary() == "5 nouveaux amendements récupérés." assert ( lecture.events[1].render_summary() == "Le contenu des articles a été récupéré." ) assert ( lecture.events[2].render_summary() == "<abbr title='*****@*****.**'>[email protected]</abbr> a créé la lecture." ) # We should have articles from the page (1, 2) and from the amendements (3, 8, 9) assert {article.num for article in lecture.articles} == {"1", "2", "3", "8", "9"} # We should have loaded 5 amendements assert [amdt.num for amdt in lecture.amendements] == [177, 270, 723, 135, 192]
def test_post_form_senat_2019(app, user_david): from zam_repondeur.models import DBSession, Lecture assert not DBSession.query(Lecture).all() responses.add( responses.GET, "https://www.senat.fr/amendements/2018-2019/106/jeu_complet_2018-2019_106.csv", body=( HERE.parent / "fetch" / "sample_data" / "senat" / "jeu_complet_2018-2019_106.csv" ).read_bytes(), status=200, ) responses.add( responses.GET, "https://www.senat.fr/enseance/2018-2019/106/liste_discussion.json", body=( HERE.parent / "fetch" / "sample_data" / "senat" / "liste_discussion_106.json" ).read_bytes(), status=200, ) responses.add( responses.GET, "https://www.senat.fr/leg/pjl18-106.html", body=(HERE.parent / "sample_data" / "pjl18-106.html").read_text( "utf-8", "ignore" ), status=200, ) responses.add( responses.GET, "https://data.senat.fr/data/senateurs/ODSEN_GENERAL.csv", body=( HERE.parent / "fetch" / "sample_data" / "senat" / "ODSEN_GENERAL.csv" ).read_bytes(), status=200, ) # We cannot use form.submit() given the form is dynamic and does not # contain choices for lectures (dynamically loaded via JS). resp = app.post( "/lectures/add", {"dossier": "DLR5L15N36892", "lecture": "PRJLSNR5S319B0106-PO78718-"}, user=user_david, ) assert resp.status_code == 302 assert ( resp.location == "https://zam.test/lectures/senat.2018-2019.106.PO78718/amendements" ) resp = resp.follow() assert resp.status_code == 200 assert "Lecture créée avec succès," in resp.text lecture = Lecture.get( chambre="senat", session_or_legislature="2018-2019", num_texte=106, partie=None, organe="PO78718", ) assert lecture.chambre == "senat" assert lecture.titre == "Première lecture – Titre lecture" assert lecture.dossier.titre == "Sécurité sociale : loi de financement 2019" result = "Sénat, session 2018-2019, Séance publique, Première lecture, texte nº 106" assert str(lecture) == result # We should have an event entry for articles, and one for amendements assert len(lecture.events) == 3 assert lecture.events[0].render_summary() == "2 nouveaux amendements récupérés." assert ( lecture.events[1].render_summary() == "Le contenu des articles a été récupéré." ) assert ( lecture.events[2].render_summary() == "<abbr title='*****@*****.**'>[email protected]</abbr> a créé la lecture." ) # We should have articles from the page (1) and from the amendements (19, 29) assert {article.num for article in lecture.articles} == {"1", "19", "29"} # We should have loaded 2 amendements assert [amdt.num for amdt in lecture.amendements] == [629, 1]
def model(self) -> LectureModel: lecture = LectureModel.get(self.chambre, self.session, self.num_texte, self.organe) if lecture is None: raise ResourceNotFound(self) return lecture