From 788ae04ebb4fc6576973c173c7e86452c69cf3b3 Mon Sep 17 00:00:00 2001 From: Coureau Date: Mon, 15 Jun 2026 08:27:44 +0200 Subject: [PATCH 01/11] =?UTF-8?q?Configuration=20de=20l'environnement=20de?= =?UTF-8?q?=20tests=20et=20mise=20=C3=A0=20jour=20des=20d=C3=A9pendances?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 - pytest.ini | 2 ++ requirements.txt | 15 +++++++++------ tests/__init__.py | 0 tests/conftest.py | 11 +++++++++++ tests/functional/__init__.py | 0 tests/integration/__init__.py | 0 tests/unit/__init__.py | 0 8 files changed, 22 insertions(+), 7 deletions(-) create mode 100644 pytest.ini create mode 100644 tests/__init__.py create mode 100644 tests/conftest.py create mode 100644 tests/functional/__init__.py create mode 100644 tests/integration/__init__.py create mode 100644 tests/unit/__init__.py diff --git a/.gitignore b/.gitignore index 2cba99d87..950060a15 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,5 @@ bin include lib .Python -tests/ .envrc __pycache__ \ No newline at end of file diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 000000000..de19c9f0b --- /dev/null +++ b/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +testpaths = tests \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 139affa05..8f10818fd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,9 @@ -click==7.1.2 -Flask==1.1.2 -itsdangerous==1.1.0 -Jinja2==2.11.2 -MarkupSafe==1.1.1 -Werkzeug==1.0.1 +click==8.1.7 +Flask==3.0.3 +itsdangerous==2.2.0 +Jinja2==3.1.4 +MarkupSafe==2.1.5 +Werkzeug==3.0.4 +pytest==8.3.3 +pytest-cov==5.0.0 +locust==2.31.6 \ No newline at end of file diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 000000000..570ed6d5b --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,11 @@ +import pytest + +import server + + +@pytest.fixture +def client(): + server.app.config['TESTING'] = True + with server.app.test_client() as client: + yield client + diff --git a/tests/functional/__init__.py b/tests/functional/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/integration/__init__.py b/tests/integration/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/unit/__init__.py b/tests/unit/__init__.py new file mode 100644 index 000000000..e69de29bb From c96a4032b3f4f784040897744f04df9d6953b887 Mon Sep 17 00:00:00 2001 From: Coureau Date: Tue, 16 Jun 2026 07:03:42 +0200 Subject: [PATCH 02/11] #1 : Gestion de l'email inconnu sans crash de l'application --- server.py | 8 ++++++-- templates/index.html | 9 +++++++++ tests/integration/test_login.py | 19 +++++++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 tests/integration/test_login.py diff --git a/server.py b/server.py index 4084baeac..2406bbfc5 100644 --- a/server.py +++ b/server.py @@ -26,8 +26,12 @@ def index(): @app.route('/showSummary',methods=['POST']) def showSummary(): - club = [club for club in clubs if club['email'] == request.form['email']][0] - return render_template('welcome.html',club=club,competitions=competitions) + matching_clubs = [c for c in clubs if c['email'] == request.form['email']] + if not matching_clubs: + flash("Sorry, that email was not found.") + return redirect(url_for('index')) + club = matching_clubs[0] + return render_template('welcome.html', club=club, competitions=competitions) @app.route('/book//') diff --git a/templates/index.html b/templates/index.html index 926526b7d..ecfe61c61 100644 --- a/templates/index.html +++ b/templates/index.html @@ -5,6 +5,15 @@ GUDLFT Registration + {% with messages = get_flashed_messages() %} + {% if messages %} +
    + {% for message in messages %} +
  • {{ message }}
  • + {% endfor %} +
+ {% endif %} + {% endwith %}

Welcome to the GUDLFT Registration Portal!

