def test_column_filtering_by_checkbox( wsgi_server, driver, lecture_an, lecture_an_url, article1_an, amendements_an, user_david_table_an, column_index, kind, initial, filtered, ): from zam_repondeur.models import Amendement, DBSession with transaction.manager: DBSession.add(user_david_table_an) amendement = Amendement.create( lecture=lecture_an, article=article1_an, num=777, position=3, auteur="LE GOUVERNEMENT", ) user_david_table_an.add_amendement(amendement) driver.get(f"{lecture_an_url}/amendements/") trs = driver.find_elements_by_css_selector(f"tbody tr:not(.hidden-{kind})") assert extract_column_text(column_index, trs) == initial label = driver.find_element_by_css_selector( f"thead tr.filters th:nth-child({column_index}) label[for='{kind}']") label.click() trs = driver.find_elements_by_css_selector(f"tbody tr:not(.hidden-{kind})") assert extract_column_text(column_index, trs) == filtered assert driver.current_url == f"{lecture_an_url}/amendements/?{kind}=1" # Restore initial state. label.click() trs = driver.find_elements_by_css_selector(f"tbody tr:not(.hidden-{kind})") assert extract_column_text(column_index, trs) == initial assert driver.current_url == f"{lecture_an_url}/amendements/" # Check filters are active on URL (re)load. driver.get(f"{lecture_an_url}/amendements/?{kind}=1") trs = driver.find_elements_by_css_selector(f"tbody tr:not(.hidden-{kind})") assert extract_column_text(column_index, trs) == filtered label = driver.find_element_by_css_selector( f"thead tr.filters th:nth-child({column_index}) label[for='{kind}']") label.click() trs = driver.find_elements_by_css_selector(f"tbody tr:not(.hidden-{kind})") assert extract_column_text(column_index, trs) == initial assert driver.current_url == f"{lecture_an_url}/amendements/"
def test_column_filtering_by_value_with_shared_tables( wsgi_server, driver, lecture_an, lecture_an_url, article1_an, amendements_an, user_david_table_an, shared_table_lecture_an, column_index, input_text, kind, initial, filtered, ): from zam_repondeur.models import DBSession with transaction.manager: DBSession.add(user_david_table_an) DBSession.add(shared_table_lecture_an) user_david_table_an.add_amendement(amendements_an[0]) shared_table_lecture_an.add_amendement(amendements_an[1]) driver.get(f"{lecture_an_url}/amendements") trs = driver.find_elements_by_css_selector(f"tbody tr:not(.hidden-{kind})") assert extract_column_text(column_index, trs) == initial input_field = driver.find_element_by_css_selector( f"thead tr.filters th:nth-child({column_index}) input") input_field.send_keys(input_text) trs = driver.find_elements_by_css_selector(f"tbody tr:not(.hidden-{kind})") assert extract_column_text(column_index, trs) == filtered assert ( driver.current_url == f"{lecture_an_url}/amendements?{kind}={input_text.replace(' ', '+')}") # Restore initial state. input_field.send_keys(Keys.BACKSPACE * len(input_text)) trs = driver.find_elements_by_css_selector(f"tbody tr:not(.hidden-{kind})") assert extract_column_text(column_index, trs) == initial assert driver.current_url == f"{lecture_an_url}/amendements" # Check filters are active on URL (re)load. driver.get(f"{lecture_an_url}/amendements?{kind}={input_text}") trs = driver.find_elements_by_css_selector(f"tbody tr:not(.hidden-{kind})") assert extract_column_text(column_index, trs) == filtered input_field = driver.find_element_by_css_selector( f"thead tr.filters th:nth-child({column_index}) input") input_field.send_keys(Keys.BACKSPACE * len(input_text)) trs = driver.find_elements_by_css_selector(f"tbody tr:not(.hidden-{kind})") assert extract_column_text(column_index, trs) == initial assert driver.current_url == f"{lecture_an_url}/amendements"
def test_amendement_parent_relationship(amendements_an): from zam_repondeur.models import Amendement, DBSession a, b = DBSession.query(Amendement).all() assert a.parent is None assert b.parent is None b.parent = a # Note: when updating a relationship, the foreign key is only updated on a flush DBSession.flush() assert b.parent_pk == a.pk
def amendements_an(db, lecture_an, article1_an): from zam_repondeur.models import Amendement, DBSession with transaction.manager: amendements = [ Amendement.create( lecture=lecture_an, article=article1_an, num=num, position=position ) for position, num in enumerate((666, 999), 1) ] DBSession.add_all(amendements) return amendements
def test_not_possible_to_regular_user(self, app, user_sgg, user_david, user_ronan): from zam_repondeur.models import DBSession, User with transaction.manager: user_david.admin_at = datetime.utcnow() DBSession.add(user_david) assert DBSession.query(User).filter(User.admin_at.isnot(None)).count() == 2 resp = app.post("/admins/", {"user_pk": user_david.pk}, user=user_ronan) assert resp.status_code == 302 assert resp.location == "https://zam.test/" assert DBSession.query(User).filter(User.admin_at.isnot(None)).count() == 2
def test_reponses_without_textes(app, dummy_lecture, dummy_amendements): from zam_repondeur.models import DBSession with transaction.manager: for amendement in dummy_amendements: amendement.avis = "Favorable" amendement.observations = f"Observations pour {amendement.num}" amendement.reponse = f"Réponse pour {amendement.num}" DBSession.add_all(dummy_amendements) resp = app.get("http://localhost/lectures/an.15.269.PO717460/reponses") assert len(resp.parser.css("#content-article-1")) == 0
def setup_database(config: Configurator, settings: dict) -> None: config.include("pyramid_tm") engine = engine_from_config( settings, "sqlalchemy.", connect_args={"application_name": "zam_webapp"}) DBSession.configure(bind=engine) Base.metadata.bind = engine if asbool(settings.get("zam.log_sql_queries_with_origin")): event.listen(engine, "before_cursor_execute", log_query_with_origin)
def setup_database(config: Configurator, settings: dict) -> None: # Make sure the SQLAlchemy connection pool is large enough for worker threads pool_size = max(5, settings["huey.workers"]) config.include("pyramid_tm") engine = engine_from_config(settings, "sqlalchemy.", pool_size=pool_size) DBSession.configure(bind=engine) Base.metadata.bind = engine if asbool(settings.get("zam.log_sql_queries_with_origin")): event.listen(engine, "before_cursor_execute", log_query_with_origin)
def test_additional_articles_without_avis_are_not_listed( self, app, article1_an, article1av_an, amendements_an, user_david): from zam_repondeur.models import DBSession with transaction.manager: amendements_an[0].article = article1av_an DBSession.add_all(amendements_an) resp = app.get("/lectures/an.15.269.PO717460/articles/", user=user_david) assert resp.status_code == 200 titles = [node.text().strip() for node in resp.parser.css(".article")] assert titles == ["Article 1"]
def test_upload_success_event(self, app, user_david, lecture_an): from zam_repondeur.models import DBSession with transaction.manager: DBSession.add(user_david) self._upload_backup(app, "backup.json", user_david).follow() DBSession.add(lecture_an) assert len(lecture_an.events) == 1 assert lecture_an.events[0].render_summary() == ( "<abbr title='*****@*****.**'>David</abbr> " "a importé des réponses d’un fichier JSON.")
def test_fetch_amendements_with_errored( app, source_an, lecture_an, article1_an, amendements_an ): from zam_repondeur.models import Amendement, DBSession from zam_repondeur.services.fetch.an.amendements import ANDerouleurData from zam_repondeur.services.fetch.exceptions import NotFound DBSession.add(lecture_an) with patch( "zam_repondeur.services.fetch.an.amendements.fetch_discussion_list" ) as mock_fetch_discussion_list, patch( "zam_repondeur.services.fetch.an.amendements._retrieve_amendement_data_from_first_working_url" # noqa ) as mock_retrieve_amendement: mock_fetch_discussion_list.return_value = ANDerouleurData( lecture_an, { "amdtsParOrdreDeDiscussion": { "amendements": { "amendement": [ { "@numero": "6", "@discussionCommune": "", "@discussionIdentique": "", "@position": "1/3", }, { "@numero": "7", "@discussionCommune": "", "@discussionIdentique": "", "@position": "2/3", }, { "@numero": "9", "@discussionCommune": "", "@discussionIdentique": "", "@position": "3/3", }, ] } } }, ) mock_retrieve_amendement.side_effect = NotFound result = source_an.fetch(lecture_an) assert result.fetched == set() assert result.created == set() assert result.errored == {6, 7, 9} assert DBSession.query(Amendement).count() == len(amendements_an) == 2
def test_sous_amendements(self, app, source, dossier_plfss2018, texte_plfss2018_an_premiere_lecture): from zam_repondeur.models import DBSession, Lecture with transaction.manager: texte_plfss2018_an_premiere_lecture.numero = 911 lecture = Lecture.create( chambre="an", session="15", texte=texte_plfss2018_an_premiere_lecture, titre="Titre lecture", organe="PO717460", dossier=dossier_plfss2018, ) DBSession.add(lecture) with setup_mock_responses( lecture=lecture, liste=read_sample_data("an/911/liste.xml"), amendements=( ("1", read_sample_data("an/911/1.xml")), ("2", read_sample_data("an/911/2.xml")), ("3", read_sample_data("an/911/3.xml")), ), ): amendements, created, errored = source.fetch(lecture=lecture) assert len(amendements) == 3 assert amendements[0].num == 1 assert amendements[0].position == 1 assert amendements[0].id_discussion_commune == 3448 assert amendements[0].id_identique == 8496 assert amendements[1].num == 2 assert amendements[1].position == 2 assert amendements[1].id_discussion_commune is None assert amendements[1].id_identique is None assert amendements[2].num == 3 assert amendements[2].position == 3 assert amendements[2].id_discussion_commune is None assert amendements[1].id_identique is None for amendement in amendements[1:]: assert amendement.parent is amendements[0] assert amendement.parent_pk == amendements[0].pk assert created == 3 assert errored == []
def test_aspire_senat_plf2019_1re_partie(app, texte_senat, dossier_plf): from zam_repondeur.fetch.senat.amendements import Senat from zam_repondeur.models import DBSession, Lecture with transaction.manager: texte_senat.numero = 146 lecture = Lecture.create( chambre="senat", session="2018-2019", texte=texte_senat, partie=1, titre="Numéro lecture – Titre lecture sénat", organe="PO78718", dossier=dossier_plf, ) sample_data = read_sample_data("jeu_complet_2018-2019_146.csv") responses.add( responses.GET, "https://www.senat.fr/amendements/2018-2019/146/jeu_complet_2018-2019_146.csv", body=sample_data, status=200, ) odsen_data = read_sample_data("ODSEN_GENERAL.csv") responses.add( responses.GET, "https://data.senat.fr/data/senateurs/ODSEN_GENERAL.csv", body=odsen_data, status=200, ) json_data = json.loads(read_sample_data("liste_discussion_103393.json")) responses.add( responses.GET, "https://www.senat.fr/enseance/2018-2019/146/liste_discussion_103393.json", json=json_data, status=200, ) DBSession.add(lecture) source = Senat() amendements, created, errored = source.fetch(lecture) # All amendements from part 1 are fetched assert len(amendements) == 1005
def test_post_form_seance(app, dummy_lecture, dummy_amendements): from zam_repondeur.models import DBSession, Amendement with transaction.manager: dummy_lecture.num_texte = 575 dummy_lecture.titre = "Première lecture – Séance publique" amendement = dummy_amendements[0] amendement.num_texte = 575 amendement.subdiv_num = "2" # The objects are no longer bound to a session here, as they were created in a # previous transaction, so we add them to the current session to make sure that # our changes will be committed with the current transaction DBSession.add(dummy_lecture) DBSession.add(amendement) responses.add( responses.GET, "http://www.assemblee-nationale.fr/15/projets/pl0575.asp", status=404, ) responses.add( responses.GET, "http://www.assemblee-nationale.fr/15/projets/pl0575.asp", status=404, ) responses.add( responses.GET, "http://www.assemblee-nationale.fr/15/ta-commission/r0575-a0.asp", body=(Path(__file__).parent / "sample_data" / "r0575-a0.html").read_text("utf-8", "ignore"), status=200, ) form = app.get("/lectures/an.15.575.PO717460/").forms["retrieve-textes"] resp = form.submit() assert resp.status_code == 302 assert resp.location == "http://localhost/lectures/an.15.575.PO717460/" resp = resp.follow() assert resp.status_code == 200 assert "Articles récupérés" in resp.text amendement = DBSession.query(Amendement).filter( Amendement.num == 666).first() assert amendement.subdiv_contenu["001"].startswith( "Le code des relations entre")
def test_abandoned_before_seance(lecture_senat): """ An amendement that is either withdrawn by its author or declared invalid will be removed from the "liste_discussion" """ from zam_repondeur.fetch.senat.amendements import Senat from zam_repondeur.models import DBSession responses.add( responses.GET, "https://www.senat.fr/amendements/2017-2018/63/jeu_complet_2017-2018_63.csv", body=read_sample_data("jeu_complet_2017-2018_63-short.csv"), status=200, ) responses.add( responses.GET, "https://data.senat.fr/data/senateurs/ODSEN_GENERAL.csv", body=read_sample_data("ODSEN_GENERAL-short.csv"), status=200, ) responses.add( responses.GET, "https://www.senat.fr/enseance/2017-2018/63/liste_discussion.json", body=read_sample_data("liste_discussion_63-short.json"), status=200, ) responses.add( responses.GET, "https://www.senat.fr/enseance/2017-2018/63/liste_discussion.json", body=read_sample_data("liste_discussion_63-short-retire.json"), status=200, ) DBSession.add(lecture_senat) source = Senat() source.fetch(lecture_senat) assert {amdt.num: amdt.position for amdt in lecture_senat.amendements} == { 31: 1, 443: 2, } source.fetch(lecture_senat) assert {amdt.num: amdt.position for amdt in lecture_senat.amendements} == { 31: 1, 443: None, }
def test_post_amendement_edit_form_switch_table( app, lecture_an, amendements_an, user_david, user_david_table_an, user_ronan, user_ronan_table_an, ): from zam_repondeur.models import Amendement, DBSession amendement = amendements_an[1] with transaction.manager: DBSession.add(user_david_table_an) user_david_table_an.amendements.append(amendement) resp = app.get( "/lectures/an.15.269.PO717460/amendements/999/amendement_edit", user=user_david) form = resp.forms["edit-amendement"] form["avis"] = "Favorable" form["objet"] = "Un objet très pertinent" form["reponse"] = "Une réponse <strong>très</strong> appropriée" form["comments"] = "Avec des <table><tr><td>commentaires</td></tr></table>" # Table switch just before submitting the form. with transaction.manager: DBSession.add(user_ronan_table_an) user_ronan_table_an.amendements.append(amendement) resp = form.submit("save") assert resp.status_code == 302 assert ( resp.location == "https://zam.test/lectures/an.15.269.PO717460/tables/[email protected]/" ) resp = resp.maybe_follow() assert "Les modifications n’ont PAS été enregistrées" in resp.text assert "Il est actuellement sur la table de Ronan" in resp.text amendement = DBSession.query(Amendement).filter( Amendement.num == 999).one() assert amendement.user_content.avis is None assert amendement.user_content.objet is None assert amendement.user_content.reponse is None assert amendement.user_content.comments is None # Should NOT create events. assert len(amendement.events) == 0
def test_position_changed(lecture_senat): """ The discussion order of amendements may change """ from zam_repondeur.fetch.senat.amendements import Senat from zam_repondeur.models import DBSession responses.add( responses.GET, "https://www.senat.fr/amendements/2017-2018/63/jeu_complet_2017-2018_63.csv", body=read_sample_data("jeu_complet_2017-2018_63-short.csv"), status=200, ) responses.add( responses.GET, "https://data.senat.fr/data/senateurs/ODSEN_GENERAL.csv", body=read_sample_data("ODSEN_GENERAL-short.csv"), status=200, ) responses.add( responses.GET, "https://www.senat.fr/enseance/2017-2018/63/liste_discussion.json", body=read_sample_data("liste_discussion_63-short.json"), status=200, ) responses.add( responses.GET, "https://www.senat.fr/enseance/2017-2018/63/liste_discussion.json", body=read_sample_data("liste_discussion_63-short-position.json"), status=200, ) DBSession.add(lecture_senat) source = Senat() source.fetch(lecture_senat) assert {amdt.num: amdt.position for amdt in lecture_senat.amendements} == { 31: 1, 443: 2, } source.fetch(lecture_senat) assert {amdt.num: amdt.position for amdt in lecture_senat.amendements} == { 31: 2, 443: 1, }
def test_remove_parent_amendement(lecture_senat): """ The targeted article may change """ from zam_repondeur.fetch.senat.amendements import Senat from zam_repondeur.models import DBSession responses.add( responses.GET, "https://www.senat.fr/amendements/2017-2018/63/jeu_complet_2017-2018_63.csv", body=read_sample_data("jeu_complet_2017-2018_63-short.csv"), status=200, ) responses.add( responses.GET, "https://data.senat.fr/data/senateurs/ODSEN_GENERAL.csv", body=read_sample_data("ODSEN_GENERAL-short.csv"), status=200, ) responses.add( responses.GET, "https://www.senat.fr/enseance/2017-2018/63/liste_discussion.json", body=read_sample_data("liste_discussion_63-short-parent.json"), status=200, ) responses.add( responses.GET, "https://www.senat.fr/enseance/2017-2018/63/liste_discussion.json", body=read_sample_data("liste_discussion_63-short.json"), status=200, ) DBSession.add(lecture_senat) source = Senat() source.fetch(lecture_senat) assert { amdt.num: amdt.parent.num if amdt.parent else None for amdt in lecture_senat.amendements } == {31: None, 443: 31} source.fetch(lecture_senat) assert { amdt.num: amdt.parent.num if amdt.parent else None for amdt in lecture_senat.amendements } == {31: None, 443: None}
def test_team_member_can_access_owned_lecture( app, lecture_an, team_zam, user_david, amendements_an ): from zam_repondeur.models import DBSession with transaction.manager: lecture_an.owned_by_team = team_zam user_david.teams.append(team_zam) DBSession.add(team_zam) resp = app.get("/lectures/an.15.269.PO717460/amendements", user=user_david) assert resp.status_code == 200 assert "Dossier de banc" not in resp.text
def test_post_article_edit_form_title_redirect_next_with_apres( app, lecture_an, amendements_an, user_david): from zam_repondeur.models import Amendement, Article, DBSession with transaction.manager: article_1_apres = Article.create(lecture=lecture_an, type="article", num="1", pos="après") DBSession.add(article_1_apres) article_2 = Article.create(lecture=lecture_an, type="article", num="2") DBSession.add(article_2) DBSession.add(lecture_an) amendement = DBSession.query(Amendement).filter( Amendement.num == 999).one() assert amendement.article.user_content.title == "" resp = app.get( "/dossiers/plfss-2018/lectures/an.15.269.PO717460/articles/article.1../", user=user_david, ) form = resp.forms["edit-article"] form["title"] = "Titre article" resp = form.submit() assert resp.status_code == 302 assert resp.location == ( "https://zam.test" "/dossiers/plfss-2018/lectures/an.15.269.PO717460/articles/article.2../" ) amendement = DBSession.query(Amendement).filter( Amendement.num == 999).one() assert amendement.article.user_content.title == "Titre article"
def export_pdf(context: LectureResource, request: Request) -> Response: lecture = context.model( noload("amendements"), DOSSIER_OPTIONS, subqueryload("articles").options(joinedload("user_content")), ) nums, article_param = parse_params(request, lecture=lecture) if article_param == "all": article_amendements = ( DBSession.query(Amendement) .join(Article) .filter(Amendement.lecture == lecture,) .options(USER_CONTENT_OPTIONS, LOCATION_OPTIONS) ) else: article_type, article_num, article_mult, article_pos = article_param.split(".") article_amendements = ( DBSession.query(Amendement) .filter( Article.pk == Amendement.article_pk, Amendement.lecture == lecture, Article.type == article_type, Article.num == article_num, Article.mult == article_mult, Article.pos == article_pos, ) .options(USER_CONTENT_OPTIONS, LOCATION_OPTIONS,) ) amendements = [ amendement for amendement in article_amendements if amendement.num in nums ] expanded_amendements = list(Batch.expanded_batches(amendements)) with NamedTemporaryFile() as file_: tmp_file_path = os.path.abspath(file_.name) write_pdf_multiple( lecture=lecture, amendements=amendements, article_amendements=AmendementList(article_amendements), filename=tmp_file_path, request=request, ) return write_response( tmp_file_path=tmp_file_path, fmt="pdf", lecture=lecture, article_param=article_param, amendements=expanded_amendements, )
def dummy_lecture_commission(app): from zam_repondeur.models import DBSession, Lecture with transaction.manager: lecture = Lecture( chambre="an", session="15", num_texte=269, titre="Titre lecture", organe="PO420120", ) DBSession.add(lecture) return lecture
def test_visionneuse_articles(wsgi_server, driver, lecture_an_url, article7bis_an, amendements_an): from zam_repondeur.models import DBSession with transaction.manager: amendements_an[0].article = article7bis_an DBSession.add_all(amendements_an) driver.get(f"{lecture_an_url}/articles/") articles = driver.find_elements_by_css_selector("section.article") assert len(articles) == 2 assert articles[0].find_element_by_css_selector("h2").text == "Article 1" assert articles[1].find_element_by_css_selector( "h2").text == "Article 7 bis"
def test_export_excel_columns(lecture_an, article1_an, tmpdir): from openpyxl import load_workbook from zam_repondeur.export.spreadsheet import write_xlsx from zam_repondeur.models import DBSession, Amendement filename = str(tmpdir.join("test.xlsx")) amendement = Amendement.create( lecture=lecture_an, article=article1_an, num=333, position=1, avis="Favorable", objet="Un objet très pertinent", reponse="Une réponse très appropriée", comments="Avec des commentaires", ) DBSession.add(amendement) DBSession.add(lecture_an) counter = write_xlsx(lecture_an, filename, request={}) assert counter["amendements"] == 1 wb = load_workbook(filename, read_only=True) ws = wb.active header_row = next(ws.rows) headers = [cell.value for cell in header_row] assert headers == [ "Num article", "Titre article", "Num amdt", "Rectif", "Parent (sous-amdt)", "Auteur", "Groupe", "Gouvernemental", "Corps amdt", "Exposé amdt", "Identique", "Avis du Gouvernement", "Objet amdt", "Réponse", "Commentaires", "Affectation (email)", "Affectation (nom)", "Sort", ]
def test_reponses_menu(app, dummy_lecture, dummy_amendements): from zam_repondeur.models import DBSession with transaction.manager: for amendement in dummy_amendements: amendement.avis = "Favorable" amendement.observations = f"Observations pour {amendement.num}" amendement.reponse = f"Réponse pour {amendement.num}" DBSession.add_all(dummy_amendements) resp = app.get("http://localhost/lectures/an.15.269.PO717460/reponses") assert len(resp.parser.css(".menu a")) == 1 assert resp.parser.css_first(".menu a").text() == "Art. 1"
def test_amendement_batches(amendements_an): from zam_repondeur.models import Amendement, Batch, DBSession a, b = DBSession.query(Amendement).all() assert a.location.batch is None assert b.location.batch is None batch = Batch.create() a.location.batch = batch b.location.batch = batch a, b = DBSession.query(Amendement).all() assert a.location.batch == b.location.batch == batch
def test_get_amendements_with_gouvernemental( app, lecture_an, amendements_an, user_david ): from zam_repondeur.models import DBSession with transaction.manager: amendement = amendements_an[0] amendement.auteur = "LE GOUVERNEMENT" DBSession.add(amendement) resp = app.get("/lectures/an.15.269.PO717460/amendements", user=user_david) assert resp.status_code == 200 assert "Dossier de banc" in resp.text
def test_post_amendement_edit_form_and_transfer(app, lecture_an_url, amendements_an, user_david, user_david_table_an): from zam_repondeur.models import Amendement, DBSession amendement = amendements_an[1] with transaction.manager: DBSession.add(user_david_table_an) user_david_table_an.add_amendement(amendement) amendement = DBSession.query(Amendement).filter( Amendement.num == 999).one() assert amendement.user_content.avis is None assert amendement.user_content.objet is None assert amendement.user_content.reponse is None resp = app.get(f"{lecture_an_url}/amendements/999/", user=user_david) form = resp.forms["edit-amendement"] form["avis"] = "Favorable" form["objet"] = "Un objet très pertinent" form["reponse"] = "Une réponse <strong>très</strong> appropriée" form["comments"] = "Avec des <table><tr><td>commentaires</td></tr></table>" resp = form.submit("save-and-transfer") assert resp.status_code == 302 assert resp.location == ("https://zam.test" "/dossiers/plfss-2018" "/lectures/an.15.269.PO717460" "/transfer_amendements" "?n=999&from_save=1&" "back=https%3A%2F%2Fzam.test" "%2Fdossiers%2Fplfss-2018" "%2Flectures%2Fan.15.269.PO717460" "%2Ftables%2Fdavid%40exemple.gouv.fr" "%2F%23amdt-999") amendement = DBSession.query(Amendement).filter( Amendement.num == 999).one() assert amendement.user_content.avis == "Favorable" assert amendement.user_content.objet == "Un objet très pertinent" assert (amendement.user_content.reponse == "Une réponse <strong>très</strong> appropriée") assert ( amendement.user_content.comments == "Avec des <table><tbody><tr><td>commentaires</td></tr></tbody></table>" ) # Should create events. assert len(amendement.events) == 4
def test_amendement_unicity(amendements_an, article1av_an): from zam_repondeur.models import Amendement, DBSession existing = amendements_an[0] with transaction.manager, pytest.raises(IntegrityError) as error_info: Amendement.create( lecture=existing.lecture, num=existing.num, rectif=existing.rectif + 1, article=article1av_an, parent=None, objet="don't worry, this is an expected error", ) DBSession.flush() assert "constraint" in error_info.value._message()
def test_non_team_member_cannot_access_owned_lecture( app, lecture_an, team_zam, user_david, amendements_an ): from zam_repondeur.models import DBSession with transaction.manager: lecture_an.owned_by_team = team_zam DBSession.add(team_zam) resp = app.get("/lectures/an.15.269.PO717460/amendements", user=user_david) assert resp.status_code == 302 resp = resp.maybe_follow() assert "L’accès à cette lecture est réservé aux personnes autorisées." in resp.text