Please enter your secretary email to continue:
diff --git a/tests/integration/test_login.py b/tests/integration/test_login.py new file mode 100644 index 000000000..c7cc014af --- /dev/null +++ b/tests/integration/test_login.py @@ -0,0 +1,19 @@ +def test_login_with_valid_email_shows_summary(client): + """Happy path : un email connu doit afficher la page de résumé.""" + response = client.post( + "/showSummary", + data={"email": "john@simplylift.co"}, + ) + assert response.status_code == 200 + assert b"john@simplylift.co" in response.data + + +def test_login_with_unknown_email_does_not_crash(client): + """Sad path (bug #1) : un email inconnu ne doit pas faire planter l'appli.""" + response = client.post( + "/showSummary", + data={"email": "inconnu@test.com"}, + follow_redirects=True, + ) + assert response.status_code == 200 + assert b"Sorry, that email was not found." in response.data \ No newline at end of file From ae2939655ad07a3448c6e5c64580e67bdb41f9b3 Mon Sep 17 00:00:00 2001 From: Coureau Date: Wed, 24 Jun 2026 09:43:26 +0400 Subject: [PATCH 03/11] Ignorer les fichiers .DS_Store de macOS --- .DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 04a508e6f6048834346c5f1769770f2ff01806e6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHLyGjE=6uo02t_eaKAz-uO517KrW(_MA7J@PZnPF^o|@7E?}H@}hH>zFF|IYk+&(>@&}^;MVR8B@>u%kBB|j?|;;!fwo; zo=xxx7mLyiv%#By`qZRWl9&8+hRJ`mar)?NOa7sCOdaF15_(t-pML;FbyJ6!KU;}s zO#X0l^^;%MnY`&)lTU29%r{F%c%p~6LIPYLe0*qf<4f<4&N6je-xM$B)O9gpJyX-< zOj94xGV7aGn$QpFT6jp#ntB%7gTb4+E{u9p$LNeCe~tP7YGBXiaPkUmZym4>SO>lw z;OB#j#^`B`6v{^jI{69!%wkvuj^!Q=ba?>iX^a$N1R+!@P?ZY(iXl`v#$BD~X^a%A zauSjm>u6@7-%x~P$G9ugNq7ovZym4>Bpt}8j|JZU*T=vACyVSS>wtCOUpXMMe#I~2 zl=R-3Iyv5JU9=h+2j@i!WeGaH9m@mWiur#98JKhV0O)Cq6k-Hne+Wn$Y-b(#Q3pN% DK3B}k From e63477955192176af287d47cebb3063db70dff79 Mon Sep 17 00:00:00 2001 From: Coureau Date: Fri, 26 Jun 2026 12:18:11 +0400 Subject: [PATCH 04/11] =?UTF-8?q?#6=20:=20D=C3=A9duction=20=20des=20points?= =?UTF-8?q?=20du=20cub=20lors=20d'une=20r=C3=A9servation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server.py | 1 + tests/integration/test_purchase.py | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 tests/integration/test_purchase.py diff --git a/server.py b/server.py index 2406bbfc5..a58f8b437 100644 --- a/server.py +++ b/server.py @@ -51,6 +51,7 @@ def purchasePlaces(): club = [c for c in clubs if c['name'] == request.form['club']][0] placesRequired = int(request.form['places']) competition['numberOfPlaces'] = int(competition['numberOfPlaces'])-placesRequired + club['points'] = int(club['points']) - placesRequired flash('Great-booking complete!') return render_template('welcome.html', club=club, competitions=competitions) diff --git a/tests/integration/test_purchase.py b/tests/integration/test_purchase.py new file mode 100644 index 000000000..39748596c --- /dev/null +++ b/tests/integration/test_purchase.py @@ -0,0 +1,25 @@ +import server + + +def test_purchase_deducts_points_from_club(client): + """Bug #6 : les points utilises doivent etre deduits du solde du club.""" + # On choisit un club et une competition connus + club = next(c for c in server.clubs if c['name'] == "Simply Lift") + competition = next( + c for c in server.competitions if c['name'] == "Spring Festival" + ) + + points_avant = int(club['points']) + places_reservees = 3 + + client.post( + "/purchasePlaces", + data={ + "competition": competition['name'], + "club": club['name'], + "places": str(places_reservees), + }, + ) + + points_apres = int(club['points']) + assert points_apres == points_avant - places_reservees \ No newline at end of file From 0930056cb00cd303c662c47418c416457c7c6310 Mon Sep 17 00:00:00 2001 From: Coureau Date: Thu, 20 Aug 2026 11:40:48 +0200 Subject: [PATCH 05/11] =?UTF-8?q?#2=20:=20Blocage=20des=20r=C3=A9servation?= =?UTF-8?q?s=20d=C3=A9passant=20les=20points=20du=20clubs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 7 ++++++- server.py | 5 +++++ tests/integration/test_purchase.py | 27 ++++++++++++++++++++++++++- 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 950060a15..23264e70d 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,9 @@ include lib .Python .envrc -__pycache__ \ No newline at end of file +__pycache__.DS_Store +env/ +__pycache__/ +*.pyc +.DS_Store +.pytest_cache/ \ No newline at end of file diff --git a/server.py b/server.py index a58f8b437..1e874403b 100644 --- a/server.py +++ b/server.py @@ -50,6 +50,11 @@ def purchasePlaces(): competition = [c for c in competitions if c['name'] == request.form['competition']][0] club = [c for c in clubs if c['name'] == request.form['club']][0] placesRequired = int(request.form['places']) + + if placesRequired > int(club['points']): + flash("You do not have enough points to book that many places.") + return render_template('welcome.html', club=club, competitions=competitions) + competition['numberOfPlaces'] = int(competition['numberOfPlaces'])-placesRequired club['points'] = int(club['points']) - placesRequired flash('Great-booking complete!') diff --git a/tests/integration/test_purchase.py b/tests/integration/test_purchase.py index 39748596c..6923ffe0a 100644 --- a/tests/integration/test_purchase.py +++ b/tests/integration/test_purchase.py @@ -22,4 +22,29 @@ def test_purchase_deducts_points_from_club(client): ) points_apres = int(club['points']) - assert points_apres == points_avant - places_reservees \ No newline at end of file + assert points_apres == points_avant - places_reservees + +def test_purchase_more_than_points_is_blocked(client): + """Bug #2 : un club ne peut pas reserver plus de places qu'il n'a de points.""" + club = next(c for c in server.clubs if c['name'] == "Iron Temple") # 4 points + competition = next( + c for c in server.competitions if c['name'] == "Spring Festival" + ) + + points_avant = int(club['points']) + places_demandees = points_avant + 5 # plus que le solde : impossible + + response = client.post( + "/purchasePlaces", + data={ + "competition": competition['name'], + "club": club['name'], + "places": str(places_demandees), + }, + follow_redirects=True, + ) + + # Les points ne doivent pas avoir changé (rien n'a ete reserve) + assert int(club['points']) == points_avant + # Et un message d'erreur doit apparaitre + assert b"do not have enough points" in response.data \ No newline at end of file From 9236c2886567cbc372a6105cb33a7304cd4c06b0 Mon Sep 17 00:00:00 2001 From: Coureau Date: Thu, 20 Aug 2026 12:16:48 +0200 Subject: [PATCH 06/11] =?UTF-8?q?Isolation=20des=20tests=20:=20restauratio?= =?UTF-8?q?n=20des=20donn=C3=A9es=20entre=20chaque=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/conftest.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index 570ed6d5b..cda79c157 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,5 +1,5 @@ import pytest - +import copy import server @@ -9,3 +9,10 @@ def client(): with server.app.test_client() as client: yield client +@pytest.fixture(autouse=True) +def reset_data(): + clubs_sauvegarde = copy.deepcopy(server.clubs) + competition_sauvegarde = copy.deepcopy(server.competitions) + yield + server.clubs[:] = clubs_sauvegarde + server.competitions[:] = competition_sauvegarde \ No newline at end of file From 30c93792efd98732a286537af65b17eee6edfd68 Mon Sep 17 00:00:00 2001 From: Coureau Date: Thu, 20 Aug 2026 14:03:51 +0200 Subject: [PATCH 07/11] #3 : Limite de 12 places de reservation par competition --- server.py | 6 ++++++ tests/integration/test_purchase.py | 32 ++++++++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/server.py b/server.py index 1e874403b..558f6b629 100644 --- a/server.py +++ b/server.py @@ -20,6 +20,8 @@ def loadCompetitions(): competitions = loadCompetitions() clubs = loadClubs() +MAX_PLACES_PER_COMPETITION = 12 + @app.route('/') def index(): return render_template('index.html') @@ -51,6 +53,10 @@ def purchasePlaces(): club = [c for c in clubs if c['name'] == request.form['club']][0] placesRequired = int(request.form['places']) + if placesRequired > MAX_PLACES_PER_COMPETITION: + flash("You cannot book more than 12 places per competition.") + return render_template('welcome.html', club=club, competitions=competitions) + if placesRequired > int(club['points']): flash("You do not have enough points to book that many places.") return render_template('welcome.html', club=club, competitions=competitions) diff --git a/tests/integration/test_purchase.py b/tests/integration/test_purchase.py index 6923ffe0a..9bef8eb83 100644 --- a/tests/integration/test_purchase.py +++ b/tests/integration/test_purchase.py @@ -46,5 +46,33 @@ def test_purchase_more_than_points_is_blocked(client): # Les points ne doivent pas avoir changé (rien n'a ete reserve) assert int(club['points']) == points_avant - # Et un message d'erreur doit apparaitre - assert b"do not have enough points" in response.data \ No newline at end of file + # Un message d'erreur doit apparaitre + assert b"do not have enough points" in response.data + +def test_purchase_more_than_12_places_is_blocked(client): + """Bug #3 : un club ne peut reserver plus de 12 places par competition""" + # On choisit un club et une competition connus + club = next(c for c in server.clubs if c['name'] == "Simply Lift") + competition = next( + c for c in server.competitions if c['name'] == "Spring Festival" + ) + + points_avant = int(club['points']) + places_demandees = 13 # au dessus de la limite de 12 + + response = client.post( + + "/purchasePlaces", + data={ + "competition": competition['name'], + "club": club['name'], + "places": str(places_demandees), + }, + follow_redirects=True, + ) + + # Rien ne doit avoir ete debite + assert int(club["points"]) == points_avant + # Un message erreur doit apparaitre + assert b"cannot book more than 12 places" in response.data + From eadbe800402565811a9a43699e3eb6926cf7c0b3 Mon Sep 17 00:00:00 2001 From: Coureau Date: Tue, 25 Aug 2026 15:07:34 +0200 Subject: [PATCH 08/11] Ignore les fichiers generes par le coverage --- .gitignore | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 23264e70d..140e8a34b 100644 --- a/.gitignore +++ b/.gitignore @@ -3,9 +3,10 @@ include lib .Python .envrc -__pycache__.DS_Store env/ __pycache__/ *.pyc .DS_Store -.pytest_cache/ \ No newline at end of file +.pytest_cache/ +htmlcov/ +.coverage \ No newline at end of file From 9e8115c9b4c9524713c62243e43759b4c98f5073 Mon Sep 17 00:00:00 2001 From: Coureau Date: Tue, 25 Aug 2026 15:42:06 +0200 Subject: [PATCH 09/11] Tests des performances locust (6 utilisateurs) --- tests/performance/locustfile.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 tests/performance/locustfile.py diff --git a/tests/performance/locustfile.py b/tests/performance/locustfile.py new file mode 100644 index 000000000..bc2427dc4 --- /dev/null +++ b/tests/performance/locustfile.py @@ -0,0 +1,32 @@ +from locust import HttpUser, task, between + +class ClubSecretary(HttpUser): + wait_time = between(1, 3) + + @task + def index(self): + self.client.get("/") + + @task + def show_summary(self): + self.client.post("/showSummary", data={"email": "john@simplylift.co"}) + + @task + def book(self): + self.client.get("/book/Spring Festival/Simply Lift") + + @task + def purchase_places(self): + self.client.post( + "/purchasePlaces", + data={ + "competition": "Spring Festival", + "club": "Simply Lift", + "places": "1", + }, + ) + + @task + def logout(self): + self.client.get("/logout") + \ No newline at end of file From fb8d096a8e9a1e084cb32576056e2ea3a8822f27 Mon Sep 17 00:00:00 2001 From: Coureau Date: Mon, 31 Aug 2026 15:32:32 +0200 Subject: [PATCH 10/11] #4 : Blocage de la surrerservation au dela des places disponibles --- server.py | 5 +++++ tests/integration/test_purchase.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/server.py b/server.py index 558f6b629..a095ee333 100644 --- a/server.py +++ b/server.py @@ -56,10 +56,15 @@ def purchasePlaces(): if placesRequired > MAX_PLACES_PER_COMPETITION: flash("You cannot book more than 12 places per competition.") return render_template('welcome.html', club=club, competitions=competitions) + + if placesRequired > int (competition['numberOfPlaces']): + flash("There are not enough places available in this competition") + return render_template('welcome.html', club=club, competitions=competitions) if placesRequired > int(club['points']): flash("You do not have enough points to book that many places.") return render_template('welcome.html', club=club, competitions=competitions) + competition['numberOfPlaces'] = int(competition['numberOfPlaces'])-placesRequired club['points'] = int(club['points']) - placesRequired diff --git a/tests/integration/test_purchase.py b/tests/integration/test_purchase.py index 9bef8eb83..22d01d8e1 100644 --- a/tests/integration/test_purchase.py +++ b/tests/integration/test_purchase.py @@ -76,3 +76,31 @@ def test_purchase_more_than_12_places_is_blocked(client): # Un message erreur doit apparaitre assert b"cannot book more than 12 places" in response.data +def test_purchase_more_than_available_places_is_blocked(client): + """Bug #4 : un club ne peut pas reserver plus de places qu'il n'en reste""" + club = next(c for c in server.clubs if c['name'] == "Simply Lift") + competition = next( + c for c in server.competitions if c['name'] == "Spring Festival" + ) + + # Force une competition presque pleine + competition['numberOfPlaces'] = "5" + + points_avant = int(club['points']) + places_demandees = 10 # Sous la limite de 12 mais plus que les 5 restants + + response = client.post( + "/purchasePlaces", + data={ + "competition": competition['name'], + "club": club['name'], + "places": str(places_demandees), + }, + follow_redirects=True, + ) + + # Rien ne doit avoir change + assert int(club['points']) == points_avant + assert int (competition['numberOfPlaces']) == 5 + # Un message d'erreur doit apparaitre + assert b"not enough places available" in response.data \ No newline at end of file From 1997ab474bf201a1694ec58d0f2d9ff432facbe7 Mon Sep 17 00:00:00 2001 From: Coureau Date: Tue, 1 Sep 2026 16:14:59 +0200 Subject: [PATCH 11/11] #5 : Blocage des reservations sur les competitions qui ont deja eu lieu --- server.py | 5 ++++ tests/integration/test_purchase.py | 42 ++++++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/server.py b/server.py index a095ee333..ed5e9a3d7 100644 --- a/server.py +++ b/server.py @@ -1,5 +1,6 @@ import json from flask import Flask,render_template,request,redirect,flash,url_for +from datetime import datetime def loadClubs(): @@ -60,6 +61,10 @@ def purchasePlaces(): if placesRequired > int (competition['numberOfPlaces']): flash("There are not enough places available in this competition") return render_template('welcome.html', club=club, competitions=competitions) + + if datetime.strptime(competition['date'], "%Y-%m-%d %H:%M:%S") < datetime.now(): + flash("You cannot book places for a past competition") + return render_template('welcome.html', club=club, competitions=competitions) if placesRequired > int(club['points']): flash("You do not have enough points to book that many places.") diff --git a/tests/integration/test_purchase.py b/tests/integration/test_purchase.py index 22d01d8e1..687997aac 100644 --- a/tests/integration/test_purchase.py +++ b/tests/integration/test_purchase.py @@ -1,4 +1,5 @@ import server +from datetime import datetime, timedelta def test_purchase_deducts_points_from_club(client): @@ -8,6 +9,8 @@ def test_purchase_deducts_points_from_club(client): competition = next( c for c in server.competitions if c['name'] == "Spring Festival" ) + # Competition futur (pour etre bloqu par le controle de date) + competition['date'] = (datetime.now() + timedelta(days=30)).strftime("%Y-%m-%d %H:%M:%S") points_avant = int(club['points']) places_reservees = 3 @@ -30,6 +33,8 @@ def test_purchase_more_than_points_is_blocked(client): competition = next( c for c in server.competitions if c['name'] == "Spring Festival" ) + # Competition futur (pour etre bloqu par le controle de date) + competition['date'] = (datetime.now() + timedelta(days=30)).strftime("%Y-%m-%d %H:%M:%S") points_avant = int(club['points']) places_demandees = points_avant + 5 # plus que le solde : impossible @@ -56,6 +61,8 @@ def test_purchase_more_than_12_places_is_blocked(client): competition = next( c for c in server.competitions if c['name'] == "Spring Festival" ) + # Competition futur (pour etre bloqu par le controle de date) + competition['date'] = (datetime.now() + timedelta(days=30)).strftime("%Y-%m-%d %H:%M:%S") points_avant = int(club['points']) places_demandees = 13 # au dessus de la limite de 12 @@ -82,7 +89,9 @@ def test_purchase_more_than_available_places_is_blocked(client): competition = next( c for c in server.competitions if c['name'] == "Spring Festival" ) - + # Competition futur (pour etre bloqu par le controle de date) + competition['date'] = (datetime.now() + timedelta(days=30)).strftime("%Y-%m-%d %H:%M:%S") + # Force une competition presque pleine competition['numberOfPlaces'] = "5" @@ -103,4 +112,33 @@ def test_purchase_more_than_available_places_is_blocked(client): assert int(club['points']) == points_avant assert int (competition['numberOfPlaces']) == 5 # Un message d'erreur doit apparaitre - assert b"not enough places available" in response.data \ No newline at end of file + assert b"not enough places available" in response.data + +def test_purchase_on_past_competition_is_blocked(client): + """#bug #5 : impossible de reserver des places sur une competition passee""" + club = next(c for c in server.clubs if c['name'] == "Simply Lift") + + # Fausse competition terminee, (injecter dans la donnée en memoire) + past_competition = { + "name": "Old Cup", + "date": (datetime.now() - timedelta(days=30)).strftime("%Y-%m-%d %H:%M:%S"), + "numberOfPlaces": "20", + } + server.competitions.append(past_competition) + + points_avant = int(club['points']) + + response = client.post( + "/purchasePlaces", + data={ + "competition" : "Old Cup", + "club": club['name'], + "places": "1", + }, + follow_redirects=True, + ) + + # Rien ne doit avoir ete debite + assert int(club['points']) == points_avant + # le message d'erreur + assert b"past competition" in response.data